{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "shell-tools",
  "title": "ShellTools",
  "description": "Responsive persistent host for explicitly defined global tools, adapting PanelTools desktop/tablet chrome to configured mobile destinations and groups.",
  "type": "registry:ui",
  "meta": {
    "library": "@ds-mo/ui",
    "distribution": "npm",
    "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-tools",
    "source": "src/wc/components/ShellTools/ShellTools.tsx",
    "intentStatus": "complete",
    "intent": {
      "audience": "specialized",
      "status": "stable",
      "summary": "Responsive persistent host for explicitly defined global tools, adapting PanelTools desktop/tablet chrome to configured mobile destinations and groups.",
      "useWhen": [
        "A ShellApp must preserve the same product-owned global tool views across desktop, tablet, and mobile."
      ],
      "avoidWhen": [
        "The tools exist only in desktop and tablet chrome; PanelTools remains supported for that case.",
        "The content is a routed primary application area."
      ],
      "alternatives": [
        {
          "when": "Only legacy rail and drawer behavior is required.",
          "component": "component:ds-panel-tools",
          "reason": "PanelTools is the direct desktop and tablet rail-and-drawer primitive."
        }
      ],
      "commonlyComposedWith": [
        "component:ds-shell-app",
        "component:ds-panel-tool-header",
        "component:ds-mobile-header",
        "component:ds-tab-group",
        "component:ds-mobile-bar-nav"
      ],
      "patterns": [
        "pattern:application-shell"
      ],
      "accessibility": [
        "Only the active mobile tool view participates in focus or the accessibility tree.",
        "Header Back and application-owned header actions preserve the PanelTools event contract.",
        "Mobile Inbox uses a named label-only TabGroup for Stacks and Activity; Messages remains a direct mobile destination."
      ],
      "states": [
        "The application owns open and activeTool and replaces headers when tool depth changes.",
        "Items with mobileDestination inbox map to one mobile Inbox destination while retaining the actual active tool id; the canonical recipe groups Stacks and Activity, while Messages remains a separate destination.",
        "Stable tool ids own named slots; label, order, rail placement, shortcut, and mobile destination are explicit item data.",
        "Switching responsive mode must not recreate application-owned slotted product elements."
      ],
      "responsiveBehavior": [
        "Desktop and tablet compose PanelTools-compatible rail and drawer chrome.",
        "Mobile renders one centered MobileHeader for every tool; Stacks and Activity use the large segmented Inbox control, while Messages remains a direct tool destination."
      ],
      "frameworkCaveats": {
        "customElements": [
          "Assign items and headers as JavaScript properties and place each persistent owner in its named *-view slot."
        ],
        "react": [
          "Keep stable keyed product owner elements in the generated wrapper's named slots."
        ],
        "angular": [
          "Bind structured items and headers as properties and keep each tool owner mounted under a named *-view slot."
        ]
      },
      "references": [
        {
          "label": "Storybook",
          "path": "src/wc/components/ShellTools/ShellTools.stories.ts"
        },
        {
          "label": "PanelTools contract",
          "path": "src/wc/components/PanelTools/PanelTools.agent.json"
        }
      ]
    },
    "api": {
      "props": {
        "activeTool": {
          "type": "PanelToolsToolId | ''",
          "resolvedType": "string",
          "attribute": "active-tool",
          "default": "''",
          "required": false,
          "mutable": true
        },
        "fullscreenHeaderMode": {
          "type": "'shared' | 'split'",
          "resolvedType": "\"shared\" | \"split\"",
          "attribute": "fullscreen-header-mode",
          "default": "'shared'",
          "required": false,
          "mutable": false
        },
        "headers": {
          "type": "PanelToolsHeaders",
          "resolvedType": "PanelToolsHeaderConfig | string",
          "default": "{}",
          "required": false,
          "mutable": false
        },
        "inboxLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "inbox-label",
          "default": "'Inbox'",
          "required": false,
          "mutable": false
        },
        "inboxNavigationLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "inbox-navigation-label",
          "default": "'Inbox sections'",
          "required": false,
          "mutable": false
        },
        "items": {
          "type": "PanelToolsItem[]",
          "resolvedType": "PanelToolsItem[]",
          "default": "[]",
          "required": false,
          "mutable": false
        },
        "open": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "open",
          "default": "false",
          "required": false,
          "mutable": true
        },
        "presentation": {
          "type": "'drawer' | 'fullscreen'",
          "resolvedType": "\"drawer\" | \"fullscreen\"",
          "attribute": "presentation",
          "default": "'drawer'",
          "required": false,
          "mutable": true
        },
        "responsiveMode": {
          "type": "ShellResponsiveMode",
          "resolvedType": "\"desktop\" | \"mobile\" | \"tablet\"",
          "attribute": "responsive-mode",
          "default": "'desktop'",
          "required": false,
          "mutable": false,
          "description": "Resolved by ShellApp; mobile uses a full-stage tool presentation."
        },
        "storageKey": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "storage-key",
          "default": "''",
          "required": false,
          "mutable": false
        },
        "toolShortcutsLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "tool-shortcuts-label",
          "default": "'Tool shortcuts'",
          "required": false,
          "mutable": false
        },
        "toolsLabel": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "tools-label",
          "default": "'Tools'",
          "required": false,
          "mutable": false
        }
      },
      "events": [
        {
          "name": "dsHeaderAction",
          "detail": "{\n    tool: PanelToolsToolId;\n    id: string;\n  }",
          "bubbles": true,
          "cancelable": true,
          "composed": true
        },
        {
          "name": "dsHeaderBack",
          "detail": "{\n    tool: PanelToolsToolId;\n  }",
          "bubbles": true,
          "cancelable": true,
          "composed": true
        },
        {
          "name": "dsPresentationChange",
          "detail": "{\n    presentation: 'drawer' | 'fullscreen';\n  }",
          "bubbles": true,
          "cancelable": true,
          "composed": true
        },
        {
          "name": "dsToolChange",
          "detail": "{\n    id: PanelToolsToolId;\n    selected: boolean;\n  }",
          "bubbles": true,
          "cancelable": true,
          "composed": true
        }
      ],
      "methods": [
        {
          "name": "activateTool",
          "signature": "activateTool(id: PanelToolsToolId) => Promise<void>",
          "description": "Match PanelTools' imperative activation contract in every responsive mode."
        },
        {
          "name": "closeDrawer",
          "signature": "closeDrawer() => Promise<void>",
          "description": "Close the active global tool surface."
        },
        {
          "name": "focusHeaderAction",
          "signature": "focusHeaderAction(id: string) => Promise<void>",
          "description": "Focus an application-owned action in the visible shared tool header."
        }
      ],
      "slots": []
    },
    "props": {
      "activeTool": {
        "type": "PanelToolsToolId | ''",
        "resolvedType": "string",
        "attribute": "active-tool",
        "default": "''",
        "required": false,
        "mutable": true
      },
      "fullscreenHeaderMode": {
        "type": "'shared' | 'split'",
        "resolvedType": "\"shared\" | \"split\"",
        "attribute": "fullscreen-header-mode",
        "default": "'shared'",
        "required": false,
        "mutable": false
      },
      "headers": {
        "type": "PanelToolsHeaders",
        "resolvedType": "PanelToolsHeaderConfig | string",
        "default": "{}",
        "required": false,
        "mutable": false
      },
      "inboxLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "inbox-label",
        "default": "'Inbox'",
        "required": false,
        "mutable": false
      },
      "inboxNavigationLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "inbox-navigation-label",
        "default": "'Inbox sections'",
        "required": false,
        "mutable": false
      },
      "items": {
        "type": "PanelToolsItem[]",
        "resolvedType": "PanelToolsItem[]",
        "default": "[]",
        "required": false,
        "mutable": false
      },
      "open": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "open",
        "default": "false",
        "required": false,
        "mutable": true
      },
      "presentation": {
        "type": "'drawer' | 'fullscreen'",
        "resolvedType": "\"drawer\" | \"fullscreen\"",
        "attribute": "presentation",
        "default": "'drawer'",
        "required": false,
        "mutable": true
      },
      "responsiveMode": {
        "type": "ShellResponsiveMode",
        "resolvedType": "\"desktop\" | \"mobile\" | \"tablet\"",
        "attribute": "responsive-mode",
        "default": "'desktop'",
        "required": false,
        "mutable": false,
        "description": "Resolved by ShellApp; mobile uses a full-stage tool presentation."
      },
      "storageKey": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "storage-key",
        "default": "''",
        "required": false,
        "mutable": false
      },
      "toolShortcutsLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "tool-shortcuts-label",
        "default": "'Tool shortcuts'",
        "required": false,
        "mutable": false
      },
      "toolsLabel": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "tools-label",
        "default": "'Tools'",
        "required": false,
        "mutable": false
      }
    },
    "events": [
      {
        "name": "dsHeaderAction",
        "detail": "{\n    tool: PanelToolsToolId;\n    id: string;\n  }",
        "bubbles": true,
        "cancelable": true,
        "composed": true
      },
      {
        "name": "dsHeaderBack",
        "detail": "{\n    tool: PanelToolsToolId;\n  }",
        "bubbles": true,
        "cancelable": true,
        "composed": true
      },
      {
        "name": "dsPresentationChange",
        "detail": "{\n    presentation: 'drawer' | 'fullscreen';\n  }",
        "bubbles": true,
        "cancelable": true,
        "composed": true
      },
      {
        "name": "dsToolChange",
        "detail": "{\n    id: PanelToolsToolId;\n    selected: boolean;\n  }",
        "bubbles": true,
        "cancelable": true,
        "composed": true
      }
    ],
    "methods": [
      {
        "name": "activateTool",
        "signature": "activateTool(id: PanelToolsToolId) => Promise<void>",
        "description": "Match PanelTools' imperative activation contract in every responsive mode."
      },
      {
        "name": "closeDrawer",
        "signature": "closeDrawer() => Promise<void>",
        "description": "Close the active global tool surface."
      },
      {
        "name": "focusHeaderAction",
        "signature": "focusHeaderAction(id: string) => Promise<void>",
        "description": "Focus an application-owned action in the visible shared tool header."
      }
    ],
    "slots": [],
    "exports": {
      "customElement": "ds-shell-tools",
      "react": "DsShellTools",
      "vue": "DsShellTools",
      "angular": "DsShellTools"
    },
    "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-shell-tools.js';",
        "example": "<ds-shell-tools></ds-shell-tools>"
      },
      "react": {
        "import": "import { DsShellTools } from '@ds-mo/ui/react';",
        "example": "<DsShellTools />"
      },
      "vue": {
        "import": "import { DsShellTools } from '@ds-mo/ui/vue';",
        "example": "<DsShellTools />"
      },
      "angular": {
        "import": "import { DsShellTools } from '@ds-mo/ui/angular/ds-shell-tools';",
        "example": "<ds-shell-tools></ds-shell-tools>"
      },
      "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: headers, items.",
      "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-unfilled",
    "mobile-header",
    "panel-tools",
    "tooltip"
  ],
  "files": [
    {
      "path": "src/wc/components/ShellTools/ShellTools.css",
      "content": ":host {\n  display: block;\n  min-width: 0;\n  min-height: 0;\n  height: 100%;\n  background: transparent;\n}\n\n:host([responsive-mode='mobile']) {\n  width: 100%;\n  background: var(--color-background-primary);\n}\n\n.shell-tools__desktop,\n.shell-tools__desktop ds-panel-tools,\n.shell-tools__mobile {\n  display: block;\n  min-width: 0;\n  min-height: 0;\n  height: 100%;\n}\n\n.shell-tools__slot-proxy {\n  display: block;\n  width: 100%;\n  height: 100%;\n  min-width: 0;\n  min-height: 0;\n}\n\n.shell-tools__mobile {\n  display: grid;\n  grid-template-rows: auto minmax(0, 1fr);\n  background: var(--color-background-primary);\n}\n\n.shell-tools__mobile-header {\n  grid-row: 1;\n}\n\n.shell-tools__mobile-body,\n.shell-tools__view {\n  min-width: 0;\n  min-height: 0;\n  height: 100%;\n}\n\n.shell-tools__mobile-body {\n  grid-row: 2;\n  overflow: hidden;\n}\n\n.shell-tools__view {\n  overflow: auto;\n  overscroll-behavior: contain;\n}\n\n.shell-tools__view[hidden] {\n  display: none;\n}\n\n.shell-tools__view ::slotted(*) {\n  min-height: 0;\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "src/wc/components/ShellTools/ShellTools.tsx",
      "content": "import {\n  Component,\n  Element,\n  Event,\n  EventEmitter,\n  h,\n  Host,\n  Method,\n  Prop,\n  Watch,\n} from '@stencil/core';\nimport {\n  PANEL_TOOLS_LABELS,\n  type PanelToolsHeaderConfig,\n  type PanelToolsHeaders,\n  type PanelToolsItem,\n  type PanelToolsToolId,\n} from '../PanelTools/panel-tools-types';\nimport {\n  orderPanelToolsItems,\n  reconcilePanelToolsAvailability,\n  resolvePanelToolActivation,\n} from '../PanelTools/panel-tools-utils';\nimport {\n  isShellInboxTool,\n  resolveAvailableInboxTool,\n  type ShellInboxToolId,\n  type ShellResponsiveMode,\n} from '../../shell/shell-responsive';\n\n@Component({\n  tag: 'ds-shell-tools',\n  styleUrl: 'ShellTools.css',\n  shadow: true,\n})\nexport class ShellTools {\n  @Element() el!: HTMLElement;\n\n  /** Resolved by ShellApp; mobile uses a full-stage tool presentation. */\n  @Prop({ attribute: 'responsive-mode', reflect: true })\n  responsiveMode: ShellResponsiveMode = 'desktop';\n  @Prop({ mutable: true, reflect: true }) open: boolean = false;\n  @Prop({ mutable: true, attribute: 'active-tool', reflect: true })\n  activeTool: PanelToolsToolId | '' = '';\n  @Prop({ mutable: true, reflect: true }) presentation: 'drawer' | 'fullscreen' = 'drawer';\n  @Prop({ attribute: 'fullscreen-header-mode', reflect: true })\n  fullscreenHeaderMode: 'shared' | 'split' = 'shared';\n  @Prop() items: PanelToolsItem[] = [];\n  @Prop() headers: PanelToolsHeaders = {};\n  @Prop({ attribute: 'storage-key' }) storageKey: string = '';\n  @Prop() toolsLabel: string = 'Tools';\n  @Prop() toolShortcutsLabel: string = 'Tool shortcuts';\n  @Prop() inboxLabel: string = 'Inbox';\n  @Prop() inboxNavigationLabel: string = 'Inbox sections';\n\n  @Watch('presentation')\n  presentationChanged(next: 'drawer' | 'fullscreen', previous: 'drawer' | 'fullscreen') {\n    if (next === previous) return;\n\n    /*\n     * Consumers update ShellTools and their slotted master/detail layout in the\n     * same render. Forward the request immediately so PanelTools can conceal\n     * its surface until its matching render class commits on the next frame.\n     */\n    if (this.panelToolsEl && this.panelToolsEl.getAttribute('presentation') !== next) {\n      this.panelToolsEl.setAttribute('presentation', next);\n    }\n  }\n\n  @Event({ bubbles: true, composed: true }) dsToolChange!: EventEmitter<{\n    id: PanelToolsToolId;\n    selected: boolean;\n  }>;\n  @Event({ bubbles: true, composed: true }) dsPresentationChange!: EventEmitter<{\n    presentation: 'drawer' | 'fullscreen';\n  }>;\n  @Event({ bubbles: true, composed: true }) dsHeaderBack!: EventEmitter<{\n    tool: PanelToolsToolId;\n  }>;\n  @Event({ bubbles: true, composed: true }) dsHeaderAction!: EventEmitter<{\n    tool: PanelToolsToolId;\n    id: string;\n  }>;\n\n  private panelToolsEl: HTMLDsPanelToolsElement | null = null;\n\n  private get resolvedItems(): PanelToolsItem[] {\n    return this.items ?? [];\n  }\n\n  private get availableInboxTools(): ShellInboxToolId[] {\n    return this.resolvedItems\n      .filter(\n        item =>\n          !item.isInactive &&\n          (item.mobileDestination === 'inbox' || isShellInboxTool(item.id))\n      )\n      .map(item => item.id as ShellInboxToolId);\n  }\n\n  private get mobileViewOrder(): PanelToolsToolId[] {\n    return orderPanelToolsItems(this.resolvedItems).map(item => item.id);\n  }\n\n  private toolLabel(id: PanelToolsToolId): string {\n    const item = this.resolvedItems.find(candidate => candidate.id === id);\n    return (\n      item?.label ??\n      item?.ariaLabel ??\n      PANEL_TOOLS_LABELS[id as keyof typeof PANEL_TOOLS_LABELS] ??\n      id\n    );\n  }\n\n  private get mobileActiveTool(): PanelToolsToolId | '' {\n    const item = this.resolvedItems.find(candidate => candidate.id === this.activeTool);\n    const inbox =\n      item?.mobileDestination === 'inbox' || isShellInboxTool(this.activeTool);\n    if (!inbox) return this.activeTool;\n    return resolveAvailableInboxTool(this.activeTool, this.availableInboxTools);\n  }\n\n  componentWillLoad() {\n    this.reconcileAvailability();\n  }\n\n  @Watch('items')\n  handleItemsChange() {\n    this.reconcileAvailability();\n  }\n\n  private reconcileAvailability() {\n    const next = reconcilePanelToolsAvailability(this.resolvedItems, this.open, this.activeTool);\n    this.open = next.open;\n    this.activeTool = next.activeTool;\n  }\n\n  private resolvedHeaders(): PanelToolsHeaders {\n    return this.headers ?? {};\n  }\n\n  private activeHeader(tool: PanelToolsToolId): PanelToolsHeaderConfig {\n    return this.resolvedHeaders()[tool] ?? {};\n  }\n\n  private activateMobileTool(id: PanelToolsToolId) {\n    const item = this.resolvedItems.find(entry => entry.id === id);\n    if (!item || item.isInactive) return;\n    const next = resolvePanelToolActivation(this.open, this.activeTool, id);\n    this.open = next.open;\n    this.activeTool = next.activeTool;\n    this.dsToolChange.emit({ id, selected: next.selected });\n  }\n\n  private selectInboxTool = (event: CustomEvent<string>) => {\n    const id = event.detail;\n    if (!this.availableInboxTools.includes(id) || id === this.mobileActiveTool) return;\n    this.open = true;\n    this.activeTool = id;\n    this.dsToolChange.emit({ id, selected: true });\n  };\n\n  private handlePanelToolChange = (\n    event: CustomEvent<{ id: PanelToolsToolId; selected: boolean }>\n  ) => {\n    this.activeTool = event.detail.id;\n    this.open = event.detail.selected;\n  };\n\n  private handlePanelPresentationChange = (\n    event: CustomEvent<{ presentation: 'drawer' | 'fullscreen' }>\n  ) => {\n    this.presentation = event.detail.presentation;\n  };\n\n  private handleMobileHeaderAction = (\n    tool: PanelToolsToolId,\n    id: string,\n    event: CustomEvent<MouseEvent>\n  ) => {\n    event.stopPropagation();\n    this.dsHeaderAction.emit({ tool, id });\n  };\n\n  /** Match PanelTools' imperative activation contract in every responsive mode. */\n  @Method()\n  async activateTool(id: PanelToolsToolId) {\n    if (this.responsiveMode !== 'mobile') {\n      await this.panelToolsEl?.activateTool(id);\n      return;\n    }\n    this.activateMobileTool(id);\n  }\n\n  /** Close the active global tool surface. */\n  @Method()\n  async closeDrawer() {\n    if (this.responsiveMode !== 'mobile') {\n      await this.panelToolsEl?.closeDrawer();\n      return;\n    }\n    if (!this.open) return;\n    const id = this.activeTool;\n    this.open = false;\n    if (id) this.dsToolChange.emit({ id, selected: false });\n  }\n\n  /** Focus an application-owned action in the visible shared tool header. */\n  @Method()\n  async focusHeaderAction(id: string) {\n    if (this.responsiveMode !== 'mobile') {\n      await this.panelToolsEl?.focusHeaderAction(id);\n      return;\n    }\n    const action = (this.el.shadowRoot ?? this.el).querySelector(\n      `[data-header-action-id=\"${CSS.escape(id)}\"]`\n    ) as\n      | (HTMLElement & { setFocus?: () => Promise<void> })\n      | null;\n    await action?.setFocus?.();\n  }\n\n  private renderForwardedSlots() {\n    return this.mobileViewOrder.flatMap(id => [\n      <div key={`tool:${id}`} class=\"shell-tools__slot-proxy\" slot={id}>\n        <slot name={id} />\n      </div>,\n      <div\n        key={`tool-view:${id}`}\n        class=\"shell-tools__slot-proxy\"\n        slot={`${id}-view`}\n      >\n        <slot name={`${id}-view`} />\n      </div>,\n    ]);\n  }\n\n  private renderDesktop() {\n    return (\n      <div class=\"shell-tools__desktop\">\n        <ds-panel-tools\n          open={this.open}\n          activeTool={this.activeTool}\n          presentation={this.presentation}\n          fullscreenHeaderMode={this.fullscreenHeaderMode}\n          items={this.resolvedItems}\n          headers={this.resolvedHeaders()}\n          storageKey={this.storageKey}\n          toolsLabel={this.toolsLabel}\n          toolShortcutsLabel={this.toolShortcutsLabel}\n          ref={element => {\n            this.panelToolsEl = element as HTMLDsPanelToolsElement | null;\n          }}\n          onDsToolChange={this.handlePanelToolChange}\n          onDsPresentationChange={this.handlePanelPresentationChange}\n        >\n          {this.renderForwardedSlots()}\n        </ds-panel-tools>\n      </div>\n    );\n  }\n\n  private renderMobileHeader(tool: PanelToolsToolId) {\n    const header = this.activeHeader(tool);\n    const configuredTitle = header.title?.trim();\n    const title = configuredTitle || this.toolLabel(tool);\n    const actions = (header.actions ?? []).filter(action => action.id !== 'fullscreen');\n    const inboxRoot = isShellInboxTool(tool) && !header.showBack;\n    const sections =\n      inboxRoot\n        ? this.availableInboxTools.map(id => {\n            const item = this.resolvedItems.find(candidate => candidate.id === id);\n            return {\n              id,\n              label: this.toolLabel(id),\n              variant: 'label' as const,\n              dot: item?.dot,\n            };\n          })\n        : [];\n\n    return (\n      <ds-mobile-header\n        class=\"shell-tools__mobile-header\"\n        heading={title}\n        headingLevel=\"h2\"\n        sections={sections}\n        value={tool}\n        sectionsAriaLabel={this.inboxNavigationLabel}\n        sectionsPresentation={inboxRoot ? 'segmented' : 'switcher'}\n        sectionsSize=\"lg\"\n        onDsSectionChange={this.selectInboxTool}\n      >\n        {header.showBack ? (\n          <ds-tooltip\n            slot=\"leading\"\n            label={header.backAriaLabel || 'Back'}\n            side=\"bottom\"\n            size=\"sm\"\n          >\n            <ds-button-unfilled\n              variant=\"icon\"\n              icon={header.backIcon || 'ChevronLeft'}\n              size=\"md\"\n              aria-label={header.backAriaLabel || 'Back'}\n              activeFill={false}\n              hasBorder={false}\n              onDsClick={() => this.dsHeaderBack.emit({ tool })}\n            />\n          </ds-tooltip>\n        ) : null}\n        {actions.map(action => (\n          <ds-tooltip\n            slot=\"trailing\"\n            key={action.id}\n            label={action.ariaLabel}\n            side=\"bottom\"\n            size=\"sm\"\n          >\n            <ds-button-unfilled\n              id={action.triggerId || undefined}\n              data-header-action-id={action.id}\n              variant=\"icon\"\n              icon={action.icon}\n              size=\"md\"\n              aria-label={action.ariaLabel}\n              haspopup={action.haspopup}\n              controls={action.controls}\n              expanded={action.expanded}\n              pressed={action.pressed}\n              isInactive={action.isInactive}\n              activeFill={false}\n              hasBorder={false}\n              onDsClick={(event: CustomEvent<MouseEvent>) =>\n                this.handleMobileHeaderAction(tool, action.id, event)}\n            />\n          </ds-tooltip>\n        ))}\n      </ds-mobile-header>\n    );\n  }\n\n  private renderMobile() {\n    const tool = this.mobileActiveTool;\n    return (\n      <div\n        class=\"shell-tools__mobile\"\n        aria-hidden={this.open && tool ? undefined : 'true'}\n        inert={this.open && tool ? undefined : true}\n      >\n        {tool ? this.renderMobileHeader(tool) : null}\n        <div class=\"shell-tools__mobile-body\">\n          {this.mobileViewOrder.map(id => {\n            const active = this.open && id === tool;\n            return (\n              <div\n                key={`mobile-tool-view:${id}`}\n                class={{\n                  'shell-tools__view': true,\n                  'shell-tools__view--active': active,\n                }}\n                hidden={!active}\n                aria-hidden={active ? undefined : 'true'}\n                inert={active ? undefined : true}\n              >\n                <slot name={`${id}-view`}>\n                  <slot name={id} />\n                </slot>\n              </div>\n            );\n          })}\n        </div>\n      </div>\n    );\n  }\n\n  render() {\n    const mobile = this.responsiveMode === 'mobile';\n    return (\n      <Host\n        role={\n          mobile\n            ? this.presentation === 'fullscreen'\n              ? 'dialog'\n              : 'complementary'\n            : undefined\n        }\n        aria-modal={mobile && this.presentation === 'fullscreen' ? 'true' : undefined}\n        aria-label={mobile ? this.toolsLabel : undefined}\n      >\n        {mobile ? this.renderMobile() : this.renderDesktop()}\n      </Host>\n    );\n  }\n}\n",
      "type": "registry:ui"
    }
  ]
}
