CommandPalette
since v12.3.0CommandPalette — cmd-K command menu. cmdk owns list filtering + item keyboard
nav; our Dialog owns open/scrim/focus-trap/z-index (ADR-0008).
Active row uses ink fill, never brand.
Install
Add the package and import the component.
pnpm add @hey-mike/tungstenpnpm add @hey-mike/tungstenimport { CommandPalette } from '@hey-mike/tungsten';import { CommandPalette } from '@hey-mike/tungsten';Preview
Same fixtures used by the visual-regression suite.
Usage
apps/docs/app/snapshots/command-palette/page.tsx
'use client';
import { useState } from 'react';
import { Button, CommandPalette } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
import { HeroSpecimen } from '../_components/HeroSpecimen';
const items = [
{ id: 'dash', label: 'Go to dashboard', group: 'Navigation', onSelect: () => {} },
{ id: 'users', label: 'Manage users', group: 'Navigation', onSelect: () => {} },
{ id: 'invite', label: 'Invite team member', group: 'Actions', onSelect: () => {} },
{ id: 'settings', label: 'Open settings', group: 'Actions', onSelect: () => {} },
];
// Detail-page variant: a closed palette behind its trigger. The interactive
// preview opens the real (portaled, modal) palette on click. The gallery
// thumbnail uses the static mock below instead — the real open palette portals a
// full-viewport modal that would leak onto the detail page and overwhelm the
// 160px thumbnail.
function CommandPaletteDemo() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open command menu (⌘K)</Button>
<CommandPalette
open={open}
onOpenChange={setOpen}
label="Command menu"
items={items}
placeholder="Type a command or search…"
/>
</>
);
}
export default function CommandPaletteSnapshot() {
return (
<VariantGrid
title="CommandPalette"
hero={
<HeroSpecimen className="max-w-[220px]">
<div className="border-stroke bg-surface shadow-overlay overflow-hidden rounded-md border text-left">
<div className="border-stroke text-ink-3 border-b px-3 py-2 text-xs">
Type a command or search…
</div>
<div className="p-1.5">
<p className="text-ink-3 tracking-label px-1.5 py-1 font-mono text-2xs uppercase">
Navigation
</p>
<div className="bg-surface-hover text-ink-1 rounded-sm px-1.5 py-1 text-sm">
Go to dashboard
</div>
<div className="text-ink-2 rounded-sm px-1.5 py-1 text-sm">Manage users</div>
</div>
</div>
</HeroSpecimen>
}
variants={[{ label: 'trigger', node: <CommandPaletteDemo /> }]}
/>
);
}
'use client';
import { useState } from 'react';
import { Button, CommandPalette } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
import { HeroSpecimen } from '../_components/HeroSpecimen';
const items = [
{ id: 'dash', label: 'Go to dashboard', group: 'Navigation', onSelect: () => {} },
{ id: 'users', label: 'Manage users', group: 'Navigation', onSelect: () => {} },
{ id: 'invite', label: 'Invite team member', group: 'Actions', onSelect: () => {} },
{ id: 'settings', label: 'Open settings', group: 'Actions', onSelect: () => {} },
];
// Detail-page variant: a closed palette behind its trigger. The interactive
// preview opens the real (portaled, modal) palette on click. The gallery
// thumbnail uses the static mock below instead — the real open palette portals a
// full-viewport modal that would leak onto the detail page and overwhelm the
// 160px thumbnail.
function CommandPaletteDemo() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open command menu (⌘K)</Button>
<CommandPalette
open={open}
onOpenChange={setOpen}
label="Command menu"
items={items}
placeholder="Type a command or search…"
/>
</>
);
}
export default function CommandPaletteSnapshot() {
return (
<VariantGrid
title="CommandPalette"
hero={
<HeroSpecimen className="max-w-[220px]">
<div className="border-stroke bg-surface shadow-overlay overflow-hidden rounded-md border text-left">
<div className="border-stroke text-ink-3 border-b px-3 py-2 text-xs">
Type a command or search…
</div>
<div className="p-1.5">
<p className="text-ink-3 tracking-label px-1.5 py-1 font-mono text-2xs uppercase">
Navigation
</p>
<div className="bg-surface-hover text-ink-1 rounded-sm px-1.5 py-1 text-sm">
Go to dashboard
</div>
<div className="text-ink-2 rounded-sm px-1.5 py-1 text-sm">Manage users</div>
</div>
</div>
</HeroSpecimen>
}
variants={[{ label: 'trigger', node: <CommandPaletteDemo /> }]}
/>
);
}
Props
Surface specific to <CommandPalette />.
| Prop | Type | Default | Description |
|---|---|---|---|
| open* | boolean | — | — |
| onOpenChange* | (open: boolean) => void | — | — |
| label* | string | — | Accessible name for the palette. |
| items* | CommandPaletteItem[] | — | — |
| placeholder | string | Type a command or search… | — |
| loading | boolean | false | — |