Skip to content

Command Palette

CommandPalette opens a search field over the page with a list of commands under it. Open it, type “dark”, then press Enter:

Ran: nothing yet

CommandPaletteDemo.tsx
import { Paragraph, View } from '@hozo/core'
import { Button, CommandPalette } from '@hozo/ui'
import { useState } from 'react'
export function CommandPaletteDemo() {
const [open, setOpen] = useState(false)
const [last, setLast] = useState('nothing yet')
const run = (name: string) => () => setLast(name)
return (
<View className="items-start gap-3">
<Button tone="neutral" onPress={() => setOpen(true)}>
Open the command palette
</Button>
<CommandPalette
open={open}
onOpenChange={setOpen}
placeholder="Type a command or search"
commands={[
{
id: 'new',
label: 'New file',
group: 'File',
shortcut: 'Ctrl N',
onSelect: run('New file'),
},
{ id: 'open', label: 'Open recent', group: 'File', onSelect: run('Open recent') },
{
id: 'theme',
label: 'Toggle dark mode',
group: 'View',
keywords: ['theme', 'colour'],
onSelect: run('Toggle dark mode'),
},
{ id: 'zoom', label: 'Zoom in', group: 'View', disabled: true, onSelect: run('Zoom in') },
]}
/>
<Paragraph className="text-sm text-hozo-text-body">{`Ran: ${last}`}</Paragraph>
</View>
)
}
  • commands: { id, label, onSelect, group?, keywords?, shortcut?, disabled? }. Commands with the same group are listed under one heading. keywords match as well as the label, which is why “colour” finds “Toggle dark mode”.
  • open and onOpenChange control it. Opening it is yours to wire, from a button as here or from a key such as Ctrl K in your app.
  • It is a modal dialog holding a combobox. Focus goes into the field, Tab cannot leave the dialog, and Escape or a press outside closes it and puts focus back where it was.
  • The arrow keys move through the commands while focus stays in the field, and Enter runs the highlighted one and closes. As the list narrows, how many commands match is announced politely.
  • shortcut is shown beside a command. It is a label, and it does not bind the key.