---
title: "Search Dialogs"
description: "Search Dialogs are a core feature of the UI subsystem, providing a centralized interface for users to discover content across documentation sets. By offering a standardized way to invoke and naviga..."
last_updated: "2026-07-02T09:46:38.942932+00:00"
canonical_url: "https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/search-subsystem/search-dialogs"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/base-ui/src/components/dialog/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search.tsx)
- [packages/radix-ui/src/components/dialog/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dialog/search.tsx)
- [packages/api-docs/src/components/schema/client.tsx](https://github.com/blade47/fumadocs/blob/main/packages/api-docs/src/components/schema/client.tsx)
- [packages/preview/src/components/ai/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/preview/src/components/ai/search.tsx)
- [packages/base-ui/src/layouts/notebook/slots/sidebar.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/layouts/notebook/slots/sidebar.tsx)
- [packages/radix-ui/src/layouts/notebook/slots/sidebar.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/layouts/notebook/slots/sidebar.tsx)
- [packages/base-ui/src/components/dialog/search-default.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-default.tsx)
- [packages/openapi/src/ui/operation/index.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/index.tsx)
- [packages/radix-ui/src/components/dialog/search-default.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dialog/search-default.tsx)
- [packages/base-ui/src/components/dialog/search-algolia.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-algolia.tsx)
- [packages/radix-ui/src/components/dialog/search-algolia.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dialog/search-algolia.tsx)
- [packages/asyncapi/src/ui/components/server-select.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/components/server-select.tsx)
- [packages/base-ui/src/contexts/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/contexts/search.tsx)
- [packages/base-ui/src/components/dialog/search-orama.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-orama.tsx)
- [packages/radix-ui/src/contexts/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/contexts/search.tsx)
- [packages/radix-ui/src/components/dialog/search-orama.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dialog/search-orama.tsx)
- [packages/base-ui/src/components/sidebar/base.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/sidebar/base.tsx)
- [packages/base-ui/src/layouts/shared/slots/search-trigger.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/layouts/shared/slots/search-trigger.tsx)
- [packages/api-docs/src/components/select-tab.tsx](https://github.com/blade47/fumadocs/blob/main/packages/api-docs/src/components/select-tab.tsx)
- [packages/radix-ui/src/components/sidebar/base.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/sidebar/base.tsx)
- [packages/create-app/template/+orama-cloud/@app/components/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/create-app/template/%2Borama-cloud/%40app/components/search.tsx)
- [packages/radix-ui/src/layouts/shared/slots/search-trigger.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/layouts/shared/slots/search-trigger.tsx)
- [packages/radix-ui/src/layouts/shared/page-actions.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/layouts/shared/page-actions.tsx)
</details>

Search Dialogs are a core feature of the UI subsystem, providing a centralized interface for users to discover content across documentation sets. By offering a standardized way to invoke and navigate search results, these components ensure a consistent user experience while remaining decoupled from specific search backends. They act as a bridge between high-level application state and low-level search implementation details.

The design relies on a provider-based architecture, allowing the search functionality to be configured and injected throughout the application. This modularity enables developers to swap out search providers—such as the default fetch-based search, Algolia, or Orama—without modifying the consumption layer. By providing a clean API surface for triggers and content, the system facilitates rapid integration into various layouts.

Internally, the Search Dialog subsystem manages complex state, including keyboard navigation, focus trapping, and asynchronous loading states. It leverages React context to share search input and selection logic among diverse components, ensuring that triggers, inputs, and results stay synchronized. This architecture minimizes boilerplate while offering hooks for advanced customizations, such as filtering and metadata display.

## Core Architecture and Contexts

The search system is initialized through a `SearchProvider`, which manages the global search state including the "open" boolean and the configuration of the dialog component.

```mermaid
flowchart TD
    SP[SearchProvider] --> Context[SearchContextType]
    Context --> Trigger[SearchTrigger]
    Context --> Dialog[SearchDialog]
    Dialog --> C[RootContext]
    C --> Content[SearchDialogContent]
    C --> List[SearchDialogList]
```
Sources: [packages/base-ui/src/contexts/search.tsx:112-162](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/contexts/search.tsx#L112-L162), [packages/base-ui/src/components/dialog/search.tsx:56-63](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search.tsx#L56-L63)

The `SearchProvider` acts as the single source of truth for whether the search modal should be displayed. It subscribes to global keyboard events (defaulting to Meta+K) to trigger the `setIsOpen` state function, ensuring immediate accessibility.

Sources: [packages/base-ui/src/contexts/search.tsx:121-133](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/contexts/search.tsx#L121-L133)

## Dialog State Management

The `SearchDialog` acts as a controlled component wrapping the Radix `Dialog.Root`. It uses an internal context to distribute the search change and selection handlers down the tree.

> [!TIP]
> The use of `useRef` for callbacks in `SearchDialog` prevents unnecessary re-renders of the entire dialog tree when the parent’s search state updates, optimizing performance for fast-typing users.

Sources: [packages/base-ui/src/components/dialog/search.tsx:177-213](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search.tsx#L177-L213)

When an item is selected in the list, the `onSelect` function determines the navigation target. It checks the item type and dispatches to the router if it's a standard page, or executes an `onSelect` function if the item is an action.

```mermaid
sequenceDiagram
    participant User
    participant List as SearchDialogList
    participant Handler as onSelect(item)
    User->>List: Press Enter
    List->>Handler: Call selected handler
    alt item.type == 'action'
        Handler->>Handler: item.onSelect()
    else item.external
        Handler->>Handler: window.open()
    else default
        Handler->>Handler: router.push(item.url)
    end
    Handler->>List: Close Dialog
```
Sources: [packages/base-ui/src/components/dialog/search.tsx:181-192](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search.tsx#L181-L192)

## Keyboard Navigation

Keyboard navigation is handled within `SearchDialogList`. The component uses `useEffectEvent` to track the `active` state and allows users to traverse results using arrow keys.

> [!WARNING]
> The logic within `SearchDialogList` ensures that list indices loop correctly using the modulo operator: `setActive(items.at(idx % items.length)?.id ?? null)`. This prevents out-of-bounds access.

Sources: [packages/base-ui/src/components/dialog/search.tsx:339-358](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search.tsx#L339-L358)

## Search Providers (Algolia, Orama)

The system exposes a standard interface for custom search backends. By wrapping `useDocsSearch` with specific client drivers, it unifies diverse API structures into the `SortedResult` interface.

| Feature | `fetchClient` (Default) | `algoliaClient` | `oramaCloudClient` |
| :--- | :--- | :--- | :--- |
| **Logic** | HTTP fetch | Algolia SDK | Orama API |
| **Config** | API URL | Algolia options | Client/Index config |

Sources: [packages/base-ui/src/components/dialog/search-default.tsx:63-70](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-default.tsx#L63-L70), [packages/base-ui/src/components/dialog/search-algolia.tsx:61-67](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-algolia.tsx#L61-L67), [packages/base-ui/src/components/dialog/search-orama.tsx:68-76](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-orama.tsx#L68-L76)

## Customizing the Search Result Rendering

The `SearchDialogListItem` uses a `renderMarkdown` function to render search results. This renderer is configured with specific components to handle highlighted matches, links, and code blocks within the snippet display.

Sources: [packages/base-ui/src/components/dialog/search.tsx:425-470](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search.tsx#L425-L470)

The list item component distinguishes between types (page, heading, text) and styles them accordingly, often applying specific padding and icons to indicate hierarchical structure.

Sources: [packages/base-ui/src/components/dialog/search.tsx:451-468](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search.tsx#L451-L468)

## Worked Example: Implementing a Custom Search Dialog

To build a custom dialog, create a component that implements the `SharedProps` and utilizes the exported UI sub-components from the search module.

```typescript
import { 
  SearchDialog, 
  SearchDialogHeader, 
  SearchDialogInput, 
  SearchDialogList,
  type SharedProps 
} from 'fumadocs-ui/components/dialog/search';

export default function MyCustomSearch(props: SharedProps) {
  const [search, setSearch] = useState('');
  
  // Implementation of query logic here...
  
  return (
    <SearchDialog search={search} onSearchChange={setSearch} {...props}>
      <SearchDialogHeader>
        <SearchDialogInput />
      </SearchDialogHeader>
      <SearchDialogList items={...} />
    </SearchDialog>
  );
}
```
Sources: [packages/create-app/template/+orama-cloud/@app/components/search.tsx:4-54](https://github.com/blade47/fumadocs/blob/main/packages/create-app/template/%2Borama-cloud/%40app/components/search.tsx#L4-L54)

## Related

- [Search Clients](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/search-subsystem/search-clients)
- [Layout System](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/rendering-ui/layout-system)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/llms.txt) for all pages in this wiki.
