{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "bar-workflow",
  "title": "BarWorkflow",
  "description": "Compact bold-brand create/edit workflow chrome with Exit, controlled previous and next step navigation, and a final Save or Submit action.",
  "type": "registry:ui",
  "meta": {
    "library": "@ds-mo/ui",
    "distribution": "npm",
    "storybook": "https://zainadeel.github.io/compomo/?path=/story/bar-workflow",
    "source": "src/wc/components/BarWorkflow/BarWorkflow.tsx",
    "intentStatus": "complete",
    "intent": {
      "audience": "general",
      "status": "stable",
      "summary": "Compact bold-brand create/edit workflow chrome with Exit, controlled previous and next step navigation, and a final Save or Submit action.",
      "useWhen": [
        "A create or edit flow needs persistent page-level Exit and step navigation.",
        "A single-step form needs the same compact workflow chrome and final Save or Submit action.",
        "Next or Submit must remain visible while the application owns validation and the current step."
      ],
      "avoidWhen": [
        "The header identifies a routed page, list, or detail view; use BarTitle instead.",
        "The steps must be visibly enumerated or expose progress; BarWorkflow uses steps only to resolve its navigation controls.",
        "The header belongs to a PanelTools drawer or fullscreen pane; use PanelToolHeader through PanelTools instead.",
        "The interaction is a local wizard inside page content rather than page-level workflow chrome."
      ],
      "alternatives": [
        {
          "when": "A routed page needs responsive title, section, Back, and page-action presentations.",
          "component": "component:ds-bar-title",
          "reason": "BarTitle owns page identity and capacity variants rather than workflow progression."
        },
        {
          "when": "The workflow belongs to a tool drawer or fullscreen tool pane.",
          "component": "component:ds-panel-tool-header",
          "reason": "PanelToolHeader owns tool-pane navigation and actions within PanelTools."
        }
      ],
      "commonlyComposedWith": [
        "component:ds-shell-page",
        "component:ds-mobile-header",
        "component:ds-button-filled",
        "component:ds-button-unfilled",
        "component:ds-text",
        "component:ds-tooltip"
      ],
      "patterns": [],
      "accessibility": [
        "Provide one concise workflow heading; BarWorkflow renders exactly one h1 and appends the controlled current-step count as heading · X/N only for multi-step workflows.",
        "Provide a workflow-specific Exit accessible name that describes the consequence or destination.",
        "Give every step a stable id and concise label even though step labels are not rendered as visible progress.",
        "Previous is omitted on the first step; it appears from step two onward. Next remains visible on intermediate steps and becomes the final labeled Check action on the last step.",
        "Use submitAction.type=submit inside a form so the final action preserves native submission semantics."
      ],
      "states": [
        "BarWorkflow always renders compact 48px bold-brand chrome; responsiveMode changes only the action geometry, never workflow state or hierarchy.",
        "An unrecognized value resolves navigation from the first step without mutating the controlled value.",
        "The first step omits Previous. Intermediate steps show Previous and Next. The last step replaces Next with the Check Save or Submit action.",
        "The default empty steps array is a single-step flow with the plain heading, no Previous control, and the final action visible. An explicit one-step array behaves the same way.",
        "isNextInactive blocks forward navigation while preserving the Next control; the target step's isInactive state also blocks entry.",
        "submitAction owns the final label, native button type, inactive state, and loading state."
      ],
      "responsiveBehavior": [
        "Desktop and tablet keep the established left-aligned identity and trailing actions.",
        "Mobile uses symmetric MobileHeader geometry with Exit leading, the title and step count centered, and Previous plus Next or Submit trailing.",
        "The heading truncates before Exit, Previous, and Next or Submit lose their complete hit targets.",
        "When slotted into ShellPage, BarWorkflow remains compact while ShellPage continues to provide sticky placement."
      ],
      "frameworkCaveats": {
        "customElements": [
          "Assign steps and submitAction as JavaScript properties and replace their identities when controlled state changes.",
          "Update value after dsStepChange, handle dsExit in the workflow owner, and use dsSubmit only when product behavior supplements native form submission."
        ],
        "react": [
          "Pass steps and submitAction directly to DsBarWorkflow and keep value controlled in the workflow route.",
          "Place DsBarWorkflow in DsShellPage with slot=header when sticky page placement is required."
        ],
        "angular": [
          "Bind steps and submitAction on the standalone DsBarWorkflow adapter and update value from dsStepChange.",
          "Place ds-bar-workflow in ds-shell-page with slot=header and keep the form or router outlet in ShellPage content."
        ]
      },
      "references": [
        {
          "label": "Workflow states and controlled navigation",
          "path": "src/wc/components/BarWorkflow/BarWorkflow.stories.ts"
        },
        {
          "label": "Cross-browser workflow behavior",
          "path": "tests/e2e/bar-workflow.spec.ts"
        }
      ]
    },
    "api": {
      "props": {
        "exitAriaLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "exit-aria-label",
          "default": "'Exit workflow'",
          "required": false,
          "mutable": false,
          "description": "Workflow-specific accessible name for Exit."
        },
        "exitLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "exit-label",
          "default": "'Exit'",
          "required": false,
          "mutable": false,
          "description": "Concise tooltip label for the Exit control."
        },
        "heading": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "heading",
          "required": true,
          "mutable": false,
          "description": "The workflow's single visible h1."
        },
        "isNextInactive": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "is-next-inactive",
          "default": "false",
          "required": false,
          "mutable": false,
          "description": "Prevent advancing while the current step is incomplete or invalid."
        },
        "nextLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "next-label",
          "default": "'Next step'",
          "required": false,
          "mutable": false,
          "description": "Tooltip and accessible name for the next-step control."
        },
        "previousLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "previous-label",
          "default": "'Previous step'",
          "required": false,
          "mutable": false,
          "description": "Tooltip and accessible name for the previous-step control."
        },
        "responsiveMode": {
          "type": "ShellResponsiveMode",
          "resolvedType": "\"desktop\" | \"mobile\" | \"tablet\"",
          "attribute": "responsive-mode",
          "default": "'desktop'",
          "required": false,
          "mutable": false,
          "description": "Explicit shell breakpoint presentation. Mobile keeps the same controlled workflow state."
        },
        "steps": {
          "type": "BarWorkflowStep[]",
          "resolvedType": "BarWorkflowStep[]",
          "default": "[]",
          "required": false,
          "mutable": false,
          "description": "Ordered workflow steps. Step state is controlled by the application."
        },
        "submitAction": {
          "type": "BarWorkflowSubmitAction",
          "resolvedType": "BarWorkflowSubmitAction",
          "default": "{\n    label: 'Save',\n    type: 'submit',\n  }",
          "required": false,
          "mutable": false,
          "description": "The final-step Save or Submit action."
        },
        "value": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "value",
          "default": "''",
          "required": false,
          "mutable": false,
          "description": "Id of the current workflow step. Falls back to the first step."
        }
      },
      "events": [
        {
          "name": "dsExit",
          "detail": "MouseEvent",
          "bubbles": true,
          "cancelable": true,
          "composed": true,
          "description": "Emitted when Exit is activated."
        },
        {
          "name": "dsStepChange",
          "detail": "string",
          "bubbles": true,
          "cancelable": true,
          "composed": true,
          "description": "Emitted with the target previous or next step id. The component never mutates value."
        },
        {
          "name": "dsSubmit",
          "detail": "MouseEvent",
          "bubbles": true,
          "cancelable": true,
          "composed": true,
          "description": "Emitted when the final Save or Submit control is activated."
        }
      ],
      "methods": [],
      "slots": []
    },
    "props": {
      "exitAriaLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "exit-aria-label",
        "default": "'Exit workflow'",
        "required": false,
        "mutable": false,
        "description": "Workflow-specific accessible name for Exit."
      },
      "exitLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "exit-label",
        "default": "'Exit'",
        "required": false,
        "mutable": false,
        "description": "Concise tooltip label for the Exit control."
      },
      "heading": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "heading",
        "required": true,
        "mutable": false,
        "description": "The workflow's single visible h1."
      },
      "isNextInactive": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "is-next-inactive",
        "default": "false",
        "required": false,
        "mutable": false,
        "description": "Prevent advancing while the current step is incomplete or invalid."
      },
      "nextLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "next-label",
        "default": "'Next step'",
        "required": false,
        "mutable": false,
        "description": "Tooltip and accessible name for the next-step control."
      },
      "previousLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "previous-label",
        "default": "'Previous step'",
        "required": false,
        "mutable": false,
        "description": "Tooltip and accessible name for the previous-step control."
      },
      "responsiveMode": {
        "type": "ShellResponsiveMode",
        "resolvedType": "\"desktop\" | \"mobile\" | \"tablet\"",
        "attribute": "responsive-mode",
        "default": "'desktop'",
        "required": false,
        "mutable": false,
        "description": "Explicit shell breakpoint presentation. Mobile keeps the same controlled workflow state."
      },
      "steps": {
        "type": "BarWorkflowStep[]",
        "resolvedType": "BarWorkflowStep[]",
        "default": "[]",
        "required": false,
        "mutable": false,
        "description": "Ordered workflow steps. Step state is controlled by the application."
      },
      "submitAction": {
        "type": "BarWorkflowSubmitAction",
        "resolvedType": "BarWorkflowSubmitAction",
        "default": "{\n    label: 'Save',\n    type: 'submit',\n  }",
        "required": false,
        "mutable": false,
        "description": "The final-step Save or Submit action."
      },
      "value": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "value",
        "default": "''",
        "required": false,
        "mutable": false,
        "description": "Id of the current workflow step. Falls back to the first step."
      }
    },
    "events": [
      {
        "name": "dsExit",
        "detail": "MouseEvent",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "description": "Emitted when Exit is activated."
      },
      {
        "name": "dsStepChange",
        "detail": "string",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "description": "Emitted with the target previous or next step id. The component never mutates value."
      },
      {
        "name": "dsSubmit",
        "detail": "MouseEvent",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "description": "Emitted when the final Save or Submit control is activated."
      }
    ],
    "methods": [],
    "slots": [],
    "exports": {
      "customElement": "ds-bar-workflow",
      "react": "DsBarWorkflow",
      "vue": "DsBarWorkflow",
      "angular": "DsBarWorkflow"
    },
    "consumption": {
      "install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
      "cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
      "customElements": {
        "import": "import '@ds-mo/ui/dist/components/ds-bar-workflow.js';",
        "example": "<ds-bar-workflow></ds-bar-workflow>"
      },
      "react": {
        "import": "import { DsBarWorkflow } from '@ds-mo/ui/react';",
        "example": "<DsBarWorkflow />"
      },
      "vue": {
        "import": "import { DsBarWorkflow } from '@ds-mo/ui/vue';",
        "example": "<DsBarWorkflow />"
      },
      "angular": {
        "import": "import { DsBarWorkflow } from '@ds-mo/ui/angular/ds-bar-workflow';",
        "example": "<ds-bar-workflow></ds-bar-workflow>"
      },
      "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: steps, submitAction.",
      "peerDependencies": {
        "required": [
          "@ds-mo/tokens ^6.5.0",
          "@ds-mo/icons ^7.0.0"
        ],
        "frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
      }
    }
  },
  "dependencies": [
    "@ds-mo/ui",
    "@ds-mo/tokens"
  ],
  "registryDependencies": [
    "button-filled",
    "button-unfilled",
    "mobile-header",
    "text",
    "tooltip"
  ],
  "files": [
    {
      "path": "src/wc/components/BarWorkflow/BarWorkflow.css",
      "content": "@import '../../utils/control-density.css';\n@import '../../utils/chrome-layout.css';\n\n:host {\n  display: block;\n  min-width: 0;\n  box-sizing: border-box;\n  background: var(--color-background-bold-brand);\n}\n\n.bar-workflow {\n  justify-content: space-between;\n  height: var(--dimension-size-600);\n  min-width: 0;\n  background: var(--color-background-bold-brand);\n}\n\n.bar-workflow__identity {\n  display: flex;\n  flex: 1 1 auto;\n  align-items: center;\n  gap: var(--dimension-space-050);\n  height: var(--dimension-size-400);\n  min-width: 0;\n}\n\n.bar-workflow__heading {\n  display: inline-flex;\n  flex: 1 1 auto;\n  align-items: center;\n  width: auto;\n  min-width: 0;\n  height: var(--dimension-size-400);\n  padding-inline: calc(var(--ds-control-padding-inline) + var(--ds-control-label-inset));\n  box-sizing: border-box;\n  user-select: none;\n}\n\n.bar-workflow__actions {\n  display: flex;\n  flex: 0 0 auto;\n  align-items: center;\n  gap: var(--dimension-space-100);\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "src/wc/components/BarWorkflow/BarWorkflow.tsx",
      "content": "import { Component, Event, EventEmitter, h, Host, Prop } from '@stencil/core';\nimport type { ShellResponsiveMode } from '../../shell/shell-responsive';\nimport type { BarWorkflowStep, BarWorkflowSubmitAction } from './bar-workflow-types';\n\n@Component({\n  tag: 'ds-bar-workflow',\n  styleUrl: 'BarWorkflow.css',\n  scoped: true,\n})\nexport class BarWorkflow {\n  /** The workflow's single visible h1. */\n  @Prop() heading!: string;\n\n  /** Ordered workflow steps. Step state is controlled by the application. */\n  @Prop() steps: BarWorkflowStep[] = [];\n\n  /** Id of the current workflow step. Falls back to the first step. */\n  @Prop() value: string = '';\n\n  /** Concise tooltip label for the Exit control. */\n  @Prop() exitLabel: string = 'Exit';\n\n  /** Workflow-specific accessible name for Exit. */\n  @Prop() exitAriaLabel: string = 'Exit workflow';\n\n  /** Tooltip and accessible name for the previous-step control. */\n  @Prop() previousLabel: string = 'Previous step';\n\n  /** Tooltip and accessible name for the next-step control. */\n  @Prop() nextLabel: string = 'Next step';\n\n  /** The final-step Save or Submit action. */\n  @Prop() submitAction: BarWorkflowSubmitAction = {\n    label: 'Save',\n    type: 'submit',\n  };\n\n  /** Prevent advancing while the current step is incomplete or invalid. */\n  @Prop() isNextInactive: boolean = false;\n\n  /** Explicit shell breakpoint presentation. Mobile keeps the same controlled workflow state. */\n  @Prop({ attribute: 'responsive-mode', reflect: true })\n  responsiveMode: ShellResponsiveMode = 'desktop';\n\n  /** Emitted when Exit is activated. */\n  @Event() dsExit!: EventEmitter<MouseEvent>;\n\n  /** Emitted with the target previous or next step id. The component never mutates value. */\n  @Event() dsStepChange!: EventEmitter<string>;\n\n  /** Emitted when the final Save or Submit control is activated. */\n  @Event() dsSubmit!: EventEmitter<MouseEvent>;\n\n  private get currentIndex(): number {\n    const index = this.steps.findIndex(step => step.id === this.value);\n    return index >= 0 ? index : 0;\n  }\n\n  private get previousStep(): BarWorkflowStep | null {\n    return this.steps[this.currentIndex - 1] ?? null;\n  }\n\n  private get nextStep(): BarWorkflowStep | null {\n    return this.steps[this.currentIndex + 1] ?? null;\n  }\n\n  private get isLastStep(): boolean {\n    return this.steps.length <= 1 || this.currentIndex === this.steps.length - 1;\n  }\n\n  private get resolvedHeading(): string {\n    if (this.steps.length <= 1) return this.heading;\n    return `${this.heading} · ${this.currentIndex + 1}/${this.steps.length}`;\n  }\n\n  private handlePrevious = () => {\n    if (this.previousStep && !this.previousStep.isInactive) {\n      this.dsStepChange.emit(this.previousStep.id);\n    }\n  };\n\n  private handleNext = () => {\n    if (this.nextStep && !this.isNextInactive && !this.nextStep.isInactive) {\n      this.dsStepChange.emit(this.nextStep.id);\n    }\n  };\n\n  private renderSubmit(slot?: 'trailing') {\n    const submit = this.submitAction;\n    return (\n      <ds-tooltip slot={slot} label={submit.label} side=\"bottom\" size=\"sm\">\n        <ds-button-filled\n          class=\"bar-workflow__submit\"\n          variant=\"icon\"\n          icon=\"Check\"\n          label={submit.label}\n          aria-label={submit.label}\n          intent=\"brand\"\n          contrast=\"faint\"\n          background=\"bold\"\n          size=\"md\"\n          type={submit.type ?? 'submit'}\n          isInactive={submit.isInactive}\n          isLoading={submit.isLoading}\n          onDsClick={(event: CustomEvent<MouseEvent>) => this.dsSubmit.emit(event.detail)}\n        />\n      </ds-tooltip>\n    );\n  }\n\n  private renderMobile() {\n    return (\n      <ds-mobile-header\n        class=\"bar-workflow__mobile\"\n        heading={this.resolvedHeading}\n        tone=\"brand\"\n      >\n        <ds-tooltip slot=\"leading\" label={this.exitLabel} side=\"bottom\" size=\"sm\">\n          <ds-button-unfilled\n            class=\"bar-workflow__exit\"\n            variant=\"icon\"\n            icon=\"Cross\"\n            aria-label={this.exitAriaLabel}\n            size=\"md\"\n            background=\"bold\"\n            activeFill={false}\n            hasBorder={false}\n            onDsClick={(event: CustomEvent<MouseEvent>) => this.dsExit.emit(event.detail)}\n          />\n        </ds-tooltip>\n\n        {this.previousStep ? (\n          <ds-tooltip slot=\"trailing\" label={this.previousLabel} side=\"bottom\" size=\"sm\">\n            <ds-button-unfilled\n              class=\"bar-workflow__previous\"\n              variant=\"icon\"\n              icon=\"ChevronLeft\"\n              aria-label={this.previousLabel}\n              size=\"md\"\n              background=\"bold\"\n              activeFill={false}\n              hasBorder={false}\n              isInactive={this.previousStep.isInactive}\n              onDsClick={this.handlePrevious}\n            />\n          </ds-tooltip>\n        ) : null}\n\n        {this.isLastStep ? (\n          this.renderSubmit('trailing')\n        ) : (\n          <ds-tooltip slot=\"trailing\" label={this.nextLabel} side=\"bottom\" size=\"sm\">\n            <ds-button-filled\n              class=\"bar-workflow__next\"\n              variant=\"icon\"\n              icon=\"ChevronRight\"\n              label={this.nextLabel}\n              aria-label={this.nextLabel}\n              intent=\"brand\"\n              contrast=\"faint\"\n              background=\"bold\"\n              size=\"md\"\n              type=\"button\"\n              isInactive={this.isNextInactive || this.nextStep?.isInactive}\n              onDsClick={this.handleNext}\n            />\n          </ds-tooltip>\n        )}\n      </ds-mobile-header>\n    );\n  }\n\n  private renderDesktop() {\n    return (\n      <div class=\"bar-workflow ds-chrome-row ds-chrome-space--md\">\n          <div class=\"bar-workflow__identity\">\n            <ds-tooltip label={this.exitLabel} side=\"bottom\" size=\"sm\">\n              <ds-button-unfilled\n                class=\"bar-workflow__exit\"\n                variant=\"icon\"\n                icon=\"Cross\"\n                aria-label={this.exitAriaLabel}\n                size=\"md\"\n                background=\"bold\"\n                activeFill={false}\n                hasBorder={false}\n                onDsClick={(event: CustomEvent<MouseEvent>) => this.dsExit.emit(event.detail)}\n              />\n            </ds-tooltip>\n            <ds-text\n              class=\"bar-workflow__heading ds-control--md\"\n              variant=\"text-title-small\"\n              emphasis\n              color=\"on-bold\"\n              as=\"h1\"\n              lineTruncation={1}\n            >\n              {this.resolvedHeading}\n            </ds-text>\n          </div>\n\n          <div class=\"bar-workflow__actions\">\n            {this.previousStep ? (\n              <ds-tooltip label={this.previousLabel} side=\"bottom\" size=\"sm\">\n                <ds-button-unfilled\n                  class=\"bar-workflow__previous\"\n                  variant=\"icon\"\n                  icon=\"ChevronLeft\"\n                  aria-label={this.previousLabel}\n                  size=\"md\"\n                  background=\"bold\"\n                  activeFill={false}\n                  hasBorder={false}\n                  isInactive={this.previousStep.isInactive}\n                  onDsClick={this.handlePrevious}\n                />\n              </ds-tooltip>\n            ) : null}\n\n            {this.isLastStep ? (\n              this.renderSubmit()\n            ) : (\n              <ds-tooltip label={this.nextLabel} side=\"bottom\" size=\"sm\">\n                <ds-button-filled\n                  class=\"bar-workflow__next\"\n                  variant=\"icon\"\n                  icon=\"ChevronRight\"\n                  label={this.nextLabel}\n                  aria-label={this.nextLabel}\n                  intent=\"brand\"\n                  contrast=\"faint\"\n                  background=\"bold\"\n                  size=\"md\"\n                  type=\"button\"\n                  isInactive={this.isNextInactive || this.nextStep?.isInactive}\n                  onDsClick={this.handleNext}\n                />\n              </ds-tooltip>\n            )}\n          </div>\n      </div>\n    );\n  }\n\n  render() {\n    return (\n      <Host>\n        {this.responsiveMode === 'mobile' ? this.renderMobile() : this.renderDesktop()}\n      </Host>\n    );\n  }\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "src/wc/components/BarWorkflow/bar-workflow-types.ts",
      "content": "export interface BarWorkflowStep {\n  id: string;\n  label: string;\n  isInactive?: boolean;\n}\n\nexport interface BarWorkflowSubmitAction {\n  label: string;\n  type?: 'button' | 'submit' | 'reset';\n  isInactive?: boolean;\n  isLoading?: boolean;\n}\n",
      "type": "registry:ui"
    }
  ]
}
