Overlay
Command
A search-enabled command palette with grouped items, keyboard navigation, filtering, and custom rendering. Built on bits-ui Command.
Playground
Experiment with different props.
Basic Usage
Pass groups with items. Built-in search filters items as you type.
<script lang="ts">
import { Command } from 'sv5ui';
const groups = [
{
id: 'actions',
label: 'Actions',
items: [
{ value: 'new-file', label: 'New File', icon: 'lucide:file-plus' },
{ value: 'new-folder', label: 'New Folder', icon: 'lucide:folder-plus' },
{ value: 'search', label: 'Search', icon: 'lucide:search' }
]
}
];
</script>
<Command {groups} placeholder="Type a command..." />Grouped Items
Organize commands into labeled groups with automatic separators.
<Command groups={[
{
id: 'suggestions',
label: 'Suggestions',
items: [
{ value: 'calendar', label: 'Calendar', icon: 'lucide:calendar' },
{ value: 'search', label: 'Search Emoji', icon: 'lucide:smile' },
{ value: 'calculator', label: 'Calculator', icon: 'lucide:calculator' }
]
},
{
id: 'settings',
label: 'Settings',
items: [
{ value: 'profile', label: 'Profile', icon: 'lucide:user' },
{ value: 'billing', label: 'Billing', icon: 'lucide:credit-card' },
{ value: 'preferences', label: 'Preferences', icon: 'lucide:settings' }
]
}
]} />With Description
Add secondary text to items.
<Command groups={[
{
id: 'pages',
label: 'Pages',
items: [
{ value: 'home', label: 'Home', description: 'Go to the home page', icon: 'lucide:home' },
{ value: 'docs', label: 'Documentation', description: 'Browse component docs', icon: 'lucide:book-open' },
{ value: 'blog', label: 'Blog', description: 'Read latest articles', icon: 'lucide:pen-line' }
]
}
]} />onSelect Callback
Execute actions when items are selected.
<script lang="ts">
import { Command } from 'sv5ui';
import { toast } from 'sv5ui';
const groups = [{
id: 'actions',
items: [
{ value: 'copy', label: 'Copy', icon: 'lucide:copy', onSelect: () => toast('Copied!') },
{ value: 'paste', label: 'Paste', icon: 'lucide:clipboard', onSelect: () => toast('Pasted!') },
{ value: 'delete', label: 'Delete', icon: 'lucide:trash-2', onSelect: () => toast.error('Deleted!') }
]
}];
</script>
<Command {groups} />Search Keywords
Add keywords so items can be found by alternative search terms. Try typing "dark" or "console".
<!-- Keywords help users find items with alternative search terms -->
<Command groups={[{
id: 'tools',
items: [
{ value: 'theme', label: 'Toggle Theme', icon: 'lucide:sun', keywords: ['dark', 'light', 'mode'] },
{ value: 'zoom', label: 'Zoom In', icon: 'lucide:zoom-in', keywords: ['magnify', 'scale', 'bigger'] },
{ value: 'terminal', label: 'Open Terminal', icon: 'lucide:terminal', keywords: ['console', 'shell', 'cmd'] }
]
}]} />Sizes
5 sizes.
sm
md
lg
<Command {groups} size="sm" />
<Command {groups} size="md" />
<Command {groups} size="lg" />Disabled Items
<Command groups={[{
id: 'items',
items: [
{ value: 'active', label: 'Active Item', icon: 'lucide:check' },
{ value: 'disabled', label: 'Disabled Item', icon: 'lucide:ban', disabled: true },
{ value: 'another', label: 'Another Item', icon: 'lucide:plus' }
]
}]} />Loading
<Command {groups} loading />In a Modal (Cmd+K)
Classic command palette pattern. Press + K or click below.
<script lang="ts">
import { Command, Modal, Button, Kbd } from 'sv5ui';
import { useKbd } from 'sv5ui';
let open = $state(false);
useKbd({
shortcuts: {
'ctrl+k': () => open = !open
}
});
</script>
<Button variant="outline" color="surface" onclick={() => open = true}>
Search...
{#snippet trailingSlot()}
<Kbd value="ctrl" size="sm" /> <Kbd value="K" size="sm" />
{/snippet}
</Button>
<Modal bind:open ui={{ content: 'p-0 max-w-lg' }} close={false} title="">
{#snippet content()}
<Command {groups} size="sm" />
{/snippet}
</Modal>Custom Empty Text
<Command {groups} emptyText="No commands match your search." />UI Slots
Use the ui prop to override classes on internal elements.
| Slot | Description |
|---|---|
root | Main container |
inputWrapper | Search input wrapper |
inputIcon | Search icon |
input | Input element |
list | Items list container |
empty | Empty state |
loading | Loading state |
group | Group container |
groupHeading | Group heading text |
separator | Divider between groups |
item | Individual item |
itemIcon | Item leading icon |
itemLabel | Item label text |
itemDescription | Item description text |
itemTrailing | Item trailing section |
footer | Footer container |
Snippets
| Snippet | Description |
|---|---|
item | Custom item rendering (receives item, index) |
itemLeading | Custom leading section (icon area) |
itemLabel | Custom label section |
itemTrailing | Custom trailing section |
empty | Custom empty state (receives search term) |
footer | Footer content |
Props
| Prop | Type | Default |
|---|---|---|
groups | CommandGroup[] | - |
search | string | '' |
value | string | - |
placeholder | string | 'Type a command...' |
size | 'xs'|'sm'|'md'|'lg'|'xl' | 'md' |
icon | string | - |
loading | boolean | false |
emptyText | string | 'No results found.' |
loop | boolean | - |
shouldFilter | boolean | true |
onValueChange | (value) => void | - |
ref | HTMLElement | null | null |
class | string | - |
ui | Record<Slot, Class> | - |
Item Props
| Prop | Type | Default |
|---|---|---|
value | string | - |
label | string | - |
description | string | - |
icon | string | - |
keywords | string[] | - |
disabled | boolean | false |
onSelect | () => void | - |
class | string | - |
Group Props
| Prop | Type | Default |
|---|---|---|
id | string | - |
label | string | - |
items | CommandItem[] | - |