Recipes
05
CommandPalette
⌘K search over a command list — a real listbox with full keyboard navigation.
rendered by aura-react
rendered by aura-react
rendered by aura-react
rendered by aura-react
rendered by aura-react
Code
Demo.tsx
import { useMemo, useState } from 'react';
import { Button, Dialog, Field, Typography } from '@ilomee/aura-react';
const COMMANDS = [
{ id: 'theme', label: 'Toggle theme' },
{ id: 'accent', label: 'Change accent', description: '10 to choose from' },
{ id: 'docs', label: 'Open docs' },
];
// A palette is a Dialog, a Field and a list you filter. `Dialog` brings the scrim, the trap and
// Escape; `Select`'s own listbox brings the keyboard when the list has to be arrowed through.
// This is the shape, not a component: what a palette *does* is your commands.
export default function Demo() {
const [open, setOpen] = useState(true);
const [query, setQuery] = useState('');
const shown = useMemo(
() => COMMANDS.filter((c) => c.label.toLowerCase().includes(query.toLowerCase())),
[query],
);
return (
<>
<Button variant="primary" onClick={() => setOpen(true)}>
Open palette
</Button>
<Dialog open={open} onClose={() => setOpen(false)} label="Commands" top autoFocus={false}>
<Field label="Command" value={query} onValueChange={setQuery} placeholder="Type a command…" />
<ul className="aura-listbox" role="listbox" aria-label="Commands" style={{ marginTop: 12 }}>
{shown.map((command) => (
<li key={command.id} className="aura-listbox__option" role="option" aria-selected="false">
<span className="aura-listbox__label">
{command.label}
{command.description && (
<span className="aura-listbox__description">{command.description}</span>
)}
</span>
</li>
))}
{shown.length === 0 && <li className="aura-listbox__empty">Nothing matches.</li>}
</ul>
<Typography variant="caption" tone="faint" style={{ marginTop: 12 }}>
Wire ⌘K to `setOpen(true)` — the shortcut is the app's, not the dialog's.
</Typography>
</Dialog>
</>
);
}This is an example, not a component — no package ships it, and there is nothing to import. It is built from primitives that each of the four packages does ship, so the same composition works in every stack; copy it into your own component and it is yours to change.
Props
No props: the composition takes what you give the primitives inside it. Their props are on their own pages.
Emitted classes
Every framework emits the same classes — that is what makes the four libraries look identical. You can use them directly, without any component library.
| Class | Role | Notes |
|---|---|---|
| .aura-overlay | base | Required. A modifier does nothing without it. |
| .aura-popup | base | Required. A modifier does nothing without it. |