ComponentsOverlays

Search Dialog

A search palette pinned near the top of the screen. You filter the results; it groups them with counts, moves through them with the arrow keys, and opens the active one with Enter.

Jump to a page or action

The workspace palette: Recent, Pages, and Quick actions groups with icon tiles, a Clear search recovery, and footer hints. ⌘K or Ctrl+K toggles it.

Workspace searchtitle only · SearchItemIcon media · recents after you open something

Nothing opened yet

Usage

Search Dialog usageTSX
import {
  SearchDialog,
  SearchEmpty,
  SearchFooter,
  SearchGroup,
  SearchHint,
  SearchInput,
  SearchItem,
  SearchItemIcon,
  SearchList,
} from "@tulipfarm/sprout/search-dialog";

<SearchDialog
  open={open}
  onOpenChange={setOpen}
  title="Jump to…"
  description="Find workspace pages and quick actions."
>
  <SearchInput
    ref={inputRef}
    value={query}
    onValueChange={setQuery}
    placeholder="Find a page or action…"
    label="Find a page or action"
  />
  <SearchList label="Pages and actions">
    {pages.length ? (
      <SearchGroup heading="Pages" count={pages.length}>
        {pages.map((page) => (
          <SearchItem
            key={page.id}
            value={page.id}
            title={page.title}
            media={<SearchItemIcon><page.icon size={14} aria-hidden="true" /></SearchItemIcon>}
            onSelect={() => open(page)}
          />
        ))}
      </SearchGroup>
    ) : (
      <SearchEmpty
        title="No pages or actions found"
        description="Try another page or action name."
        action={<Button variant="outline" size="sm" onClick={clear}>Clear search</Button>}
      />
    )}
  </SearchList>
  <SearchFooter>
    <SearchHint keys="↑↓">Select</SearchHint>
    <SearchHint keys="↵">Open</SearchHint>
    <SearchHint keys="Esc">Close</SearchHint>
  </SearchFooter>
</SearchDialog>

Search Dialog does not filter. Match the query yourself and render only the results, then show SearchEmpty when nothing is left. Clear the query when the dialog closes. Give every SearchItem avalue that is unique across groups, such as the group name plus the id when one entry appears under Recent and Pages.

Commands and events

Pass a shortcut letter as trailing; on the active row it swaps for the Enter key. media can be a bare icon, centered in a 28px box, or a muted SearchItemIcon. detailadds a second line such as a time. A group whose count is 0 is not rendered, and long titles truncate.

Calendar commands

Commands with trailing shortcut keys and events with kind icons and times. The Enter hint replaces the shortcut on the active row. Press / to open.

Calendar searchtrailing keys · raw icon media · detail line · empty with media

No command run yet

Filters, meta, and empty media

SearchFilters holds a row of SearchFilter toggles that scrolls sideways when narrow. meta sits after the title behind a dot. Give SearchEmpty one to three icons asmedia to show them as fanned tiles over a faint grid.

Filters, meta, and detail

Toggle filters under the input, a meta label after each title, a second detail line, and an empty state with fanned icon tiles and a Clear filters action.

Record searchSearchFilters · meta · detail · empty with three tiles

Nothing selected

API

SearchDialog takes open, onOpenChange, a visually hidden title and description, plusclassName and container. It is 42rem wide from 640px and pins 12% from the top. SearchInput takes a controlledvalue and onValueChange,placeholder, label, closeLabel, and aref so a Clear search button can refocus it.

SearchFilters takes label; SearchFiltertakes pressed, onPressedChange, and an optionalicon. SearchList takes label and keeps a steady height. SearchGroup takes heading andcount. SearchItem takes value,onSelect, media, title, and optionalmeta, detail, and trailing.SearchEmpty takes title, description, and optional media and action.SearchFooter holds SearchHints, each withkeys; it hides below 640px. Every part sets adata-slot.

Accessibility

Focus moves to the search field, a combobox that controls the resultslistbox, and the active result is announced througharia-activedescendant. Arrow keys move and wrap at the ends, Home and End jump, Alt with arrows jumps between groups, and Enter opens. Group names include their count. Filters are toggle buttons witharia-pressed. The empty state is a status, so its message is announced. Escape or the close button closes the dialog and returns focus to the trigger.

The dialog fades and scales over 180ms, and highlights and filters change over 120ms. Motion stops when reduced motion is requested.

Theme tokens

Search Dialog uses --sprout-surface, --sprout-canvas,--sprout-text, --sprout-muted,--sprout-line, --sprout-input,--sprout-hover, --sprout-active,--sprout-focus, --sprout-overlay, and the panel shadows and radii. It needs no brand color, so it looks the same with the neutral and TulipFarm themes in light and dark mode.