Skip to content
Component installs need the registry setup
VegaStack Design

command-search-01

A search palette with scope chips, recents, results grouped by type, loading, empty and error states, and ⌘↵ to open in a new tab.

Last updated

Search

Find meetings, tasks, products, customers and pages.

Search

Search meetings, tasks, products, families, accessories, customers, projects, attributes and pages

What it is

A search palette — scope chips, recents, results grouped by type, loading, empty and error states, and ⌘↵ to open in a new tab. It is a block: you pull it once with shadcn add, and then you own it — nothing re-pulls it and no integrity hash tracks your edits, unlike the components it composes.

CommandSearch in components/ is the palette; sample-search.ts is a stand-in search(query, scope, signal) over an in-memory index.

Install

npx shadcn@latest add @vegastack/command-search-01
Registry setup required
Run this command only after configuring the Base UI shadcn project, the @vegastack registry namespace, and the Cloudflare Access service-token headers in Install from the VegaStack registry.

This installs the block's own files plus the components it composes: app-shell, button, command, item, kbd, page-header, toggle-group, use-platform.

Preview

Search

Find meetings, tasks, products, customers and pages.

Search

Search meetings, tasks, products, families, accessories, customers, projects, attributes and pages

Anatomy

  • CommandDialog (the wide default size) › Command shouldFilter={false} — the host's search does the matching.
  • CommandInput "Search…", then the scope chips — All · Meetings · Tasks · Products · Families · Accessories · Customers · Projects · Attributes · Pages — as a ToggleGroup wrap deselectable={false} inside CommandFilters. The chips are their own Tab stop after the input; Alt+← and Alt+→ switch scope without leaving it.
  • CommandList: "Recent" while the query is empty; CommandLoading while a search runs; one CommandGroup per type, each row an ItemTitle over an ItemDescription ("Meeting · Skyline Hotels · 3 Sep"); CommandEmpty "No results"; or the error line with "Try again".
  • CommandFooter with no children — its built-in Kbd hints ↵ Open · ⌘↵ / Ctrl ↵ New tab · Esc Close — hidden below sm. CommandLoading shows the animated searching icon.

Searching

Each keystroke or scope change calls search(query, scope, signal) and aborts the one before, so a slow answer never overwrites a newer one. Changing scope keeps the query. When an answer settles, the palette says its count once in a polite live region — "5 results", "1 result" or "No results". Command's own result announcer is silenced (resultsLabel returns an empty string), because with shouldFilter={false} it counts the zero rows on screen while a search is in flight.

Opening a result

↵ opens the selected result; ⌘↵ or Ctrl+↵ opens it in a new tab. cmdk's onSelect receives no event, so the new-tab path reads the controlled selection in the palette's onKeyDown.

Files

FileRegistry typeTarget
command-search-01/components/command-search.tsxregistry:componentapp/command-search-01/components/command-search.tsx
command-search-01/components/sample-search.tsregistry:componentapp/command-search-01/components/sample-search.ts
command-search-01/page.tsxregistry:pageapp/command-search-01/page.tsx

Do / Don't

Do
Let the server match, abort stale searches, and keep the query when the scope changes.
Don't
Filter results on the client with cmdk, or hide the error behind “No results”.

On this page