{
  "name": "CommandPalette",
  "source": "src/components/CommandPalette.tsx",
  "propsType": "CommandPaletteProps",
  "description": "CommandPalette — every action in the product, one search away.\n\n⌘K (Ctrl+K elsewhere) opens it from anywhere; typing filters; Enter runs.\nMount it once, near the root, and hand it every command the product has.\n\nWHY NOT A MODAL WITH A COMBOBOX IN IT\n\nA Combobox's list is a popover that opens and closes on its own rules, and\nit SELECTS a value that stays selected. A palette's list is always open and\neach row is RUN, once, and the palette goes away. The ARIA shape is the same\n— a combobox driving a listbox through `aria-activedescendant` — so this\nuses it, without the parts of Combobox that exist for choosing a value.\n\nNOT A NAVIGATION MENU\n\nEverything in the palette must also be reachable without it. It is a faster\nroute for people who know what they want, and a shortcut nobody told you\nabout is not a route at all.",
  "import": "import { CommandPalette } from 'ionbase-ui';",
  "status": "stable",
  "since": "0.81.0",
  "summary": "A searchable list of every command in the product, opened with ⌘K / Ctrl+K from anywhere, that runs the chosen command and closes.",
  "useWhen": [
    "the product has more actions and destinations than its navigation shows at once",
    "people who use it daily want to reach anything without the pointer",
    "mounted once, near the root, with every command the product has"
  ],
  "useInstead": [
    {
      "when": "the user picks a value that stays chosen — an assignee, a country",
      "use": "Combobox",
      "why": "a combobox selects and keeps a value in a form; a palette runs a command once and goes away"
    },
    {
      "when": "a few actions belong to one object — a row's Edit, Duplicate, Delete",
      "use": "Menu",
      "why": "those actions belong beside the thing they act on, where people look for them"
    },
    {
      "when": "the search is over records — agents, runs — shown as a page of results",
      "use": "Input",
      "why": "a filtered table is a page with its own URL, and a palette is gone the moment it is used"
    }
  ],
  "a11y": {
    "role": "dialog",
    "guarantees": [
      "a modal dialog named by `label`: focus is trapped, the page behind is hidden from assistive tech, Escape and a scrim click close it, and focus returns to what had it",
      "focus stays in the search field, a combobox whose always-open listbox is driven by aria-activedescendant — typing and choosing never compete for focus",
      "sections are role=group, named by their heading",
      "disabled commands are listed with aria-disabled, skipped by the arrow keys, and do nothing on click",
      "the number of matches is announced through a polite live region as the query changes",
      "`onAction` runs after the palette has closed and handed focus back, so an action that moves focus keeps it",
      "shortcut hints are read as key names — \"Command Shift N\" — not as symbols"
    ],
    "requires": [
      "every command also reachable without the palette — it is a faster route, never the only one",
      "a visible way to open it for people who do not know the shortcut, such as a header button showing the keys"
    ]
  },
  "antiPatterns": [
    {
      "dont": "showing a `shortcut` on a command without binding that shortcut yourself",
      "why": "the palette displays a command's shortcut and does not listen for it; a hint for a key that does nothing is worse than no hint"
    },
    {
      "dont": "moving focus from inside a command's handler by running it before closing, or wrapping onAction to close the palette first",
      "why": "onAction already runs after close. While the dialog is mounted its focus scope pulls focus back to the search field"
    },
    {
      "dont": "rendering <CommandPalette> only when a state flag is true",
      "do": "mount it always and drive `isOpen`, or let it open itself on the shortcut",
      "why": "unmounted, it cannot listen for ⌘K"
    },
    {
      "dont": "labels that are nouns — \"Agents\", \"Dark mode\"",
      "do": "start with a verb — \"Go to Agents\", \"Switch to dark theme\"",
      "why": "a row says what pressing Enter will do; a noun leaves the reader guessing whether it opens, toggles or deletes"
    },
    {
      "dont": "two palettes on one page, or a second listener for ⌘K",
      "why": "both toggle on the same key press and cancel each other out"
    }
  ],
  "slots": {
    "emptyLabel": {
      "expects": "what to show when nothing matches"
    }
  },
  "stylesheet": "src/styles/command-palette.css",
  "tokens": [
    "--border-subtle",
    "--border-width-default",
    "--border-width-thick",
    "--font-family-sans",
    "--font-weight-medium",
    "--icon-disabled",
    "--icon-secondary",
    "--icon-size-md",
    "--icon-size-sm",
    "--ion-shadow-shadow-xl",
    "--radius-sm",
    "--radius-xl",
    "--spacing-12",
    "--spacing-16",
    "--spacing-2",
    "--spacing-32",
    "--spacing-4",
    "--spacing-40",
    "--spacing-48",
    "--spacing-8",
    "--spacing-96",
    "--surface-hover",
    "--surface-overlay",
    "--surface-scrim",
    "--text-default",
    "--text-disabled",
    "--text-tertiary",
    "--type-body",
    "--type-body-lg",
    "--type-body-lg-line-height",
    "--type-body-line-height",
    "--type-body-sm",
    "--type-body-sm-line-height",
    "--type-caption",
    "--type-caption-line-height"
  ],
  "props": {
    "commands": {
      "type": "readonly CommandPaletteItem[]",
      "required": true,
      "origin": "own",
      "description": "Every command. Filtering happens here, against what is typed."
    },
    "onAction": {
      "type": "(id: string) => void",
      "required": true,
      "origin": "own",
      "description": "Runs the chosen command. Called AFTER the palette has closed and handed\nfocus back, so an action that moves focus — to a search field, into a\nform — keeps it."
    },
    "isOpen": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "defaultOpen": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "onOpenChange": {
      "type": "((isOpen: boolean) => void) | undefined",
      "required": false,
      "origin": "own"
    },
    "openShortcut": {
      "type": "string | null | undefined",
      "required": false,
      "origin": "own",
      "description": "The shortcut that opens it from anywhere on the page, and closes it again.\nDefaults to `mod+k` — ⌘K on a Mac, Ctrl+K elsewhere. `null` turns it off,\nfor a page that opens the palette some other way."
    },
    "label": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Names the dialog and the search field."
    },
    "placeholder": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "emptyLabel": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Shown in place of the list when nothing matches."
    },
    "labels": {
      "type": "CommandPaletteLabels | undefined",
      "required": false,
      "origin": "own",
      "description": "Every other string the palette renders, for translation. English by default."
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    }
  },
  "propCounts": {
    "own": 11,
    "aria": 0,
    "dom": 0,
    "other": 0
  }
}
