Overlays · Command
Command
⌘K command palette. Soma owns fuzzy scoring
(computeFuzzyScore), keyboard nav (arrow + vim
bindings + typeahead + loop + grid columns + RTL), item
visibility and the imperative CommandApi. Eidos
paints the palette chrome, exposes size
(sm/md/lg), adds Item.Icon / Item.Shortcut
sub-parts, and provides a <Command.Dialog>
composition wired to the eidos Dialog with an optional
mod+k shortcut binding.
parts {compiled.parts.order.length}
events {events.length}
sizes 3
apg
combobox ↗
{#if lastInvoked}
last {lastInvoked}
{/if}
No commands match.
Files
📄
New file
⌘N
📁
Open file…
⌘O
💾
Save file
⌘S
Edit
↶
Undo
⌘Z
↷
Redo
⇧⌘Z
🔍
Find in file
⌘F
Help
📚
Open documentation
↗
ℹ︎
About (disabled)
trace
{#if trace.length === 0}
type or arrow-nav to highlight, Enter to invoke
{:else}
{#each trace.slice(0, 3) as entry}
{entry.event} · {entry.family}{entry.intent ? ' · ' + entry.intent : ''}
{fmtTime(entry.at)}
{/each}
{/if}
value {value || '—'}
(dialogOpen = !dialogOpen)}
style="padding: var(--uix-space-2) var(--uix-space-4); border: 1px solid var(--color-border-default); border-radius: var(--radius-md); background: var(--color-surface-raised); cursor: pointer;"
>
{dialogOpen ? 'Close' : 'Open'} Command.Dialog (or press {dialogShortcut})
No matches.
Quick actions
+
New project
⌘N
🔍
Global search
⌘P
⚙︎
Open settings
⌘,
(tab = 'live')}>Live
(tab = 'api')}>
API 15
(tab = 'morfo')}>
morfo
{partsList.length}p · {events.length}e
(tab = 'sema')}>
sema
{events.length}
(tab = 'recipe')}>Recipe
(tab = 'a11y')}>A11y
{#if tab === 'live'}
{/if}
{#if tab === 'api'}
API reference
13 soma parts plus 3 eidos additions: Command.Dialog
(wraps eidos Dialog), Command.Item.Icon and
Command.Item.Shortcut (Item layout sub-parts).
Provider (Command)
Prop Type Default Description
value bindable string '' Currently highlighted item value.
search bindable string '' Current search string.
shouldFilter boolean true Whether to run the scoring filter over items.
filter CommandFilterFn computeFuzzyScore Custom scoring function. Return 0 to exclude.
loop boolean false Loop keyboard navigation at the edges.
vimBindings boolean true Ctrl+N/J = next, Ctrl+P/K = previous.
columns number 1 Grid columns — arrows move ±1 (Right/Left) or ±columns (Down/Up).
disablePointerSelection boolean false Hovering items doesn't change the highlight.
dir 'ltr' | 'rtl' from soma config Grid arrow inversion in RTL.
size eidos ResponsiveProp<'sm' | 'md' | 'lg'> 'md' Visual size — input height + item height + font.
shortcut eidos string | string[] — Optional keyboard shortcut (e.g. 'mod+k') that toggles open. Requires bindable open.
Item
Prop Type Default Description
value string required Unique value used by the scorer.
keywords readonly string[] [] Text aliases the scorer also matches.
disabled boolean false Disable activation. Still focusable.
forceMount boolean false Render even when filtered out.
onSelect () => void — Fired on Enter or click.
Item.Icon / Item.Shortcut eidos
Sub-parts of Item. Both accept children; the recipe handles layout — Icon is a leading flex slot, Shortcut is pushed to row's end via margin-inline-start: auto. Pair with <Kbd> for richer shortcut styling.
Command.Dialog eidos
Prop Type Default Description
open bindable boolean false Dialog open state.
shortcut string | string[] | null 'mod+k' Keyboard binding(s) to toggle. null disables.
size 'sm' | 'md' | 'lg' 'md' Inner Command palette size.
dialogSize DialogSize 'md' Eidos Dialog panel size (sm | md | lg | xl | full).
modal · label · value · search · shouldFilter · filter · loop · … pass-through — Forwarded to Dialog + Command.
{/if}
{#if tab === 'morfo'}
morfo
· declarative contract
Source: src/uix/morfo/components/command.ts.
Field Value
name "{commandMorfo.name}"
kebab "{commandMorfo.kebab}"
scope [{commandMorfo.scope.map((s) => `"${s}"`).join(', ')}]
parts.length {commandMorfo.parts.length}
events.length {events.length}
Parts
Part Marker Element Role Archetype States Optional
{#each partsList as part (part.kebab)}
{part.kebab}
[{part.marker}]
<{part.defaultElement}>
{part.role ?? '—'}
{part.archetype ?? '—'}
{part.states.length ? part.states.join(' | ') : '—'}
{part.optional ? 'yes' : 'no'}
{/each}
Events declaration
name family verb sequence intent target
{#each events as action (action.name)}
{@const sem = action.semantic}
{@const intentDecl = 'intent' in sem ? sem.intent : undefined}
{@const intentStr = typeof intentDecl === 'string' ? intentDecl : intentDecl ? `fromProp:${(intentDecl as { fromProp?: string }).fromProp ?? '?'}` : '—'}
{action.name}
{sem.family}
{sem.verb ?? '—'}
{sem.sequence ?? 'pre'}
{intentStr}
{action.target}
{/each}
{/if}
{#if tab === 'sema'}
sema
· events + perceptual signature
One event: commit-invoke fires when the user
activates a highlighted Item (Enter or click). Verb submit,
intent fulfill.
Name Family Verb Sequence Intent Play
{#each events as action (action.name)}
{@const intentDecl = 'intent' in action.semantic ? action.semantic.intent : undefined}
{@const effectiveIntent = typeof intentDecl === 'string' ? intentDecl : undefined}
{action.name}
{action.semantic.family}
{action.semantic.verb ?? '—'}
{action.semantic.sequence ?? 'pre'}
{effectiveIntent ?? '—'}
{
const target = (stageRef?.querySelector('[data-command-item]') ?? stageRef) as HTMLElement | null;
if (!target) return;
void uix.events?.emit({
name: action.name,
family: action.semantic.family,
target,
...(effectiveIntent ? { intent: effectiveIntent } : {})
});
}}
>▶ play
{/each}
{/if}
{#if tab === 'recipe'}
Eidos recipe
Selectors at src/uix/eidos/components/command/command.css.
Inside <Command.Dialog> the dialog panel chrome
comes from dialog.css and the inner palette uses these
selectors.
Selector Source What it paints
[data-command] eidos Palette container — flex column, border, surface bg.
[data-command][data-size] eidos Size variant — input + item heights, font-size.
[data-command-input] morfo Search input row + divider.
[data-command-list], [data-command-viewport] morfo Scrolling list.
[data-command-item], [data-command-link-item] morfo Row — flex, padding, gap.
[data-command-item][data-selected] morfo Highlighted row tint.
[data-command-item-icon], [data-command-item-shortcut] eidos Item sub-part layout slots — icon fixed, shortcut auto-end.
[data-command-group-heading] morfo Muted uppercase group label.
[data-command-separator] morfo 1px divider between groups.
{/if}
{#if tab === 'a11y'}
Accessibility
Follows the APG combobox pattern with a listbox popup. Input has role="combobox"; List is role="listbox"; each Item is role="option".
Keyboard
Key Action
ArrowDown / ArrowUp Move highlight ±1 (or ±columns if columns > 1).
ArrowRight / ArrowLeft In grid mode, move ±1 column (RTL inverts).
Ctrl+N / Ctrl+J Next (vim binding, if vimBindings=true).
Ctrl+P / Ctrl+K Previous (vim binding).
Home / End First / last visible item.
Enter Activate highlighted item — fires onSelect + commit-invoke.
Escape Clear search (or close dialog if inside Command.Dialog).
mod+k Toggle dialog open/close (if shortcut is configured).
ARIA contract
Part Attribute Value
input role "combobox"
input aria-expanded "true" (always while palette is mounted)
input aria-controls {``}
input aria-activedescendant {``}
list role "listbox"
item role "option"
item aria-selected "true" (when highlighted)
item aria-disabled "true" (when disabled)
{/if}