# Search dialog Search caller-provided results in a dialog with keyboard navigation and custom content. ## Install ```sh npx shadcn@4.21.0 add lr-run/dir-ui/search-dialog#v0.1.3 ``` [Registry item with source and dependencies](https://github.com/lr-run/dir-ui/blob/v0.1.3/registry.json) Requires React 19, Tailwind CSS 4 and shadcn initialized with Base UI. Registry target placeholders resolve through components.json: @ui, @components, @hooks and @lib. Imports below use the conventional @/ prefix for illustration; the CLI rewrites them to your configured aliases. Shared components are installed once through registryDependencies. The installer merges shared theme rules into the stylesheet configured in components.json. Existing files are never forcibly overwritten; review CLI conflicts before accepting changes. No Dir runtime is required. ## SearchDialog, SearchDialogTrigger, type SearchDialogProps, type SearchItem, type LoadSearchResults ```tsx import { SearchDialog, SearchDialogTrigger, type SearchDialogProps, type SearchItem, type LoadSearchResults } from '@/components/collections/search-dialog.tsx' ``` | Prop | Type | Default / required | Notes | | --- | --- | --- | --- | | loadResults | LoadSearchResults | — | Remote adapter. Pass AbortSignal to fetch; return result items. Server order within each group is preserved without local filtering. | | debounceMs | number | 250 | Remote search delay; cancels pending and in-flight requests on new input or close. | | minQueryLength | number | 0 | Do not request results below this trimmed query length. | | SearchDialogTrigger.placeholder / shortcut | string / boolean | Search… / false | Input-style button label and platform keyboard hint. Enable SearchDialog.shortcut separately. | | SearchDialogTrigger.…buttonProps | ComponentProps<"button"> | — | Supply onClick, aria-expanded, disabled, className, and ref. | | items | readonly SearchItem[] | [] | Local results or initial suggestions; ignored when loadResults is supplied. | | onSelect | (item: SearchItem) => void \| Promise | Required | Rejected promises display an error; duplicate selection is prevented. | | query / onQueryChange | string / (query: string) => void | Uncontrolled | | | filter | boolean | true | Applies to local items only. loadResults automatically bypasses local filtering. | | loading / error / onRetry | boolean / string / () => void | — | | | maxVisible | number | 100 | | | placeholder | string | Search… | | | inputLabel | string | Search | Accessible search field name. | | emptyQueryLabel | string | Suggestions | Fallback group label for caller-provided initial results; no history is stored. | | selectLabel | string | Select | Label of the footer selection button. | | renderPreview | (item: SearchItem) => ReactNode | — | Optional content for the highlighted result. Updates on keyboard/pointer navigation; hidden below 600px. showPreview is a documentation-only control. | | emptyMessage | ReactNode | No results found. | | | renderItem | (item: SearchItem) => ReactNode | — | Customize result content; keyboard and selection behavior remain managed. | | open / onOpenChange | boolean / (open: boolean) => void | Required | | | title | string | Search | | | shortcut | boolean | false | Opt in to one Cmd/Ctrl+K handler per application. | ```ts type LoadSearchResults = (query: string, context: { signal: AbortSignal }) => Promise type SearchItem = { id: string; label: string; group?: string; description?: string; keywords?: string[]; icon?: ReactNode; meta?: string; disabled?: boolean } ```