Skip to content

components/palette/PalettePanel

import { … } from 'zidane-ui'ui/src/components/palette/PalettePanel.tsx

Components#

PalettePanelComponent#

Renders the Cmd+K surface: the query as the header, the ranked sections, a footer that says what Enter does, and an optional notice. It is controlled: the caller owns the query, the cursor and what running a row means. The input takes focus on mount and handles the arrows, Home, End, Enter, Escape and Backspace on an empty nested query. It brings no scrim or focus trap, so mount it in a layer such as Overlay.

TypeScript
function PalettePanel<T extends PaletteEntry>(props: PalettePanelProps<T>): Element
Type parameters
NameTypeDescription
Textends PaletteEntry
Parameters
NameTypeDescription
propsPalettePanelProps<T>

PalettePanelProps.

Element
PalettePanel props
NameTypeDefaultDescription
cursornumber

Flat index of the marked row, across sections.

groupsreadonly PaletteSection<T>[]

The ranked sections to show.

inputRef?Ref<HTMLInputElement>

Ref to the query input.

loading?boolean

The rows are not known yet.

nested?boolean

A nested level: a back button, and Backspace on an empty query calls it.

notice?PaletteNotice | null

A status line shown under the footer.

onBack?() => void

Called by the back button, and by Backspace on an empty query, to leave a nested level.

onClose() => void

Escape in the input.

onCursorChange(index: number) => void

Called with a new flat row index when the arrows, Home, End or the pointer move the cursor.

onQueryChange(query: string) => void

Called with the new text when the query changes. The cursor resets to the first row.

onRun(row: PaletteRowData<T>) => void

Called with the marked row on Enter, or with a clicked row.

onScopeClear?() => void

Backspace on an empty query at the root while scoped: search every section again.

onScopeNext?() => void

Shift+Tab at the root: scope the search to the next section (after the last, back to every section).

placeholder?string

Defaults to the labels' paletteFilter.

querystring

The query in the input.

renderIcon?(row: PaletteRowData<T>) => ReactNode

Draws the default row's icon. A dot shows when omitted.

renderKeys?PaletteKeysdefaultPaletteKeys

Draws a keybinding spec as keycaps.

renderRow?(props: PaletteRowProps<T>) => ReactNode

Draws a row. Return undefined for the default row. Keep it stable, since rows are memoized.

running?boolean

A row is running: a spinner in the header.

scope?string

The section the root search is scoped to, as a chip before the query.

settled?boolean

False while the rows are still for an earlier query: Enter waits for them. Default true.

title?string

The level's name, as a chip before the query.

verb?(row: PaletteRowData<T>, nested: boolean) => string | undefined

The footer's word for Enter on the marked row; undefined falls back to paletteVerb.

ui/src/components/palette/PalettePanel.tsx:142

Functions#

paletteVerbFunction#

What Enter does to a row by its kind; an app names its own kinds first (verb).

TypeScript
function paletteVerb(
  row: PaletteRowData<PaletteEntry> | undefined,
  nested: boolean,
  labels: { addDiagnosticToChat: (message: string) => string; address: string; addressPlaceholder: string; addToChat: string; back: string; cancel: string; close: string; closeTab: (name: string) => string; code: string; completionSuggestions: string; confirm: string; continue: string; copied: string; copy: string; copyCode: string; copyImage: string; copyImageBase64: string; copyImageDataUrl: string; current: string; diagnosticsCheckedBy: (source: string) => string; diagnosticsChecking: string; diagnosticsNone: string; editorConflict: string; editorConflictDetail: string; editorEmpty: string; editorOverwrite: string; editorReadFailed: (message: string) => string; editorReload: string; errorFailed: (region: string) => string; errorStack: string; errorTryAgain: string; filePath: (path: string) => string; fileReadOnly: (path: string) => string; fileTree: string; fileUnsaved: string; fileUnsavedTitle: (path: string) => string; findClose: string; findCloseHint: string; findInFile: string; findMatchCase: string; findNext: string; findNextHint: string; findNoResults: string; findPrevious: string; findPreviousHint: string; findReferences: string; goToDefinition: string; goToStep: (step: string) => string; loading: string; modalBack: string; modalFailed: string; next: string; noReferences: string; of: (index: number, count: number) => string; openFiles: string; openInNewTab: string; paletteBack: string; paletteBackHint: string; paletteChoose: string; paletteEmpty: string; paletteFilter: string; paletteLabel: string; paletteLoading: string; paletteNoMatch: (query: string) => string; paletteOpen: string; paletteRun: string; paletteScopeHint: string; paletteTurnOff: string; paletteTurnOn: string; previous: string; reload: string; rename: string; retry: string; screenBack: (screen: string) => string; screenBackKey: string; signInCopyCode: string; signInDone: (account?: string) => string; signInEnterCode: (host: string) => string; signInFailed: string; signInInBrowser: (service: string) => string; signInNotOpened: string; signInOpenPage: string; signInPaste: string; signInStarting: string; signInSubmit: string; skip: string; stepOf: (index: number, count: number) => string; steps: string; terminal: string; terminalExited: (code: number) => string; terminalLoadFailed: (message: string) => string; working: string; wrapLines: string; zoomFit: string; zoomPercent: (percent: number) => string },
): string
Parameters
NameTypeDescription
rowPaletteRowData<PaletteEntry> | undefined

