Get started

Command palette design system: define commands, states, and safety

A command palette design system should standardize the interaction shell, not the authority behind each action. The shared system can define invocation, input, result anatomy, focus presentation, and generic states. The consuming application must own command definitions, context, permissions, execution, side effects, and recovery.

Updated October 15, 2026

Use a shared shell over an application-owned registry

A command palette looks like search, but its main job is to initiate actions. It may navigate, change application state, open a workflow, or invoke an operation. Sam Solomon describes the practical distinction: search helps people find things, while a command palette lets them do things. That distinction brings application behavior into an interface that can otherwise look like a simple dialog.

Treat the palette as a view over a command registry. The registry stores stable command identities and the application rules needed to resolve them. The shell receives current presentation data such as label, group, scope, availability, and confirmation requirements. It renders those values, then sends the selected intent to an application-owned handler.

The shared system can own the dialog, query input, result layout, focus styling, keyboard conventions, and generic presentations for loading or empty results. It should not import domain permissions, infer the active record, call product services directly, or decide whether an operation succeeded.

Decide whether the pattern fits

Use a command palette when people repeatedly perform actions across a product and the command set is broad enough that menus and shortcuts become slow to scan. It works especially well for experienced users who know the outcome they want but may not remember where the product put it.

A palette is a poor substitute for the next obvious action. Use a visible button for an important step, ordinary navigation for a compact information architecture, and search when the main task is finding content. Search and commands can sit beside each other, but their similar inputs shouldn't obscure their different outcomes.

Best fitMain limitation
Visible button or menuFrequent, important, or high-consequence actionsPersistent space becomes crowded if every action is exposed
Navigation or searchFinding destinations, records, documents, or contentFinding an item does not define an action or its consequences
Keyboard shortcutA small set of stable, frequently repeated actionsShortcuts are hard to discover and can conflict
Command paletteA broad action set used across changing contextsIt is hidden by default and unsuitable as the sole route to essential work
Choose the surface based on the task, not its visual treatment.

Keep essential routes visible

Essential navigation and actions need ordinary product controls. The palette can make those routes faster, but people still need access when they don't know the shortcut, use a touch device, encounter a conflict, or cannot operate the palette.

Assign responsibility before designing states

Start with one ownership matrix before drawing detailed screens. It keeps product policy out of the shared package and shows what every application must supply to the shell.

Design systemConsuming applicationShared review
InvocationLauncher pattern, overlay structure, shortcut displayAllowed surfaces and local shortcut conflictsKeyboard path, small-screen route, focus entry and return
Visual systemTokens, typography, spacing, modes, result anatomyApproved local exceptions and product contentLong text, localization, zoom, and narrow layouts
InteractionInput behavior, active-option treatment, generic keyboard conventionsRouting, workflow handoffs, cancellation semanticsExpected sequence and observable focus behavior
Command definitionField contract and rendering slotsStable IDs, labels, aliases, groups, context, ordering inputsNaming, discoverability, and collisions
AvailabilityTreatments for available, unavailable, hidden, and forbidden outcomesRuntime conditions and reason codesWhether hiding or disabling is appropriate
AuthorizationSlots for scope, restrictions, and warningsPolicy evaluation and enforcementWhether the resolved scope and restriction are understandable
ExecutionProgress, partial-outcome, and completion presentationHandlers, side effects, duplicate control, and cancellationExpected effect and failure behavior
RecoveryPlacement and styling for undo, retry, and support routesRollback, retry, reconciliation, and expiry rulesRecovery copy, ownership, and test evidence
AcceptanceEvidence for the isolated component boundaryRuntime evidence from a named consumerDisposition, correction owner, and retest trigger
The design system owns reusable presentation. The application resolves product-specific meaning and behavior.

Shared review connects the layers without giving them equal authority. For example, the application decides that a command is forbidden, while the design system supplies a supported way to present that result. The application defines a real undo operation; the shared component controls where its action appears.

