Installation
Theme
Mode

Overlays & feedback

Quick switcher

The ⌘P jump-to — a lightweight fuzzy finder that takes you to any task, project, doc, person or saved view in a couple of keystrokes. Lighter than the Command Palette: it navigates, it doesn’t run commands. Opens to recents, ranks by fuzzy match, full keyboard control.

$npx shadcn@latest add @orbit/quick-switcher

Overview

Click the trigger, press ⌘P (Ctrl+P on Windows/Linux), or wire your own button — all three open the same switcher. Picking a result closes it, reports the jump, and promotes it to the top of recents.

Live · click or press ⌘P

Open it, then type a few letters — try mark or dsa.

last jump:

The panel

With an empty query the list shows your recent places; typing switches to a single ranked result list with the matched letters highlighted in the brand colour. Each row carries its entity’s tinted icon and a “Kind · status” subtitle, and the highlighted row shows a ↵ hint.

Recent
Ship onboarding flow v2Task · In progress
Orbit AppProject · 24 open tasks
Q3 launch planDoc · Edited 2d ago
navigateopenescclose

Capabilities

Built for navigation speed — the muscle-memory way power users move around without touching the mouse.

Fuzzy ranking

Type letters in order — “dsa” finds Design System Audit. Matches are scored by streak and word-start, best first.

Opens to recents

Before you type a thing it shows where you’ve just been, so a blind ⌘P-↵ jumps you back to the last place.

Every type, one box

Tasks, projects, docs, people and saved views share one ranked list, each with its own icon and colour.

No mouse needed

Open, type, arrow, Enter. The highlighted row shows a ↵ hint and Escape backs out without navigating.

Recents

Recents live inside the component by default (seed them with defaultRecents). Pass recents + onRecentsChange to own the list — e.g. to persist it per user. Every pick promotes that id to the front, capped at maxRecents.

Recent
Ship onboarding flow v2Task · In progress
Orbit AppProject · 24 open tasks
Q3 launch planDoc · Edited 2d ago
navigateopenescclose

recents: [t1, p1, d1]

Props

PropTypeDefaultDescription
itemsQuickSwitcherItem[]Everything the switcher can jump to, across all kinds. Fuzzy-matched by title.
openbooleanControlled open state. Pair with onOpenChange.
defaultOpenbooleanfalseInitial open state when uncontrolled.
onOpenChange(open: boolean) => voidCalled when the switcher opens or closes (trigger, ⌘P, Esc, scrim, pick).
hotkeybooleantrueGlobal ⌘P / Ctrl+P toggles the switcher. Turn off to bind your own.
onSelect(item: QuickSwitcherItem) => voidCalled with the picked item on Enter or click; the switcher then closes.
recentsstring[]Controlled recents — item ids, most recent first. Shown when the query is empty.
defaultRecentsstring[][]Initial recents when uncontrolled.
onRecentsChange(ids: string[]) => voidCalled with the updated id list after a pick (most recent first).
maxRecentsnumber4How many recents to keep after a pick.
placeholderstring"Search tasks, projects, docs, people…"Search input placeholder.
inlinebooleanfalseRender the panel in the page flow instead of a ⌘P dialog — for docs and embeds.
childrenReactNodeTrigger slot — e.g. <QuickSwitcherTrigger />. Ignored when inline.
classNamestringClass applied to the 600px panel.
PropTypeDefaultDescription
QuickSwitcherItem.idstringUnique id — passed back through onSelect and stored in recents.
QuickSwitcherItem.kind"task" | "project" | "doc" | "person" | "view"Entity type — sets the row's default icon, tint, and type label.
QuickSwitcherItem.titlestringPrimary row text. The fuzzy matcher scores against this.
QuickSwitcherItem.substringSecondary text, “ · ”-separated — the row shows the kind label plus the last segment.
QuickSwitcherItem.iconReactNodeOverride the kind's default glyph inside the 32px tile.
QuickSwitcherItem.colorstringOverride the kind's default tint — any CSS color, tokens included (e.g. "var(--warning)").
QuickSwitcherTrigger.labelstring"Jump to…"Placeholder-style label in the 248×38 search-box trigger.

Usage

The switcher takes you somewhere; the Command Palette does something. Keeping them distinct keeps both fast.

Do

Keep it to navigation

The switcher’s only job is “take me there.” That single purpose is what lets people trust a blind Enter.

Don’t

Mix in actions

Creating, deleting or changing status belongs in the Command Palette. Mixing them makes a fast jump feel risky.

Do

Highlight the match

Bold the matched letters so people can see why a result ranked, and trust that the fuzzy logic understood them.

Don’t

Forget recents

Most jumps are to a handful of places. An empty-query list of recents turns ⌘P into a one-keystroke back button.

Keyboard & accessibility

The overlay is a Base UI Dialog — role=dialog with aria-modal, a focus trap, and focus restore on close. Inside it, Base UI Autocomplete gives the input ARIA combobox semantics: it owns the listbox and tracks the highlight with aria-activedescendant, so focus never leaves the search field. Esc always closes without navigating.

⌘ P / Ctrl POpen or close the switcher
TypeFuzzy-search every entity at once
↑ ↓Move between results
Jump to the highlighted result
EscBack out without navigating