Overlays
Command palette
Finds and runs any command by typing a few letters. Opens with ⌘ K (Ctrl K on Windows and Linux).
Installation
npx sinaui add command-paletteCopy src/lib/ui/CommandPalette.svelte, glide.ts, announce.ts, Icon.svelte and tokens.css. No other dependencies.
Examples
Basic
Matches the start of a label first, then the start of a word, then anywhere, then keywords; accents don't matter.
Try “qara”, “cordoba” or “share”.
<script lang="ts">
import {
Book02Icon,
BookOpen01Icon,
Location01Icon,
Moon02Icon,
Search01Icon,
Share08Icon,
Sun03Icon
} from '@hugeicons/core-free-icons';
import Button from '#lib/ui/Button.svelte';
import CommandPalette, { type Command } from '#lib/ui/CommandPalette.svelte';
let open = $state(false);
let last = $state<string>();
const did = (what: string) => () => (last = what);
const commands: Command[] = [
{
id: 'borrow',
label: 'Borrow a manuscript',
group: 'Library',
icon: BookOpen01Icon,
shortcut: ['B'],
onselect: did('Borrow a manuscript')
},
{
id: 'return',
label: 'Return a manuscript',
group: 'Library',
icon: Book02Icon,
onselect: did('Return a manuscript')
},
{
id: 'search',
label: 'Search the catalog',
group: 'Library',
icon: Search01Icon,
keywords: ['find', 'look up'],
shortcut: ['/'],
onselect: did('Search the catalog')
},
{
id: 'share',
label: 'Copy link to this page',
group: 'Library',
icon: Share08Icon,
keywords: ['share', 'url'],
onselect: did('Copy link')
},
{
id: 'baghdad',
label: 'Bayt al-Ḥikma, Baghdad',
group: 'Go to',
icon: Location01Icon,
keywords: ['house of wisdom', 'iraq'],
onselect: did('Go to Baghdad')
},
{
id: 'fez',
label: 'Al-Qarawiyyīn, Fez',
group: 'Go to',
icon: Location01Icon,
keywords: ['morocco'],
onselect: did('Go to Fez')
},
{
id: 'cordoba',
label: 'Library of Córdoba',
group: 'Go to',
icon: Location01Icon,
keywords: ['andalus', 'spain'],
onselect: did('Go to Córdoba')
},
{
id: 'dark',
label: 'Dark theme',
group: 'Theme',
icon: Moon02Icon,
keywords: ['night', 'appearance'],
onselect: did('Dark theme')
},
{
id: 'light',
label: 'Light theme',
group: 'Theme',
icon: Sun03Icon,
keywords: ['day', 'appearance'],
onselect: did('Light theme')
}
];
</script>
<div class="row">
<Button variant="secondary" onclick={() => (open = true)}>Open command palette</Button>
<p>{last ? `Last command: ${last}` : 'Try “qara”, “cordoba” or “share”.'}</p>
</div>
<!-- This site's own search already answers ⌘K, so this example opens from its button. -->
<CommandPalette {commands} bind:open shortcut={false} />
<style>
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 1rem;
}
.row p {
margin: 0;
color: var(--ui-muted);
font-size: 0.875rem;
}
</style>Props
| Prop | Type | Default |
|---|---|---|
commands | { id, label, onselect, group?, keywords?, shortcut?, icon? }[] | |
open | boolean, bindable | false |
shortcut | boolean | true |
label | string | 'Command palette' |
placeholder, empty | string |
A command's shortcut is shown beside it; the keys themselves are yours to bind.
Accessibility
- A modal dialog: the page behind can't be reached, and closing puts focus back where it was.
- Focus stays in the search box and points at the highlighted command; the number of matches is announced as you type.
- The list keeps one height while you type, so nothing jumps under the pointer.
| Key | Action |
|---|---|
| ⌘ K / Ctrl K | Open or close. |
| ↓ ↑ | Next / previous command, wrapping round. |
| Enter | Run the highlighted command. |
| Esc | Close. |