Skip to main content
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

import { DocSearchModal } from '@docsearch/react';

Usage

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
      )}
    </>
  );
}

Props

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

Required Props

appId
string
required
Algolia application ID used by the search client.
apiKey
string
required
Public API key with search permissions for the index.
initialScrollY
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.
onAskAiToggle
OnAskAiToggle
required
Callback function when Ask AI mode is toggled.Signature: (isActive: boolean, initialMessage?: InitialAskAiMessage) => void

Index Configuration

indexName
string
deprecated
Name of the Algolia index to query.Deprecated: Use indices property instead.
indices
Array<DocSearchIndex | string>
default:"[]"
List of indices and optional search parameters to be used for search.
searchParameters
SearchParamsObject
deprecated
Additional Algolia search parameters.Deprecated: Use indices property instead.
onClose
() => void
Callback function when the modal should close.
isAskAiActive
boolean
default:"false"
Whether Ask AI mode is currently active.
interceptAskAiEvent
(initialMessage: InitialAskAiMessage) => boolean | void
Intercept Ask AI requests. Return true to prevent default Ask AI behavior.
initialQuery
string
Query string to prefill when opening the modal.

Ask AI Configuration

askAi
DocSearchAskAi | string
Configuration or assistant ID to enable Ask AI mode.

UI Customization

theme
'light' | 'dark'
Theme applied to the modal.
placeholder
string
Placeholder text for the search input.
translations
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.)

Results Customization

maxResultsPerGroup
number
Maximum number of hits to display per source/group.
transformItems
(items: DocSearchHit[]) => DocSearchHit[]
Hook to post-process hits before rendering.
hitComponent
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
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

Search Client

transformSearchClient
(searchClient: DocSearchTransformClient) => DocSearchTransformClient
Hook to wrap or modify the Algolia search client.

User Personalization

disableUserPersonalization
boolean
default:"false"
Disable storage and usage of recent and favorite searches.
recentSearchesLimit
number
default:"7"
Limit of how many recent searches should be saved/displayed.
recentSearchesWithFavoritesLimit
number
default:"4"
Limit of how many recent searches should be saved/displayed when there are favorited searches.
navigator
AutocompleteOptions['navigator']
Custom navigator for controlling link navigation.
getMissingResultsUrl
({ query }: { query: string }) => string
Builds a URL to report missing results for a given query.

Analytics

insights
AutocompleteOptions['insights']
default:"false"
Insights client integration options to send analytics events.

Advanced

isHybridModeSupported
boolean
default:"false"
Internal flag for hybrid mode support with sidepanel integration.
The modal renders with the following structure:
<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

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

DocSearchModalProps

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

Build docs developers (and LLMs) love