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-switcherOverview
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.
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.
Capabilities
Built for navigation speed — the muscle-memory way power users move around without touching the mouse.
Type letters in order — “dsa” finds Design System Audit. Matches are scored by streak and word-start, best first.
Before you type a thing it shows where you’ve just been, so a blind ⌘P-↵ jumps you back to the last place.
Tasks, projects, docs, people and saved views share one ranked list, each with its own icon and colour.
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.
recents: [t1, p1, d1]
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| items | QuickSwitcherItem[] | — | Everything the switcher can jump to, across all kinds. Fuzzy-matched by title. |
| open | boolean | — | Controlled open state. Pair with onOpenChange. |
| defaultOpen | boolean | false | Initial open state when uncontrolled. |
| onOpenChange | (open: boolean) => void | — | Called when the switcher opens or closes (trigger, ⌘P, Esc, scrim, pick). |
| hotkey | boolean | true | Global ⌘P / Ctrl+P toggles the switcher. Turn off to bind your own. |
| onSelect | (item: QuickSwitcherItem) => void | — | Called with the picked item on Enter or click; the switcher then closes. |
| recents | string[] | — | Controlled recents — item ids, most recent first. Shown when the query is empty. |
| defaultRecents | string[] | [] | Initial recents when uncontrolled. |
| onRecentsChange | (ids: string[]) => void | — | Called with the updated id list after a pick (most recent first). |
| maxRecents | number | 4 | How many recents to keep after a pick. |
| placeholder | string | "Search tasks, projects, docs, people…" | Search input placeholder. |
| inline | boolean | false | Render the panel in the page flow instead of a ⌘P dialog — for docs and embeds. |
| children | ReactNode | — | Trigger slot — e.g. <QuickSwitcherTrigger />. Ignored when inline. |
| className | string | — | Class applied to the 600px panel. |
| Prop | Type | Default | Description |
|---|---|---|---|
| QuickSwitcherItem.id | string | — | Unique 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.title | string | — | Primary row text. The fuzzy matcher scores against this. |
| QuickSwitcherItem.sub | string | — | Secondary text, “ · ”-separated — the row shows the kind label plus the last segment. |
| QuickSwitcherItem.icon | ReactNode | — | Override the kind's default glyph inside the 32px tile. |
| QuickSwitcherItem.color | string | — | Override the kind's default tint — any CSS color, tokens included (e.g. "var(--warning)"). |
| QuickSwitcherTrigger.label | string | "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.
Keep it to navigation
The switcher’s only job is “take me there.” That single purpose is what lets people trust a blind Enter.
Mix in actions
Creating, deleting or changing status belongs in the Command Palette. Mixing them makes a fast jump feel risky.
Highlight the match
Bold the matched letters so people can see why a result ranked, and trust that the fuzzy logic understood them.
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.