{
  "name": "AppSwitcher",
  "source": "src/components/AppSwitcher.tsx",
  "propsType": "AppSwitcherProps",
  "description": "AppSwitcher — the grid of products in a suite's header.\n\nLINKS, NOT A MENU\n\nEach product is a place with an address: it opens in this tab, in a new\none with a modifier or a middle click, and its address can be copied. A\n`menu` of `menuitem`s would give up all three for arrow keys. So the panel\nis a Popover — a dialog, focus kept inside, Escape and an outside click\nclose it and focus goes back to the button — holding a list of links,\nreached with Tab.\n\nWHERE YOU ARE\n\nThe product you are in is marked `aria-current=\"true\"` — not \"page\": it is\na product, not this page — and drawn with a border as well as a tint, so\nit is not told by colour alone. It stays a link, to its home.\n\nA press on a link closes the panel. Opening a product in the same document\n— a hash route, a client router — would otherwise leave it open over the\npage it went to.",
  "import": "import { AppSwitcher } from 'ionbase-ui';",
  "status": "stable",
  "summary": "The nine-dot button in a suite's header and the grid of products it opens — links, each to a product's home, with the one you are in marked.",
  "useWhen": [
    "a suite of separate products shares a header, and people move between them",
    "the products have their own addresses: each opens at its home, in this tab or a new one"
  ],
  "useInstead": [
    {
      "when": "sections of one product",
      "use": "Sidebar",
      "why": "sections are navigation within a product, always in view; a switcher hides them behind a button for the sake of a move people make every minute"
    },
    {
      "when": "choosing a workspace or an account inside the same product",
      "use": "MenuTrigger",
      "why": "that changes what the product shows, not which product it is — a menu of choices, not a set of places"
    },
    {
      "when": "jumping to anything by name, products included",
      "use": "CommandPalette",
      "why": "search reaches every page by typing; the switcher is for recognising a product's mark"
    }
  ],
  "composition": {
    "order": [
      "AppSwitcher"
    ],
    "note": "Goes in Header's `end`, before the account. `apps` is the suite, in the order people look for them; `currentApp` names this product's `id`. `label` names the button, its tooltip and the panel. `footer` takes a Link to every app or to managing access.",
    "example": "<Header brand={…} end={<><AppSwitcher currentApp=\"ops\" apps={[{ id: 'ops', name: 'Ops', href: '/' }, { id: 'docs', name: 'Docs', href: 'https://docs.example' }]} /><Avatar … /></>} />"
  },
  "slots": {
    "footer": {
      "accepts": "Link",
      "note": "one link under the grid, centred"
    }
  },
  "a11y": {
    "requires": [
      "a `label` in the product's language when it is not English — it is the button's only name, the icon being nine dots"
    ],
    "guarantees": [
      "the button is named by `label`, \"Apps\" by default, with a tooltip showing it; `aria-expanded` says whether the panel is open",
      "the panel is a dialog named by `label`: focus moves into it and stays there, and Escape or a click outside closes it and gives focus back to the button",
      "each product is a link, reached with Tab, so it opens in a new tab with a modifier and its address can be copied",
      "the product you are in is `aria-current=\"true\"` and drawn with a border as well as a tint",
      "a product's `description` is its link's accessible description",
      "a press on a product closes the panel, so a same-document route does not leave it open over the page it went to",
      "in forced colours the current product's border is Highlight"
    ],
    "notes": [
      "Not a `menu`: menu items would give up opening in a new tab and copying the address for arrow keys.",
      "`icon` sits centred on a 40px tinted square, at its own size — a 24px icon suits. A product without one shows its initial there."
    ]
  },
  "antiPatterns": [
    {
      "dont": "an AppSwitcher listing the sections of one product",
      "do": "<Sidebar> with a NavItem each",
      "why": "sections are moved between constantly and belong in view; a switcher is for the few moves between products"
    },
    {
      "dont": "a Menu of products, each a MenuItem with an onAction that sets `location`",
      "do": "<AppSwitcher apps={…} />",
      "why": "menu items are not links: no new tab, no copied address, no status-bar URL"
    },
    {
      "dont": "leaving out `currentApp`",
      "do": "currentApp=\"ops\"",
      "why": "without it nothing says which product you are in, and the grid reads as a list of elsewheres"
    }
  ],
  "stylesheet": "src/styles/app-switcher.css",
  "tokens": [
    "--border-primary-strong",
    "--border-subtle",
    "--border-width-default",
    "--border-width-thick",
    "--font-weight-medium",
    "--font-weight-semibold",
    "--icon-primary",
    "--ion-duration-base",
    "--ion-ease-out",
    "--radius-md",
    "--ring-focus",
    "--spacing-12",
    "--spacing-4",
    "--spacing-40",
    "--spacing-8",
    "--surface-hover",
    "--surface-primary-subtle",
    "--surface-selected",
    "--surface-selected-hover",
    "--text-default",
    "--text-primary",
    "--text-secondary",
    "--type-body-md",
    "--type-body-md-line-height",
    "--type-body-sm",
    "--type-body-sm-line-height",
    "--type-caption",
    "--type-caption-line-height"
  ],
  "props": {
    "apps": {
      "type": "AppSwitcherApp[]",
      "required": true,
      "origin": "own",
      "description": "The products in the suite, in the order people look for them."
    },
    "currentApp": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "The `id` of the product this header belongs to."
    },
    "label": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Names the button — which is an icon only — its tooltip, and the panel.\nDefault \"Apps\"."
    },
    "footer": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Under the grid: a link to every app, or to manage access."
    },
    "isOpen": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "onOpenChange": {
      "type": "((isOpen: boolean) => void) | undefined",
      "required": false,
      "origin": "own"
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    }
  },
  "propCounts": {
    "own": 7,
    "aria": 0,
    "dom": 0,
    "other": 0
  }
}
