Search nx-ui

Jump to any foundation, component, block or example.

Command search

A framework-neutral ⌘K palette: static pages and actions, debounced remote results, opt-in recents — and no router assumptions, so it ships to Next, Vite and server-rendered Worker apps alike.

$bunx shadcn@latest add @nx-ui/command-search
Registry item
Installs withbadgecommandkbdskeletonutils

Trigger and static groups

The trigger is an input-shaped button for a top bar; its ⌘K hint renders the platform's own modifier after mount, so a server render never mismatches. This demo binds ⌘J rather than the default ⌘K, which the showcase's own palette already owns.

Search Nexus ID

Jump to an organisation, a staff member or an action.

Nothing chosen yet — navigation is intercepted here instead of leaving the page.

Remote results, scoped to a context

Typing past two characters debounces for 150ms, then calls search with an AbortSignal. Previous results stay on screen while the next page loads — dimmed and unselectable from the keystroke that supersedes them, because they answer a query you have already moved on from — and a response arriving after a newer request is discarded. Switching organisation while the palette is open changes searchKey: the rendered hits are cleared rather than left answering the old tenant, anything in flight is retired, and the same query runs again.

Search staff

Search the staff directory and the console's own pages.

Searching Persimmon Homes. Leave the palette open, type dan, and switch organisation.

Loading, empty and error states

Skeleton rows while the first page loads, an empty message when nothing matches, and an alert with a retry when the endpoint fails. Static groups keep working throughout — a broken search endpoint never takes the palette down.

Search staff

Search pages, records and actions.

Recents, filtered

Recents are opt-in per item: only rows the consumer's filter accepts are written to localStorage. Here the pages are persisted and anything from the staff directory is not, so no personal data reaches the browser store. Reads and writes are wrapped, so a blocked or full store is simply a palette without recents.

Search Nexus ID

Search pages, records and actions.

Framework neutrality

What a consumer can rely on when vendoring this block.

Portability contract

No router. Choosing a row with an href calls onNavigate(href, item), defaulting to window.location.assign(href). A Next app passes router.push; a React Router app passes navigate; an MPA passes nothing. An item may instead carry its own onSelect.

Server-render safe. Nothing reads window, localStorage or navigator during render, so the block renders under Next's App Router, Vite SSR and server-rendered Cloudflare Workers alike. The platform-specific shortcut hint resolves in an effect, after hydration.

Filtering stays predictable. With no search prop, cmdk fuzzy-filters everything. Once a remote query is live, cmdk's filter is switched off so server hits are never second-guessed, and the static groups are filtered locally instead.

Results never outlive their context. searchKey names the organisation, account or data version search answered in; changing it clears the rendered hits and re-runs the query. Changing the search function's identity retires the in-flight request too, so a response from the previous fetcher can never land. And from the keystroke that supersedes them until their replacement lands, remote rows answering an earlier query are dimmed and non-interactive — cmdk skips them, so neither a click nor Enter can open a record the visible query never asked for. Re-issuing the same query leaves them live, so a retry does not flicker.

Recents are replayable or absent. onSelect does not survive JSON, so a callback-only row is persisted only when a current staticGroups item shares its id — it is re-linked to that live item on the way back out. Anything that could only come back inert is never stored, and is dropped on read if an older entry lingers.

API reference

Exported parts and their props, extracted from the component source.