Define the palette's visual rules upstream

Once ownership and behavior are explicit, a design kit can supply the shell's color roles, typography, spacing, focus treatment, and modes. Keep those visual decisions separate from the application registry.

Write a command record that every role can review

A mockup usually captures a label, icon, and shortcut. An implementation array may add an ID and callback. Contextual commands need more: an availability rule, permission source, consequence, confirmation policy, recovery route, visible alternative, owner, and acceptance status.

The YAML below is a fictional planning fixture, not an implementation result. Its unresolved values are deliberate. They mark the decisions and observations the product team still needs to make.

id: project.archive
label: Archive project
aliases:
  - close project
  - retire project
group: Project
context:
  requires: [activeProjectId]
  resolvedScope: "Current project: Northstar"
availability:
  rule: disable_during_export
  reasonCode: export_in_progress
permission:
  source: project-policy-service
  capability: project.archive
consequence:
  tier: reversible-state-change
  expectedEffect: remove_from_active_projects
confirmation:
  rule: require_when_open_tasks_greater_than_zero
execution:
  owner: project-commands
  handler: archiveProject
recovery:
  route: undo-toast
  expiresAfter: unresolved
alternateAccess:
  route: /projects/:projectId/settings
  control: Archive project
acceptance:
  namedConsumer: web-project-detail
  fixture: active-project-with-two-open-tasks
  declared: proposed
  registered: unverified
  available: unverified
  invoked: unverified
  completed: unverified
  observed: unverified
  disposition: unresolved
  correctionOwner: unassigned
  retestTrigger: handler_or_policy_change
Fictional, unexecuted command record. Replace placeholders with owned product decisions and recorded observations.

Fields that prevent ambiguity

  • Stable identity: keep the ID separate from visible copy so labels can change without breaking permissions, analytics, or integrations.
  • Copy and aliases: record the displayed language and the approved terms that can retrieve the command.
  • Context and availability: state where the command applies and whether it can run under current conditions.
  • Permission source: name the application authority that evaluates access at execution time.
  • Consequence and confirmation: classify the effect, then apply the product's confirmation policy.
  • Execution and recovery: name the handler owner, expected effect, retry or undo route, and any expiry.
  • Alternate access: identify a visible route so the palette remains an accelerator.
  • Evidence and retest: record the named consumer, observed status, correction owner, and changes that invalidate acceptance.

Choose visibility separately from enforcement

A disabled command can explain why an action is unavailable. Hiding may reduce clutter or avoid exposing a sensitive capability. Either presentation still requires enforcement at the application's execution boundary.

Design the shell around the record

The familiar anatomy includes an invocation affordance, query input, grouped results, an active option, metadata, shortcut hints, progress, outcome messaging, and sometimes a confirmation or detail region. Setproduct offers a deeper visual and state reference. The design-system task is to turn that anatomy into a stable component contract.

Show enough metadata to separate similar results. Depending on the command, that may include a destination, selected object, workspace, current mode, shortcut, unavailability reason, or consequence. Leave secondary details out of the result row unless they affect the choice. The confirmation step or destination interface can carry the rest.

Treat long labels, translated copy, missing shortcuts, many groups, no matches, slow remote sources, and narrow viewports as normal inputs. Document wrapping, truncation, scrolling, group persistence, and the way loading or error content changes the result region.

The shared component can define focus styling and a default interaction model. The consumer still has to choose a meaningful focus destination after closing, navigating, completing an inline action, or handing off to a form. Test that behavior in the composed interface with its real routing and content.

Make matching and ranking predictable

