- Components
Command
A search box over a list of actions, and the Cmd+K palette that puts it in a dialog.
npx shadcn add @klarhimmel/commandWhen to use
Use for
A fast way to go anywhere or do anything by typing its name: the Cmd+K palette.
Not for
Choosing one value in a form. Use Combobox. Navigation people need to see. Use Tabs or a menu.
Pairs with
Dialog, Kbd, Button.
Preview
Press Ctrl or Cmd and K, or the button.
command.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { Command, CommandDialog } from '@/components/klarhimmel/ui/command';
export default function Example() {
return (
<Theme theme="brand">
<CommandDialog
open
onOpenChange={() => {}}
title="Command menu"
aria-label="Commands"
hotkey="k"
onSelect={(value) => console.log(value)}
groups={[{ heading: 'Go to', items: [{ value: 'rooms', label: 'Rooms' }, { value: 'guests', label: 'Guests' }] }]}
/>
</Theme>
);
}Install
Import
import { Command, CommandDialog } from '@/components/klarhimmel/ui/command';- Lands in
- components/klarhimmel/ui/command.tsx, plus cn() and the theme item if they are missing. Import theme.css after Tailwind.
- Render in
- Render it inside <Theme>, once near the root of your app. Tokens and fonts are scoped to it, so outside it the component is unstyled.
- Limit
- Overlays render into the Theme root with position: fixed. A transform on an ancestor re-parents fixed (a dialog centres in the wrapper) and overflow: hidden clips menus. Render <Theme> at the app root, outside any transformed wrapper.
Examples
Inline
5 results
RoomsSeaside suiteGarden roomLoftTreatmentsDeep tissue massageSauna for twoType, then Up and Down, then Enter.
import { useState } from 'react'; import { Command } from '@/components/klarhimmel/ui/command'; const groups = [ { heading: 'Rooms', items: [{ value: 'sea', label: 'Seaside suite' }, { value: 'garden', label: 'Garden room' }, { value: 'loft', label: 'Loft', keywords: ['attic'] }] }, { heading: 'Treatments', items: [{ value: 'massage', label: 'Deep tissue massage' }, { value: 'sauna', label: 'Sauna for two' }] }, ]; export default function CommandInline() { const [last, setLast] = useState(''); return ( <div className="flex w-[min(28rem,calc(100cqw-3rem))] flex-col gap-3"> <div className="overflow-hidden rounded-kh-xl border border-kh-line bg-kh-surface shadow-kh-1"> <Command aria-label="Find a room or treatment" groups={groups} onSelect={setLast} placeholder="Find a room or a treatment…" /> </div> <p role="status" className="text-kh-small text-kh-muted">{last ? `Chose ${last}.` : 'Type, then Up and Down, then Enter.'}</p> </div> ); }Empty
No help articles match. Try fewer words.
No help articles match. Try fewer words.
import { Command } from '@/components/klarhimmel/ui/command'; export default function CommandEmpty() { return ( <div className="w-[min(28rem,calc(100cqw-3rem))] overflow-hidden rounded-kh-xl border border-kh-line bg-kh-surface shadow-kh-1"> <Command aria-label="Search the help centre" query="refund policy" groups={[{ heading: 'Help articles', items: [{ value: 'cancel', label: 'Cancelling a booking' }, { value: 'pay', label: 'Paying by invoice' }] }]} emptyText="No help articles match. Try fewer words." /> </div> ); }
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
groups | CommandGroup[] | - | Required. A group is { heading?, items }; an item is { value, label, keywords?, shortcut?, icon?, disabled? }. Every word typed must match a label or a keyword. Shortcuts only remind; the app binds the keys. |
onSelect | (value: string) => void | - | Called with the item's value on Enter or click. |
placeholder / emptyText | string | English words | The box ('Type a command or search…') and the empty message ('No results'). Pass them translated. |
resultsLabel | (count: number) => string | '3 results' | What is announced as you type. |
aria-label | string | - | Required: names the box and the list. |
CommandDialog props | open, onOpenChange, title, hotkey | - | Controlled. The title names the dialog for assistive tech and is not shown. hotkey is a letter that toggles it with Cmd or Ctrl. |
className | string | - | Extra classes, merged after the component's own. |
Accessibility
| Key | Does |
|---|---|
Cmd or Ctrl + K | Opens and closes the palette (hotkey) |
Type | Narrows the list; every word must match |
Down / Up | Moves the highlight, wrapping; disabled items are skipped |
Enter | Chooses the highlighted item |
Escape | Clears the text; again, closes the dialog |
The WAI-ARIA combobox with an always-open listbox: focus stays in the box and aria-activedescendant follows the highlight. The number of results is announced as you type.
Accessibility