Command palette
In reviewLive · web
Press ⌘K (or Ctrl-K) inside the stage: type, ↑↓, Enter, Esc
Press ⌘ K or the button above to launch
No command run yet. Launch the palette and press Enter on a row.
// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform. Spec + live demo,// not yet exported from @dizyx/nockerl-react; promotion is tracked.)
const commands = [ { id: 'new-session', label: 'New session', hint: 'Start a fresh session', group: 'Actions', icon: 'plus', shortcut: ['⌘', 'N'], run: createSession }, { id: 'go-inbox', label: 'Go to Inbox', hint: '3 unread', group: 'Navigation', icon: 'inbox', shortcut: ['G', 'I'], run: => navigate('/inbox') }, { id: 'recent-design', label: 'nockerl-design · docs', group: 'Recent', icon: 'doc', run: => openSession('design') },];
export function App() { const [open, setOpen] = useState(false); // ⌘K / Ctrl-K toggles the palette from anywhere. useHotkey('mod+k', => setOpen((v) => !v));
return ( <CommandPalette open={open} onOpenChange={setOpen} commands={commands} groupOrder={['Actions', 'Navigation', 'Recent']} placeholder="Type a command or search…" /> );}// Android: Jetpack Compose. No physical ⌘K; the launcher is a modal that// reuses NockerlBottomSheet (the shipped elevated-over-scrim idiom). Opened// from the GlobalTopBar search affordance. (Intended API; see drift note.)import com.nockerl.app.core.ui.NockerlCommandPaletteimport com.nockerl.app.core.ui.CommandGroup
NockerlCommandPalette( visible = uiState.paletteOpen, onDismissRequest = viewModel::closePalette, query = uiState.query, onQueryChange = viewModel::onQueryChange, commands = uiState.commands, // filtered + bucketed by group groupOrder = listOf( CommandGroup.ACTIONS, CommandGroup.NAVIGATION, CommandGroup.RECENT, ), onRun = viewModel::run, // ripple + haptic on tap placeholder = "Type a command or search…",)// macOS: SwiftUI. The trigger is a real .keyboardShortcut("k", modifiers: .command)// (the same modifier Voice uses for ⌘D / ⌘Q in MenuBarContent.swift). The sheet// floats over a scrim; rows surface their per-row shortcut as monospaced hints.struct RootView: View { @State private var paletteOpen = false @State private var query = ""
var body: some View { WorkspaceView() .background( Button("") { paletteOpen.toggle() } .keyboardShortcut("k", modifiers: .command) // ⌘K .hidden() ) .sheet(isPresented: $paletteOpen) { NockerlCommandPalette( query: $query, commands: commands, // filtered + grouped (Actions / Navigation / Recent) placeholder: "Type a command or search…", onRun: { command in run(command); paletteOpen = false } ) } }}Parameters
Section titled “Parameters”| Prop | Type | Default | Description |
|---|---|---|---|
open * | boolean | Whether the palette is shown. Drops a scrim and floats the panel near top-center. | |
onOpenChange * | (open: boolean) => void | Fired on Esc, scrim click, or after a command runs. Focus is restored to the trigger on close. | |
commands * | Command[] | The full set. Each: { id, label, hint?, group, icon, shortcut?, run, disabled? }. Filtered live by what is typed (label + hint substring). | |
groupOrder | string[] | ['Actions','Navigation','Recent'] | Section order. Headers render above each non-empty bucket; ↑↓ flow across groups in this order. |
placeholder | string | 'Search…' | Search-field placeholder. The field is a persistent input, never a label. |
emptyLabel | string | 'No results' | Shown with the query when nothing matches, above a quiet “Try a different search.” |
| Parameter | Type | Default | Description |
|---|---|---|---|
visible * | Boolean | Whether the palette sheet is shown. Built on NockerlBottomSheet (elevated over the scrim token). | |
onDismissRequest * | () -> Unit | Invoked on scrim tap, back gesture, or system dismiss. | |
query * | String | Current search text (recessed well). Pair with onQueryChange for live filtering. | |
onQueryChange * | (String) -> Unit | Emits on each keystroke from a connected keyboard or IME. | |
commands * | List<NockerlCommand> | Filtered + bucketed entries: id, label, hint?, group, icon, shortcut?, enabled. | |
groupOrder | List<CommandGroup> | ACTIONS, NAVIGATION, RECENT | Section order; a quiet header precedes each non-empty bucket. |
onRun * | (NockerlCommand) -> Unit | Invoked on row tap: ripple + haptic. No-op for a disabled row. | |
placeholder | String | "Search…" | Search-field placeholder for the recessed well. |
SwiftUI exposes the palette as a View presented in a .sheet; the ⌘K trigger is a
standard .keyboardShortcut("k", modifiers: .command). State lives in @State
bindings; there is no explicit open parameter on the view itself.
| Style | Type | Default | Description |
|---|---|---|---|
query | Binding<String> | Two-way bound search text in the recessed field. Filters via localizedCaseInsensitiveContains (the HistoryView idiom). | |
commands | [NockerlCommand] | Filtered + grouped entries (id, label, hint?, group, icon, shortcut?, isEnabled); per-row shortcut renders as monospaced kbd hints. | |
placeholder | String | Search-field prompt. The field carries a leading magnifier glyph. | |
onRun | (NockerlCommand) -> Void | Closure run when a row is chosen (click or ↵). Dismiss the sheet inside it. |