Command
Fast, composable command palette.
import * as stylex from '@stylexjs/stylex';
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandShortcut,
} from '@/components/ui/command';
import { ring } from '@/lib/stylex-utils';
import { container } from '@/lib/constants.stylex';
import { shadow } from '@/lib/tokens.stylex';
const commands = [
{ value: 'calendar', label: 'Calendar', group: 'Suggestions' },
{ value: 'search-emoji', label: 'Search emoji', group: 'Suggestions' },
{ value: 'calculator', label: 'Calculator', group: 'Suggestions' },
{ value: 'profile', label: 'Profile', group: 'Settings', shortcut: '⌘P' },
{ value: 'billing', label: 'Billing', group: 'Settings', shortcut: '⌘B' },
{ value: 'settings', label: 'Settings', group: 'Settings', shortcut: '⌘S' },
];
type CommandEntry = (typeof commands)[number];
export default function CommandDemo() {
return (
<Command
items={commands}
style={[styles.root, ring({ shadow: shadow.md })]}
>
<CommandInput placeholder="Type a command or search…" />
<CommandEmpty>No results found.</CommandEmpty>
<CommandList>
{(item: CommandEntry) => (
<CommandItem key={item.value} value={item}>
{item.label}
{item.shortcut && <CommandShortcut>{item.shortcut}</CommandShortcut>}
</CommandItem>
)}
</CommandList>
</Command>
);
}
const styles = stylex.create({
root: {
maxWidth: container.lg,
},
});
Install
npx @madeui/cli add commandUsage
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandShortcut,
} from '@/components/ui/command';Composition
<Command items={items}>
<CommandInput />
<CommandEmpty />
<CommandList>
{(item) => <CommandItem value={item} />}
</CommandList>
</Command>Groups
import * as React from 'react';
import * as stylex from '@stylexjs/stylex';
import { Calendar, CreditCard, Smile, User } from 'lucide-react';
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from '@/components/ui/command';
import { icon } from '@/lib/stylex-utils';
const commandGroups = [
{
value: 'suggestions',
label: 'Suggestions',
items: [
{ value: 'calendar', label: 'Calendar', icon: <Calendar {...stylex.props(icon.md)} /> },
{ value: 'search-emoji', label: 'Search emoji', icon: <Smile {...stylex.props(icon.md)} /> },
],
},
{
value: 'settings',
label: 'Settings',
items: [
{
value: 'profile',
label: 'Profile',
icon: <User {...stylex.props(icon.md)} />,
shortcut: '⌘P',
},
{
value: 'billing',
label: 'Billing',
icon: <CreditCard {...stylex.props(icon.md)} />,
shortcut: '⌘B',
},
],
},
];
export default function CommandGroups() {
return (
<Command items={commandGroups}>
<CommandInput placeholder="Type a command or search…" />
<CommandEmpty>No results found.</CommandEmpty>
<CommandList>
{(group: (typeof commandGroups)[number]) => (
<React.Fragment key={group.value}>
<CommandGroup heading={group.label}>
{group.items.map((item) => (
<CommandItem key={item.value} value={item}>
{item.icon}
{item.label}
{'shortcut' in item && item.shortcut && (
<CommandShortcut>{item.shortcut}</CommandShortcut>
)}
</CommandItem>
))}
</CommandGroup>
{group.value !==
commandGroups[commandGroups.length - 1].value && (
<CommandSeparator />
)}
</React.Fragment>
)}
</CommandList>
</Command>
);
}
Scrollable
import {
Command,
CommandEmpty,
CommandInput,
CommandItem,
CommandList,
} from '@/components/ui/command';
const fruits = [
'Apple', 'Apricot', 'Banana', 'Blackberry', 'Blueberry', 'Cantaloupe',
'Cherry', 'Clementine', 'Coconut', 'Cranberry', 'Date', 'Dragonfruit',
'Elderberry', 'Fig', 'Grape', 'Grapefruit', 'Guava', 'Honeydew', 'Kiwi',
'Lemon', 'Lime', 'Lychee', 'Mango', 'Mandarin', 'Nectarine', 'Orange',
'Papaya', 'Passionfruit', 'Peach', 'Pear', 'Persimmon', 'Pineapple',
'Plum', 'Pomegranate', 'Raspberry', 'Star fruit', 'Strawberry',
'Tangerine', 'Watermelon',
].map((label) => ({ label, value: label }));
export default function CommandScrollable() {
return (
<Command items={fruits}>
<CommandInput placeholder="Search fruit…" />
<CommandEmpty>No results found.</CommandEmpty>
<CommandList>
{(item: (typeof fruits)[number]) => (
<CommandItem key={item.value} value={item}>
{item.label}
</CommandItem>
)}
</CommandList>
</Command>
);
}
Keyboard shortcut
Open the palette with ⌘K / Ctrl K using the useHotkey helper
(npx @madeui/cli add use-hotkey).
'use client';
import * as React from 'react';
import { Button } from '@/components/ui/button';
import {
Command,
CommandDialog,
CommandEmpty,
CommandInput,
CommandItem,
CommandList,
} from '@/components/ui/command';
import { Kbd, KbdGroup } from '@/components/ui/kbd';
import { useHotkey } from '@/lib/use-hotkey';
const commands = [
{ value: 'calendar', label: 'Calendar' },
{ value: 'search-emoji', label: 'Search emoji' },
{ value: 'calculator', label: 'Calculator' },
];
type CommandEntry = (typeof commands)[number];
export default function CommandDialogHotkey() {
const [open, setOpen] = React.useState(false);
useHotkey('k', () => setOpen((value) => !value));
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>
Open command palette
<KbdGroup>
<Kbd>⌘</Kbd>
<Kbd>K</Kbd>
</KbdGroup>
</Button>
<CommandDialog open={open} onOpenChange={setOpen}>
<Command items={commands}>
<CommandInput placeholder="Type a command or search…" />
<CommandEmpty>No results found.</CommandEmpty>
<CommandList>
{(item: CommandEntry) => (
<CommandItem
key={item.value}
value={item}
onClick={() => setOpen(false)}
>
{item.label}
</CommandItem>
)}
</CommandList>
</Command>
</CommandDialog>
</>
);
}
API reference
Built on Base UI Autocomplete in inline open mode — the filtered list renders in place with no popup, like a command palette, with no extra dependency. Pass items to Command; filtering and highlight ship with the primitive, and CommandList accepts a render function over the filtered items. All other props are forwarded to the Base UI Root (filter, onValueChange, itemToStringLabel, …); see the Base UI Autocomplete API reference.
CommandDialog
Wraps the palette in our Dialog (installed as a dependency), positioned at the top third with no close button.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | 'Command Palette' | Screen-reader-only dialog title. |
description | string | 'Search for a command to run…' | Screen-reader-only description. |
CommandGroup
| Prop | Type | Default | Description |
|---|---|---|---|
heading | ReactNode | — | Renders a muted group label above the items. |
Every part accepts a style prop (StyleXStyles, merged last).