> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/algolia/docsearch/llms.txt
> Use this file to discover all available pages before exploring further.

# DocSearchModal

> Modal component for DocSearch

The `DocSearchModal` component is the modal interface for DocSearch. It's rendered automatically by the `DocSearch` component but can also be used standalone for custom implementations where you want full control over the modal lifecycle.

## Import

```jsx theme={null}
import { DocSearchModal } from '@docsearch/react';
```

## Usage

<CodeGroup>
  ```jsx Basic Usage theme={null}
  import { useState } from 'react';
  import { DocSearchModal } from '@docsearch/react';
  import { createPortal } from 'react-dom';

  function CustomSearch() {
    const [isOpen, setIsOpen] = useState(false);

    return (
      <>
        <button onClick={() => setIsOpen(true)}>Search</button>
        {isOpen && createPortal(
          <DocSearchModal
            appId="YOUR_APP_ID"
            apiKey="YOUR_SEARCH_API_KEY"
            indexName="YOUR_INDEX_NAME"
            initialScrollY={window.scrollY}
            onClose={() => setIsOpen(false)}
          />,
          document.body
        )}
      </>
    );
  }
  ```

  ```jsx With Ask AI theme={null}
  import { useState } from 'react';
  import { DocSearchModal } from '@docsearch/react';
  import { createPortal } from 'react-dom';

  function CustomSearch() {
    const [isOpen, setIsOpen] = useState(false);
    const [isAskAiActive, setIsAskAiActive] = useState(false);

    return (
      <>
        <button onClick={() => setIsOpen(true)}>Search</button>
        {isOpen && createPortal(
          <DocSearchModal
            appId="YOUR_APP_ID"
            apiKey="YOUR_SEARCH_API_KEY"
            indexName="YOUR_INDEX_NAME"
            askAi="YOUR_ASSISTANT_ID"
            initialScrollY={window.scrollY}
            isAskAiActive={isAskAiActive}
            onAskAiToggle={(active) => setIsAskAiActive(active)}
            onClose={() => setIsOpen(false)}
          />,
          document.body
        )}
      </>
    );
  }
  ```

  ```jsx Custom Hit Rendering theme={null}
  import { DocSearchModal } from '@docsearch/react';

  function CustomSearch() {
    const customHitComponent = ({ hit, children }) => (
      <div className="custom-hit">
        <span className="hit-title">{hit.hierarchy.lvl1}</span>
        {children}
      </div>
    );

    return (
      <DocSearchModal
        appId="YOUR_APP_ID"
        apiKey="YOUR_SEARCH_API_KEY"
        indexName="YOUR_INDEX_NAME"
        initialScrollY={window.scrollY}
        hitComponent={customHitComponent}
        onClose={() => {}}
      />
    );
  }
  ```
</CodeGroup>

## Props

The `DocSearchModal` extends all props from `DocSearchProps` with additional modal-specific properties.

### Required Props

<ParamField path="appId" type="string" required>
  Algolia application ID used by the search client.
</ParamField>

<ParamField path="apiKey" type="string" required>
  Public API key with search permissions for the index.
</ParamField>

<ParamField path="initialScrollY" type="number" required>
  The window scroll position when the modal was opened. Used to restore scroll position when closing.

  Typically set to `window.scrollY` when opening the modal.
</ParamField>

<ParamField path="onAskAiToggle" type="OnAskAiToggle" required>
  Callback function when Ask AI mode is toggled.

  Signature: `(isActive: boolean, initialMessage?: InitialAskAiMessage) => void`
</ParamField>

### Index Configuration

<ParamField path="indexName" type="string" deprecated>
  Name of the Algolia index to query.

  **Deprecated:** Use `indices` property instead.
</ParamField>

<ParamField path="indices" type="Array<DocSearchIndex | string>" default="[]">
  List of indices and optional search parameters to be used for search.
</ParamField>

<ParamField path="searchParameters" type="SearchParamsObject" deprecated>
  Additional Algolia search parameters.

  **Deprecated:** Use `indices` property instead.
</ParamField>

### Modal Behavior

<ParamField path="onClose" type="() => void">
  Callback function when the modal should close.
</ParamField>

<ParamField path="isAskAiActive" type="boolean" default="false">
  Whether Ask AI mode is currently active.
</ParamField>

<ParamField path="interceptAskAiEvent" type="(initialMessage: InitialAskAiMessage) => boolean | void">
  Intercept Ask AI requests. Return `true` to prevent default Ask AI behavior.
</ParamField>

<ParamField path="initialQuery" type="string">
  Query string to prefill when opening the modal.
</ParamField>

### Ask AI Configuration

<ParamField path="askAi" type="DocSearchAskAi | string">
  Configuration or assistant ID to enable Ask AI mode.
