Zetta v1.6

Components · Overlays & menus

Command palette

Keyboard-driven global search and command launcher. Split from zetta-overlay-v1_4.md (removed in v1.5) in v1.4.

Preview

Navigation
Go to Foundations
Go to Components
Go to Tokens
Actions
Toggle dark theme
Copy current URL
Open settings

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Command palette" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `command-palette` spec and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `command-palette` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

┌──────────────────────────────────────────────┐
│  🔍  Search commands…                         │  ← command-palette-input (48px)
├──────────────────────────────────────────────┤
│  RECENT                                       │  ← command-palette-group-label
│  [icon] Open settings           ⌘,            │  ← command-palette-item
│  [icon] Create new project      ⌘N            │
│─────────────────────────────────────────────  │
│  NAVIGATION                                   │
│  [icon] Go to Dashboard                       │
│  [icon] Go to Members                         │
└──────────────────────────────────────────────┘
State Visual
Closed Not rendered
Open Full-width modal over blanket, input focused
Typing Results filter in real time
Item hover {colors.accent} fill
Item focused {colors.accent} fill + focus outline
Item selected {colors.primary} text, bold
Empty "No results for '[query]'" centered message

When to use

  • Global command launcher accessible from anywhere in the product.
  • Navigation shortcut for power users.

When not to use

  • Context-specific search — use a search input within that view.
  • Single-purpose action — use a button or dropdown.

Do

  • Open via ⌘K (Mac) / Ctrl+K (Windows) keyboard shortcut.
  • Show recent commands at the top before the user types.
  • Group commands by category with section labels.
  • Include keyboard shortcut hints right-aligned in muted text.
  • Command labels: verb + noun. "Create project", "Open settings", "Go to dashboard".
  • Group labels: short noun. "Recent", "Navigation", "Actions". All caps.
  • Empty state: "No results for '[query]'." — include the query in the message.
  • Placeholder: "Search commands…" or "Search and navigate…".

Keyboard

Key Behavior
⌘K / Ctrl+K Open command palette
Up / Down Arrow Navigate items
Enter Execute focused command
Escape Close palette
Type Filter results in real time

Accessibility

  • role="dialog" on the palette panel, aria-modal="true", aria-label="Command palette".
  • role="combobox" on the input, aria-controls="results-id", aria-expanded="true".
  • role="listbox" on the results list, role="option" on each item.
  • aria-activedescendant on the input, pointing to the focused item.
  • Focus trap inside palette while open.
  • aria-live="polite" region announces result count: "5 results."

Spec

Values and token references resolved straight from the Zetta spec.

command-palette
backgroundColor
{colors.popover}
textColor
{colors.popover-foreground}
borderColor
{colors.hairline}
borderWidth
1px
borderRadius
{rounded.base}
shadow
{elevation.shadow.overlay}
maxWidth
560px
width
100%
display
flex
flexDirection
column
overflow
hidden
command-palette-input
height
48px
paddingX
16px
textColor
{colors.ink}
placeholderColor
{colors.placeholder}
fontFamily
Geist
fontSize
14px
borderBottomColor
{colors.hairline}
borderBottomWidth
1px
command-palette-item
textColor
{colors.ink}
fontFamily
Geist
fontSize
14px
minHeight
40px
paddingX
14px
paddingY
12px
borderRadius
{rounded.base}
display
flex
alignItems
center
gap
8px
cursor
pointer
command-palette-item-hover
backgroundColor
{colors.accent}
command-palette-item-focused
backgroundColor
{colors.accent}
outline
2px solid {colors.border-focus}
outlineOffset
-2px
command-palette-item-selected
textColor
{colors.primary}
fontWeight
500
command-palette-list
overflowY
auto
maxHeight
320px
padding
6px
command-palette-empty
textColor
{colors.muted}
fontFamily
Geist
fontSize
14px
textAlign
center
padding
{spacing.md}
command-palette-group-label
textColor
{colors.placeholder}
fontFamily
Geist
fontSize
11px
fontWeight
600
textTransform
uppercase
letterSpacing
0.06em
paddingX
14px
paddingY
6px