{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "mobile-sheet-nav",
  "title": "MobileSheetNav",
  "description": "Full-height mobile navigation sheet with a single brand, context, and utility header above large primary destinations.",
  "type": "registry:ui",
  "meta": {
    "library": "@ds-mo/ui",
    "distribution": "npm",
    "storybook": "https://zainadeel.github.io/compomo/?path=/story/mobile-sheet-nav",
    "source": "src/wc/components/MobileSheetNav/MobileSheetNav.tsx",
    "intentStatus": "complete",
    "intent": {
      "audience": "specialized",
      "status": "experimental",
      "summary": "Full-height mobile navigation sheet with a single brand, context, and utility header above large primary destinations.",
      "useWhen": [
        "The mobile ShellApp Menu control needs to expose the complete primary navigation collection."
      ],
      "avoidWhen": [
        "Rendering desktop PanelNav.",
        "Switching local page content."
      ],
      "commonlyComposedWith": [
        "component:ds-shell-app",
        "component:ds-mobile-bar-nav"
      ],
      "patterns": [
        "pattern:application-shell"
      ],
      "accessibility": [
        "The sheet is a named navigation landmark and retains visible labels for every primary destination.",
        "Dashboard and Settings use icon-only tabs with localized accessible names; Help and the optional Account shortcut use icon-only actions with matching tooltips.",
        "Escape requests dismissal and opening moves focus to the selected or first available area."
      ],
      "states": [
        "Dashboard and Settings change only the flat destination collection being browsed.",
        "Area, Help, and Account events express intent while the application owns navigation and product behavior.",
        "Set routeSelectionActive to false while a global tool owns the mobile stage so the underlying router URL remains available without marking its area current.",
        "Set showAccount to false when account and user preferences already live in the supplied Settings navigation."
      ],
      "responsiveBehavior": [
        "The pane fills the mobile content stage while the bottom bar remains available.",
        "The sheet header and scrollable navigation body each use the shared 8px chrome inset; the context TabGroup and primary controls share a 40px height and 24px icon scale.",
        "When the optional Account shortcut is hidden, the Dashboard and Settings TabGroup fills the centered two-thirds top-bar lane and gives both context options equal width.",
        "Dashboard and Settings preserve their supplied visual groups with an 8px gap between destinations inside a section and a 32px gap between sections."
      ],
      "references": [
        {
          "label": "Storybook",
          "path": "src/wc/components/MobileSheetNav/MobileSheetNav.stories.ts"
        }
      ]
    },
    "api": {
      "props": {
        "accountLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "account-label",
          "default": "'Account'",
          "required": false,
          "mutable": false
        },
        "browseContext": {
          "type": "NavChromeStyle",
          "resolvedType": "\"dashboard\" | \"settings\"",
          "attribute": "browse-context",
          "default": "'dashboard'",
          "required": false,
          "mutable": false
        },
        "currentUrl": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "current-url",
          "default": "''",
          "required": false,
          "mutable": false
        },
        "dashboardGroups": {
          "type": "PanelNavGroup[]",
          "resolvedType": "PanelNavGroup[]",
          "default": "[]",
          "required": false,
          "mutable": false
        },
        "dashboardLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "dashboard-label",
          "default": "'Dashboard'",
          "required": false,
          "mutable": false
        },
        "helpLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "help-label",
          "default": "'Help & Support'",
          "required": false,
          "mutable": false
        },
        "navigationLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "navigation-label",
          "default": "'Application navigation'",
          "required": false,
          "mutable": false
        },
        "open": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "open",
          "default": "false",
          "required": false,
          "mutable": false
        },
        "routeSelectionActive": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "route-selection-active",
          "default": "true",
          "required": false,
          "mutable": false,
          "description": "Whether the router-derived current area owns the active mobile stage."
        },
        "settingsGroups": {
          "type": "PanelNavGroup[]",
          "resolvedType": "PanelNavGroup[]",
          "default": "[]",
          "required": false,
          "mutable": false
        },
        "settingsLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "settings-label",
          "default": "'Settings'",
          "required": false,
          "mutable": false
        },
        "showAccount": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "show-account",
          "default": "true",
          "required": false,
          "mutable": false,
          "description": "Show the optional Account shortcut in the sheet header."
        }
      },
      "events": [
        {
          "name": "dsAreaSelect",
          "detail": "string",
          "bubbles": true,
          "cancelable": true,
          "composed": true
        },
        {
          "name": "dsBrowseContextChange",
          "detail": "NavChromeStyle",
          "bubbles": true,
          "cancelable": true,
          "composed": true
        },
        {
          "name": "dsClose",
          "detail": "void",
          "bubbles": true,
          "cancelable": true,
          "composed": true
        }
      ],
      "methods": [],
      "slots": []
    },
    "props": {
      "accountLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "account-label",
        "default": "'Account'",
        "required": false,
        "mutable": false
      },
      "browseContext": {
        "type": "NavChromeStyle",
        "resolvedType": "\"dashboard\" | \"settings\"",
        "attribute": "browse-context",
        "default": "'dashboard'",
        "required": false,
        "mutable": false
      },
      "currentUrl": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "current-url",
        "default": "''",
        "required": false,
        "mutable": false
      },
      "dashboardGroups": {
        "type": "PanelNavGroup[]",
        "resolvedType": "PanelNavGroup[]",
        "default": "[]",
        "required": false,
        "mutable": false
      },
      "dashboardLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "dashboard-label",
        "default": "'Dashboard'",
        "required": false,
        "mutable": false
      },
      "helpLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "help-label",
        "default": "'Help & Support'",
        "required": false,
        "mutable": false
      },
      "navigationLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "navigation-label",
        "default": "'Application navigation'",
        "required": false,
        "mutable": false
      },
      "open": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "open",
        "default": "false",
        "required": false,
        "mutable": false
      },
      "routeSelectionActive": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "route-selection-active",
        "default": "true",
        "required": false,
        "mutable": false,
        "description": "Whether the router-derived current area owns the active mobile stage."
      },
      "settingsGroups": {
        "type": "PanelNavGroup[]",
        "resolvedType": "PanelNavGroup[]",
        "default": "[]",
        "required": false,
        "mutable": false
      },
      "settingsLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "settings-label",
        "default": "'Settings'",
        "required": false,
        "mutable": false
      },
      "showAccount": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "show-account",
        "default": "true",
        "required": false,
        "mutable": false,
        "description": "Show the optional Account shortcut in the sheet header."
      }
    },
    "events": [
      {
        "name": "dsAreaSelect",
        "detail": "string",
        "bubbles": true,
        "cancelable": true,
        "composed": true
      },
      {
        "name": "dsBrowseContextChange",
        "detail": "NavChromeStyle",
        "bubbles": true,
        "cancelable": true,
        "composed": true
      },
      {
        "name": "dsClose",
        "detail": "void",
        "bubbles": true,
        "cancelable": true,
        "composed": true
      }
    ],
    "methods": [],
    "slots": [],
    "exports": {
      "customElement": "ds-mobile-sheet-nav",
      "react": "DsMobileSheetNav",
      "vue": "DsMobileSheetNav",
      "angular": "DsMobileSheetNav"
    },
    "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-mobile-sheet-nav.js';",
        "example": "<ds-mobile-sheet-nav></ds-mobile-sheet-nav>"
      },
      "react": {
        "import": "import { DsMobileSheetNav } from '@ds-mo/ui/react';",
        "example": "<DsMobileSheetNav />"
      },
      "vue": {
        "import": "import { DsMobileSheetNav } from '@ds-mo/ui/vue';",
        "example": "<DsMobileSheetNav />"
      },
      "angular": {
        "import": "import { DsMobileSheetNav } from '@ds-mo/ui/angular/ds-mobile-sheet-nav';",
        "example": "<ds-mobile-sheet-nav></ds-mobile-sheet-nav>"
      },
      "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: dashboardGroups, settingsGroups.",
      "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",
    "@ds-mo/icons"
  ],
  "registryDependencies": [
    "badge",
    "button-unfilled",
    "icon",
    "tab-group",
    "text",
    "tooltip"
  ],
  "files": [
    {
      "path": "src/wc/components/MobileSheetNav/MobileSheetNav.css",
      "content": "@import '../../utils/control-density.css';\n@import '../../utils/chrome-layout.css';\n@import '../../utils/focus-ring.css';\n@import '../../utils/interaction-fill.css';\n\n:host {\n  display: block;\n  min-width: 0;\n  min-height: 0;\n  height: 100%;\n  background: var(--color-background-primary);\n}\n\n:host(:not([open])) {\n  display: none;\n}\n\n.mobile-sheet-nav {\n  display: grid;\n  grid-template-rows: auto minmax(0, 1fr);\n  height: 100%;\n  min-height: 0;\n  background: var(--color-background-primary);\n}\n\n.mobile-sheet-nav__header {\n  position: relative;\n  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);\n}\n\n.mobile-sheet-nav__header--expanded-context {\n  grid-template-columns:\n    minmax(var(--dimension-size-500), 1fr)\n    minmax(0, 4fr)\n    minmax(var(--dimension-size-500), 1fr);\n}\n\n.mobile-sheet-nav__header--expanded-context .mobile-sheet-nav__context {\n  width: 100%;\n}\n\n.mobile-sheet-nav__header::after {\n  content: '';\n  position: absolute;\n  inset-inline: 0;\n  inset-block-end: 0;\n  height: var(--dimension-stroke-width-012);\n  background: var(--color-border-tertiary);\n  pointer-events: none;\n}\n\n.mobile-sheet-nav__brand {\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n  min-width: 0;\n}\n\n.mobile-sheet-nav__logo {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: var(--dimension-size-500);\n  height: var(--dimension-size-500);\n  padding: var(--dimension-space-100);\n  box-sizing: border-box;\n  color: var(--color-foreground-primary);\n}\n\n.mobile-sheet-nav__logo-mark {\n  width: var(--dimension-iconography-lg);\n  height: var(--dimension-iconography-lg);\n  flex: 0 0 auto;\n}\n\n.mobile-sheet-nav__context {\n  justify-self: center;\n}\n\n.mobile-sheet-nav__actions {\n  display: flex;\n  align-items: center;\n  justify-content: flex-end;\n  gap: var(--dimension-space-050);\n  min-width: 0;\n}\n\n.mobile-sheet-nav__body {\n  min-height: 0;\n  overflow: auto;\n  overscroll-behavior: contain;\n}\n\n.mobile-sheet-nav__sections {\n  display: grid;\n  gap: var(--dimension-space-400);\n}\n\n.mobile-sheet-nav__items {\n  display: grid;\n  gap: var(--dimension-space-100);\n}\n\n.mobile-sheet-nav__item {\n  appearance: none;\n  width: 100%;\n  height: var(--ds-control-height);\n  min-height: var(--ds-control-height);\n  padding-inline: var(--ds-control-padding-inline);\n  border: 0;\n  border-radius: var(--ds-control-radius);\n  background: transparent;\n  color: var(--color-foreground-secondary);\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n  gap: var(--ds-control-gap);\n  cursor: default;\n  text-align: start;\n  box-sizing: border-box;\n}\n\n.mobile-sheet-nav__item--selected {\n  color: var(--color-foreground-primary);\n}\n\n.mobile-sheet-nav__item-label {\n  min-width: 0;\n  padding-inline: var(--ds-control-label-inset);\n}\n\n.mobile-sheet-nav__dot {\n  margin-inline-start: auto;\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "src/wc/components/MobileSheetNav/MobileSheetNav.tsx",
      "content": "import {\n  Component,\n  Element,\n  Event,\n  EventEmitter,\n  h,\n  Host,\n  Listen,\n  Prop,\n  Watch,\n} from '@stencil/core';\nimport type { NavChromeStyle } from '../../shell/nav-chrome';\nimport { deriveActiveIdFromUrl } from '../PanelNav/panel-nav-utils';\nimport type { PanelNavGroup, PanelNavItem } from '../PanelNav/panel-nav-types';\n\ntype MobileSheetNavHeaderDestinationId = 'account' | 'help';\n\nconst CONTEXT_TABS = [\n  { id: 'dashboard', label: 'Dashboard', icon: 'Dashboard', variant: 'icon' as const },\n  { id: 'settings', label: 'Settings', icon: 'Gear', variant: 'icon' as const },\n];\n\n@Component({\n  tag: 'ds-mobile-sheet-nav',\n  styleUrl: 'MobileSheetNav.css',\n  scoped: true,\n})\nexport class MobileSheetNav {\n  @Element() el!: HTMLElement;\n\n  @Prop({ reflect: true }) open: boolean = false;\n  @Prop() browseContext: NavChromeStyle = 'dashboard';\n  @Prop() dashboardGroups: PanelNavGroup[] = [];\n  @Prop() settingsGroups: PanelNavGroup[] = [];\n  @Prop() currentUrl: string = '';\n  /** Whether the router-derived current area owns the active mobile stage. */\n  @Prop() routeSelectionActive: boolean = true;\n  @Prop() navigationLabel: string = 'Application navigation';\n  @Prop() dashboardLabel: string = 'Dashboard';\n  @Prop() settingsLabel: string = 'Settings';\n  @Prop() accountLabel: string = 'Account';\n  @Prop() helpLabel: string = 'Help & Support';\n  /** Show the optional Account shortcut in the sheet header. */\n  @Prop() showAccount: boolean = true;\n\n  @Event() dsAreaSelect!: EventEmitter<string>;\n  @Event() dsBrowseContextChange!: EventEmitter<NavChromeStyle>;\n  @Event() dsClose!: EventEmitter<void>;\n\n  private get groups(): PanelNavGroup[] {\n    return this.browseContext === 'settings' ? this.settingsGroups : this.dashboardGroups;\n  }\n\n  private get activeId(): string {\n    if (!this.routeSelectionActive) return '';\n    return deriveActiveIdFromUrl(this.currentUrl, [\n      ...this.dashboardGroups.flatMap(group => group.items),\n      ...this.settingsGroups.flatMap(group => group.items),\n    ]);\n  }\n\n  @Watch('open')\n  handleOpenChange(open: boolean) {\n    if (!open) return;\n    requestAnimationFrame(() => {\n      const selected = this.el.querySelector<HTMLElement>('[aria-current=\"page\"]');\n      const first = this.el.querySelector<HTMLElement>('.mobile-sheet-nav__item');\n      (selected ?? first)?.focus({ preventScroll: true });\n    });\n  }\n\n  @Listen('keydown')\n  handleKeyDown(event: KeyboardEvent) {\n    if (!this.open || event.key !== 'Escape') return;\n    event.preventDefault();\n    this.dsClose.emit();\n  }\n\n  private handleContextChange = (event: CustomEvent<string>) => {\n    const next = event.detail === 'settings' ? 'settings' : 'dashboard';\n    if (next === this.browseContext) return;\n    this.dsBrowseContextChange.emit(next);\n  };\n\n  private renderItem(item: PanelNavItem) {\n    const selected = item.id === this.activeId;\n    return (\n      <button\n        type=\"button\"\n        class={{\n          'mobile-sheet-nav__item': true,\n          'mobile-sheet-nav__item--selected': selected,\n          'ds-control--lg': true,\n          'ds-focus-ring-inset': true,\n          'ds-interaction-fill': true,\n        }}\n        aria-current={selected ? 'page' : undefined}\n        onClick={() => this.dsAreaSelect.emit(item.id)}\n      >\n        <ds-icon\n          class=\"ds-interaction-fill__content\"\n          name={item.icon}\n          size=\"lg\"\n          color=\"inherit\"\n        />\n        <ds-text\n          class=\"mobile-sheet-nav__item-label ds-interaction-fill__content\"\n          as=\"span\"\n          variant=\"text-body-large\"\n          emphasis={selected}\n          color=\"inherit\"\n        >\n          {item.label}\n        </ds-text>\n        {item.dot && (\n          <ds-badge\n            class=\"mobile-sheet-nav__dot ds-interaction-fill__content\"\n            variant=\"dot\"\n            hasRing={false}\n            label=\"\"\n            aria-hidden=\"true\"\n          />\n        )}\n      </button>\n    );\n  }\n\n  private renderLogo() {\n    return (\n      <span class=\"mobile-sheet-nav__logo\" aria-hidden=\"true\">\n        {/* eslint-disable-next-line local/prefer-ds-icon -- Motive brand mark is not part of the IcoMo runtime catalog. */}\n        <svg\n          class=\"mobile-sheet-nav__logo-mark\"\n          viewBox=\"0 0 20 20\"\n          fill=\"none\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          focusable=\"false\"\n          aria-hidden=\"true\"\n        >\n          <path\n            d=\"M11.1159 4.31537H7.67021L2.53401 13.0703H0V15.6875H4.02716L8.24319 8.49978V15.6846H11.6342L15.8289 8.47829V15.6846H18.7122V4.3125H15.2559L11.1159 11.3648V4.31537Z\"\n            fill=\"currentColor\"\n          />\n        </svg>\n      </span>\n    );\n  }\n\n  private renderHeaderDestination(\n    id: MobileSheetNavHeaderDestinationId,\n    icon: string,\n    label: string\n  ) {\n    return (\n      <ds-tooltip label={label} side=\"bottom\" size=\"sm\">\n        <ds-button-unfilled\n          variant=\"icon\"\n          size=\"lg\"\n          icon={icon}\n          aria-label={label}\n          activeFill={false}\n          hasBorder={false}\n          onDsClick={() => this.dsAreaSelect.emit(id)}\n        />\n      </ds-tooltip>\n    );\n  }\n\n  render() {\n    const contextTabs = [\n      { ...CONTEXT_TABS[0], label: this.dashboardLabel },\n      { ...CONTEXT_TABS[1], label: this.settingsLabel },\n    ];\n\n    return (\n      <Host aria-hidden={this.open ? undefined : 'true'} inert={this.open ? undefined : true}>\n        <section\n          id=\"ds-mobile-sheet-nav\"\n          class=\"mobile-sheet-nav\"\n        >\n          <header\n            class={{\n              'mobile-sheet-nav__header': true,\n              'mobile-sheet-nav__header--expanded-context': !this.showAccount,\n              'ds-chrome-grid': true,\n              'ds-chrome-space--md': true,\n            }}\n          >\n            <div class=\"mobile-sheet-nav__brand\">{this.renderLogo()}</div>\n            <ds-tab-group\n              class=\"mobile-sheet-nav__context\"\n              tabs={contextTabs}\n              value={this.browseContext}\n              size=\"lg\"\n              width={this.showAccount ? 'hug' : 'fill'}\n              aria-label=\"Browse context\"\n              onDsChange={this.handleContextChange}\n            />\n            <div class=\"mobile-sheet-nav__actions\">\n              {this.renderHeaderDestination('help', 'CircleQuestion', this.helpLabel)}\n              {this.showAccount\n                ? this.renderHeaderDestination('account', 'Avatar', this.accountLabel)\n                : null}\n            </div>\n          </header>\n\n          <nav\n            class=\"mobile-sheet-nav__body ds-chrome-column ds-chrome-space--md\"\n            aria-label={this.navigationLabel}\n          >\n            <div class=\"mobile-sheet-nav__sections\">\n              {this.groups\n                .filter(group => group.items.length > 0)\n                .map(group => (\n                  <div class=\"mobile-sheet-nav__items\">\n                    {group.items.map(item => this.renderItem(item))}\n                  </div>\n                ))}\n            </div>\n          </nav>\n        </section>\n      </Host>\n    );\n  }\n}\n",
      "type": "registry:ui"
    }
  ]
}