Ranking affects which action a person is likely to run. Rootly describes page-aware ordering, and Avery Vigolo recommends contextual information with consistent results. Use context to improve relevance, but keep the relationship among the query, visible result, and current scope understandable.

  • Match visible labels first, then explicit aliases and approved metadata. A match on hidden text should still produce an understandable visible result.
  • Use page, selection, or object context only when it has a clear relationship to the command. Record that context as a ranking input.
  • Keep the order stable while meaningful inputs remain unchanged. Avoid random tie-breaking or unexplained reshuffling when remote results arrive.
  • Decide whether unavailable commands remain visible. If shown, include a reason and block invocation. If hidden, maintain another discovery route.
  • Keep local commands usable while a remote source is loading.
  • Give an empty result a practical next step, such as revising the query or opening a relevant destination.

Observe retrieval with real tasks. Record whether people find the intended command, which terms return no useful result, whether identical inputs cause unexpected order changes, how often people select unavailable results, and when they switch to visible controls. Use those findings to revise labels, aliases, context rules, or ranking inputs.

Test states according to consequence

Loading, empty, error, and success cover only part of the command lifecycle. The acceptance matrix also needs authorization outcomes, confirmation, partial completion, and recovery. Test every state with concrete fixture content in a named consumer, not just generic mockups.

Test contentInspection criteriaFailure condition
ClosedNamed surface with launcher, shortcut, and visible alternate routeOnly intended contexts invoke the palette; conflicts follow the product ruleThe palette opens unexpectedly, the shortcut steals another action, or no alternate route exists
OpenNamed context with a known initial command setFocus enters at the documented point; scope and initial ordering are clearFocus is lost, scope is ambiguous, or order changes without an input change
QueryingLabels, aliases, ties, and a hidden-term matchMatches follow the declared policy and visible text explains each resultThe intended command disappears, ties reshuffle, or a hidden match looks unrelated
LoadingLocal commands plus one delayed remote sourcePending content is identified while local actions remain usableThe whole list blocks or pending results appear as final
EmptyA query with no approved matchThe state explains the outcome and offers a useful route forwardThe user reaches a dead end or stale results remain actionable
UnavailableRelevant command blocked by a current application conditionReason and recovery route match the resolved availability responseInvocation proceeds, the reason is stale, or the recovery route is wrong
ForbiddenCommand requested by a role without the required capabilityPalette and alternate route reach the same enforced policy outcomeOne route permits the action or the interface implies that visibility grants access
Confirmation requiredKnown target, scope, effect, and recovery policyConfirmation names the actual operation and resolved scopeCopy is generic, the target is wrong, or the effect differs from the handler request
ExecutingHandler held in progress while input is repeatedProgress is clear and duplicate behavior follows application policyRepeated input creates an unintended duplicate or leaves controls in a false idle state
Partially failedBatch fixture with successful, failed, and unresolved itemsThe outcome separates each category and provides reconciliation guidanceMixed results collapse into success or unresolved items disappear
CompletedAuthoritative completion response plus expected consumer stateThe defined completion signal is recorded and the result surface shows the expected effectThe completion signal is absent, contradictory, or followed by an incorrect consumer state
Undo availableCompleted reversible action with an active recovery windowUndo restores the promised scope and reports its own outcomeOnly part of the scope returns or an undo failure is hidden
Undo expiredThe same action after the application-defined expiryThe stale action is unavailable and another recovery route is shown when one existsThe interface offers an undo request the application will reject
For each state, record the fixture, inspect the stated behavior, and fail the case when the listed condition occurs.

Consequence tiers belong to product policy. Navigation may run immediately. A reversible state change may use an undo window. A destructive, financial, external, or broad action may require a resolved target and explicit confirmation. The application makes that decision; the component presents it.

Confirmation and authorization answer different questions

Confirmation checks that the person intends the displayed effect. Authorization checks whether the current principal may request it. Evaluate permission at the execution boundary even if the palette already displayed an allowed state.

Preserve visible controls and device-appropriate routes

Record an alternate route for every important command. It may be a menu item, settings page, object action, or destination. Showing the path as result metadata can also teach people where the action lives outside the palette.

Small screens don't need to imitate a desktop keyboard workflow. A visible launcher may open the shared shell, or the product may present the same registry through an action sheet or navigation surface. Reusing command definitions doesn't require identical presentation on every device.

