Command Palette
⌘K — a search field over every action in the app, opened from anywhere.
Walkthrough
1. Basic
Groups of rows, each with a label and optionally an icon, a shortcut, a description or keywords. Type to fuzzy-match — "nwis" finds "New issue". hotkey is ⌘J here because this site already answers to ⌘K.
Last run: nothing yet
<script lang="ts"> import { Button, CommandPalette, Kbd, Text, type CommandGroup } from 'omaris'; let open = $state(false); let ran = $state('nothing yet'); const items: CommandGroup[] = [ { heading: 'Go to', items: [ { id: 'dashboard', label: 'Dashboard', icon: home, onselect: () => (ran = 'Dashboard') }, { id: 'orders', label: 'Orders', icon: box, onselect: () => (ran = 'Orders') }, { id: 'settings', label: 'Settings', keywords: ['preferences', 'account', 'profile'], icon: gear, shortcut: 'mod+,', onselect: () => (ran = 'Settings') } ] }, { heading: 'Actions', items: [ { id: 'new-order', label: 'New order', description: 'Start a blank order', icon: plus, shortcut: 'mod+shift+o', onselect: () => (ran = 'New order') }, { id: 'new-issue', label: 'New issue', icon: plus, shortcut: 'c', onselect: () => (ran = 'New issue') } ] } ];</script>{#snippet home()} ...{/snippet}{#snippet box()} ...{/snippet}{#snippet gear()} ...{/snippet}{#snippet plus()} ...{/snippet}<div class="flex flex-col items-center gap-2"> <Button variant="outlined" onclick={() => (open = true)}> Search commands <Kbd keys="mod+j" size="sm" variant="flat" /> </Button> <Text variant="body-sm" tone="muted">Last run: {ran}</Text></div><CommandPalette bind:open {items} hotkey="mod+j" /> 2. Pages and recents
A row with children is a page: it opens as its own list, named by a chip in the field; Backspace on an empty field goes back. A query from the top reaches into every page — type "dark". recentKey remembers what was chosen.
Last run: nothing yet
<script lang="ts"> import { Button, CommandPalette, Text, type CommandGroup } from 'omaris'; let open = $state(false); let ran = $state('nothing yet'); const TEAM = ['Amina Yusuf', 'Dilan Karim', 'Hevi Salih', 'Omar Nasir']; const STATUSES = ['Backlog', 'In progress', 'In review', 'Done']; const items: CommandGroup[] = [ { heading: 'Issue', items: [ { id: 'assign', label: 'Assign to…', placeholder: 'Who should take it?', children: TEAM.map((name) => ({ id: `assign:${name}`, label: name, onselect: () => (ran = `Assigned to ${name}`) })) }, { id: 'status', label: 'Change status…', children: STATUSES.map((status) => ({ id: `status:${status}`, label: status, onselect: () => (ran = `Moved to ${status}`) })) } ] }, { heading: 'Preferences', items: [ { id: 'theme', label: 'Theme…', children: [ { heading: 'Appearance', items: [ { id: 'theme:light', label: 'Light', onselect: () => (ran = 'Light theme') }, { id: 'theme:dark', label: 'Dark', onselect: () => (ran = 'Dark theme') }, { id: 'theme:system', label: 'System', onselect: () => (ran = 'System theme') } ] } ] } ] } ];</script><div class="flex flex-col items-center gap-2"> <Button variant="tonal" onclick={() => (open = true)}>Issue actions</Button> <Text variant="body-sm" tone="muted">Last run: {ran}</Text></div><CommandPalette bind:open {items} hotkey={false} recentKey="omaris-docs-palette-recent" recent={3} placeholder="What do you want to do?"/> 3. Server search
When a server does the searching: bind:query to send what is typed, filter={false} to show the answer exactly as it came back, and loading for the line under the field while it is on its way.
Picked: nobody yet
<script lang="ts"> import { Button, CommandPalette, Text, type CommandGroup } from 'omaris'; const CUSTOMERS = [ 'Zagros Café', 'Nishtiman Books', 'Erbil Bakery', 'Tigris Tailors', 'Sulaymaniyah Print House', 'Duhok Dairy', 'Basra Marine Supply' ]; let open = $state(false); let query = $state(''); let loading = $state(false); let results = $state<CommandGroup[]>([]); let picked = $state('nobody yet'); /** Stands in for `fetch('/api/customers?q=…')`. */ $effect(() => { const q = query.trim().toLowerCase(); loading = true; const timer = setTimeout(() => { const items = CUSTOMERS.filter((name) => name.toLowerCase().includes(q)).map((name) => ({ id: name, label: name, description: 'Customer', onselect: () => (picked = name) })); results = items.length ? [{ heading: 'Customers', items }] : []; loading = false; }, 400); return () => clearTimeout(timer); });</script><div class="flex flex-col items-center gap-2"> <Button variant="outlined" onclick={() => (open = true)}>Find a customer</Button> <Text variant="body-sm" tone="muted">Picked: {picked}</Text></div><CommandPalette bind:open bind:query items={results} filter={false} {loading} hotkey={false} placeholder="Search customers…"/> 4. Overridden
class narrows the dialog, classes reaches the field, the rows and the highlight, footer replaces the key hints — here in Arabic, with every label translated and the page mirrored.
آخر أمر: —
<script lang="ts"> import { Button, CommandPalette, Text, type CommandGroup } from 'omaris'; let open = $state(false); let ran = $state('—'); const items: CommandGroup[] = [ { heading: 'الطلبات', items: [ { id: 'ar-new', label: 'طلب جديد', shortcut: 'mod+n', onselect: () => (ran = 'طلب جديد') }, { id: 'ar-orders', label: 'كل الطلبات', onselect: () => (ran = 'كل الطلبات') } ] }, { heading: 'المظهر', items: [ { id: 'ar-theme', label: 'تغيير المظهر', children: [ { id: 'ar-light', label: 'فاتح', onselect: () => (ran = 'فاتح') }, { id: 'ar-dark', label: 'داكن', onselect: () => (ran = 'داكن') } ] } ] } ];</script><div dir="rtl" lang="ar" class="flex flex-col items-center gap-2"> <Button variant="outlined" onclick={() => (open = true)}>لوحة الأوامر</Button> <Text variant="body-sm" tone="muted">آخر أمر: {ran}</Text> <CommandPalette bind:open {items} dir="rtl" lang="ar" hotkey={false} label="لوحة الأوامر" placeholder="اكتب أمرًا أو ابحث…" backLabel="رجوع" clearLabel="مسح" class="max-w-lg" classes={{ header: 'bg-surface-container-low', option: 'rounded-full', highlight: 'text-tertiary underline decoration-2 underline-offset-4' }} > {#snippet empty(query)} <Text variant="body-md" tone="muted">لا نتائج لـ «{query}»</Text> {/snippet} {#snippet footer()} <Text as="span" variant="label-sm">↑↓ للتنقل · ↵ للاختيار · esc للإغلاق</Text> {/snippet} </CommandPalette></div>