The marked row. When undefined, the run label is used.

nestedboolean

Whether the palette is at a nested picker level, where a toggle row is chosen instead of switched.

labels{ addDiagnosticToChat: (message: string) => string; address: string; addressPlaceholder: string; addToChat: string; back: string; cancel: string; close: string; closeTab: (name: string) => string; code: string; completionSuggestions: string; confirm: string; continue: string; copied: string; copy: string; copyCode: string; copyImage: string; copyImageBase64: string; copyImageDataUrl: string; current: string; diagnosticsCheckedBy: (source: string) => string; diagnosticsChecking: string; diagnosticsNone: string; editorConflict: string; editorConflictDetail: string; editorEmpty: string; editorOverwrite: string; editorReadFailed: (message: string) => string; editorReload: string; errorFailed: (region: string) => string; errorStack: string; errorTryAgain: string; filePath: (path: string) => string; fileReadOnly: (path: string) => string; fileTree: string; fileUnsaved: string; fileUnsavedTitle: (path: string) => string; findClose: string; findCloseHint: string; findInFile: string; findMatchCase: string; findNext: string; findNextHint: string; findNoResults: string; findPrevious: string; findPreviousHint: string; findReferences: string; goToDefinition: string; goToStep: (step: string) => string; loading: string; modalBack: string; modalFailed: string; next: string; noReferences: string; of: (index: number, count: number) => string; openFiles: string; openInNewTab: string; paletteBack: string; paletteBackHint: string; paletteChoose: string; paletteEmpty: string; paletteFilter: string; paletteLabel: string; paletteLoading: string; paletteNoMatch: (query: string) => string; paletteOpen: string; paletteRun: string; paletteScopeHint: string; paletteTurnOff: string; paletteTurnOn: string; previous: string; reload: string; rename: string; retry: string; screenBack: (screen: string) => string; screenBackKey: string; signInCopyCode: string; signInDone: (account?: string) => string; signInEnterCode: (host: string) => string; signInFailed: string; signInInBrowser: (service: string) => string; signInNotOpened: string; signInOpenPage: string; signInPaste: string; signInStarting: string; signInSubmit: string; skip: string; stepOf: (index: number, count: number) => string; steps: string; terminal: string; terminalExited: (code: number) => string; terminalLoadFailed: (message: string) => string; working: string; wrapLines: string; zoomFit: string; zoomPercent: (percent: number) => string }

The label set to take the verb from.

string

The word for what Enter does: choose, turn on, turn off, open or run.

ui/src/components/palette/PalettePanel.tsx:65

Interfaces#

PaletteNoticeInterface#

A line of status text under the palette's footer.

TypeScript
interface PaletteNotice
PaletteNotice properties
NameTypeDefaultDescription
textstring

The message.

tone?'error' | 'warn' | 'info''info'

Colour of the message: muted for info, warning for warn, danger for error.

ui/src/components/palette/PalettePanel.tsx:46

Types#

PalettePanelPropsType#

Props of PalettePanel: the controlled palette state and callbacks, plus the attributes of the panel's div.

TypeScript
type PalettePanelProps<T extends PaletteEntry = PaletteEntry> = PanelElementProps & { cursor: number; groups: readonly PaletteSection<T>[]; inputRef?: Ref<HTMLInputElement>; loading?: boolean; nested?: boolean; notice?: PaletteNotice | null; onBack?: () => void; onClose: () => void; onCursorChange: (index: number) => void; onQueryChange: (query: string) => void; onRun: (row: PaletteRowData<T>) => void; onScopeClear?: () => void; onScopeNext?: () => void; placeholder?: string; query: string; renderIcon?: (row: PaletteRowData<T>) => ReactNode; renderKeys?: PaletteKeys; renderRow?: (props: PaletteRowProps<T>) => ReactNode; running?: boolean; scope?: string; settled?: boolean; title?: string; verb?: (row: PaletteRowData<T>, nested: boolean) => string | undefined }
PalettePanelProps type parameters
NameTypeDefaultDescription
Textends PaletteEntryPaletteEntry

ui/src/components/palette/PalettePanel.tsx:81