Verify one command in one named consumer

Choose a specific consumer such as web-project-detail, then follow one command from its approved record to the observed result. Keep each evidence state separate. Reviewers can then locate a gap without mistaking earlier work for runtime acceptance.

  1. 1

    Declare the command

    Approve its identity, copy, context, permission source, consequence, confirmation policy, effect, recovery, alternate access, and owners.

  2. 2

    Confirm registration

    Inspect the named consumer's registry or adapter at a recorded version. Verify that the stable ID maps to the expected metadata and handler.

  3. 3

    Resolve availability

    Load the recorded fixture and capture whether the command is available, unavailable, hidden, or forbidden, including the reason and policy source.

  4. 4

    Invoke required routes

    Use the palette and the recorded alternate route. Exercise any shortcut conflict, keyboard sequence, confirmation, and focus handoff included in scope.

  5. 5

    Record execution completion

    Capture the application-owned completion signal separately from overlay closure or a client-side message.

  6. 6

    Inspect the effect and recovery

    Check the named result surface. For a reversible command, run the actual undo or retry route and record its outcome.

  7. 7

    Set the disposition

    Accept the stated scope only when every required observation is present. Otherwise, record revise or block, assign the first divergent layer to a correction owner, and name the retest trigger.

Evidence to recordNext question
DeclaredApproved command contract, owner, and versionWas that contract registered in the named consumer?
RegisteredStable ID, metadata, and handler mappingWhat does the current context resolve?
AvailableVisibility, enabled state, reason, and policy source for the fixtureCan the required route invoke the intended handler?
InvokedRequest received by the intended application pathWhat completion outcome did that path return?
CompletedApplication-defined completion signal and returned outcomeDoes the named result surface show the expected effect?
ObservedRendered effect, focus result, failure handling, and recovery under recorded conditionsDoes the evidence meet the acceptance criteria for this scope?
AcceptedApprover, disposition, scope, versions, open exceptions, and dateWhich changes require this case to run again?
Each status records a different point in the implementation path.

Assign a failed case to the first layer that diverged. Missing visual behavior belongs with the relevant token or component owner. An incorrect permission result belongs with the policy or application owner. A wrong handler mapping belongs with the consumer integration. This prevents a team from fixing the visible symptom while leaving the originating fault in place.

Useful retest triggers include changes to the command record, registry, handler, permission policy, routing, ranking inputs, shared component, shortcut mapping, or consumer composition. Store the trigger with the evidence so reviewers know when the acceptance has expired.

Apply Identity Forge at the visual boundary

Identity Forge can supply the palette's upstream visual system: semantic light and dark color tokens, typography, spacing, layout guidance, motifs, DESIGN.md, and shadcn, Tailwind, or DTCG exports. These artifacts can help a coding agent or development team keep the shell consistent with the surrounding product.

The consuming project still owns its command registry, context rules, permission checks, handlers, confirmation policy, undo behavior, accessibility evaluation, and runtime evidence. Start with the highest-consequence command already reused across multiple routes. Complete its record and test it in one named consumer before expanding the registry.

Distinct command palette design questions

Is a command palette the same as search?

No. Search primarily finds content or destinations, while a command palette initiates actions. A product can place them beside each other or make search one command, but the interface should make the resulting behavior clear.

Should unavailable commands be hidden or disabled?

Use a disabled result when knowing the command exists helps someone understand the product and the interface can give an accurate reason. Hide it when disclosure is inappropriate or the result would be irrelevant clutter. The application must enforce authorization in either case.

Does every risky command need confirmation?

No universal rule applies. Classify the consequence in product policy, then decide whether the resolved scope, expected effect, and recovery require confirmation. Repeated confirmation for routine reversible actions can add friction without improving the decision.

What should a team implement first?

Choose one high-consequence command that already has a visible route. Define its record, alternate access, state expectations, correction owner, and named-consumer evidence before adding more commands.

Sources