</ParamField>

### UI Customization

<ParamField path="theme" type="'light' | 'dark'">
  Theme applied to the modal.
</ParamField>

<ParamField path="placeholder" type="string">
  Placeholder text for the search input.
</ParamField>

<ParamField path="translations" type="ModalTranslations">
  Localized strings for the modal UI.

  Object with optional properties:

  * `searchBox` (SearchBoxTranslations): Search box translations
  * `newConversation` (NewConversationTranslations): New conversation screen translations
  * `footer` (FooterTranslations): Footer translations
  * Plus screen state translations (noResultsText, etc.)
</ParamField>

### Results Customization

<ParamField path="maxResultsPerGroup" type="number">
  Maximum number of hits to display per source/group.
</ParamField>

<ParamField path="transformItems" type="(items: DocSearchHit[]) => DocSearchHit[]">
  Hook to post-process hits before rendering.
</ParamField>

<ParamField path="hitComponent" type="function">
  Custom component to render an individual hit.

  Signature: `(props: { hit: InternalDocSearchHit | StoredDocSearchHit; children: React.ReactNode }, helpers?: { html: (template: TemplateStringsArray, ...values: any[]) => any }) => JSX.Element`
</ParamField>

<ParamField path="resultsFooterComponent" type="function">
  Custom component rendered at the bottom of the results panel.

  Signature: `(props: { state: AutocompleteState<InternalDocSearchHit> }, helpers?: { html: (template: TemplateStringsArray, ...values: any[]) => any }) => JSX.Element | null`
</ParamField>

### Search Client

<ParamField path="transformSearchClient" type="(searchClient: DocSearchTransformClient) => DocSearchTransformClient">
  Hook to wrap or modify the Algolia search client.
</ParamField>

### User Personalization

<ParamField path="disableUserPersonalization" type="boolean" default="false">
  Disable storage and usage of recent and favorite searches.
</ParamField>

<ParamField path="recentSearchesLimit" type="number" default="7">
  Limit of how many recent searches should be saved/displayed.
</ParamField>

<ParamField path="recentSearchesWithFavoritesLimit" type="number" default="4">
  Limit of how many recent searches should be saved/displayed when there are favorited searches.
</ParamField>

### Navigation

<ParamField path="navigator" type="AutocompleteOptions['navigator']">
  Custom navigator for controlling link navigation.
</ParamField>

<ParamField path="getMissingResultsUrl" type="({ query }: { query: string }) => string">
  Builds a URL to report missing results for a given query.
</ParamField>

### Analytics

<ParamField path="insights" type="AutocompleteOptions['insights']" default="false">
  Insights client integration options to send analytics events.
</ParamField>

### Advanced

<ParamField path="isHybridModeSupported" type="boolean" default="false">
  Internal flag for hybrid mode support with sidepanel integration.
</ParamField>

## Modal Structure

The modal renders with the following structure:

```html theme={null}
<div class="DocSearch DocSearch-Container">
  <div class="DocSearch-Modal">
    <header class="DocSearch-SearchBar">
      <!-- SearchBox component -->
    </header>
    <div class="DocSearch-Dropdown">
      <!-- ScreenState component with results -->
    </div>
    <footer class="DocSearch-Footer">
      <!-- Footer component -->
    </footer>
  </div>
</div>
```

## Keyboard Navigation

The modal supports full keyboard navigation:

* **Escape**: Close the modal
* **Up/Down arrows**: Navigate through results
* **Enter**: Select the highlighted result
* **Ctrl/Cmd + K**: Close and reopen (when shortcuts enabled)
* **Tab**: Move focus between elements

## Lifecycle

When the modal is opened:

1. Adds `DocSearch--active` class to `document.body`
2. Sets CSS variables for viewport height
3. Manages scroll position
4. Compensates for scrollbar width to prevent layout shift
5. Loads recent/favorite searches (if personalization enabled)

When the modal is closed:

1. Removes `DocSearch--active` class from `document.body`
2. Restores scroll position to `initialScrollY`
3. Cleans up event listeners

## Types

### ModalTranslations

```typescript theme={null}
type ModalTranslations = Partial<{
  searchBox: SearchBoxTranslations;
  newConversation: NewConversationTranslations;
  footer: FooterTranslations;
}> & ScreenStateTranslations;
```

### DocSearchModalProps

```typescript theme={null}
type DocSearchModalProps = DocSearchProps & {
  initialScrollY: number;
  onAskAiToggle: OnAskAiToggle;
  interceptAskAiEvent?: (initialMessage: InitialAskAiMessage) => boolean | void;
  onClose?: () => void;
  isAskAiActive?: boolean;
  translations?: ModalTranslations;
  isHybridModeSupported?: boolean;
};
```
