<Search>
This Enterprise Edition component, part of 
ra-search, lets user do a site-wide search via a smart Omnibox.
<Search> renders a global search input. It’s designed to be integrated into the top <AppBar>.
It relies on the dataProvider to provide a search() method, so you can use it with any search engine (Lucene, ElasticSearch, Solr, Algolia, Google Cloud Search, and many others). And if you don’t have a search engine, no problem! <Search> can also do the search across several resources via parallel dataProvider.getList() queries.
Usage
Install ra-search
The <Search> component is part of the @react-admin/ra-search package. To install it, run:
yarn add '@react-admin/ra-search'
This requires a valid subscription to React-admin Enterprise Edition.
Implement dataProvider.search()
Your dataProvider should support the search() method. It should return a Promise for data containing an array of SearchResult objects and a total. A SearchResult contains at least the following fields:
id: Identifier The unique identifier of the search resulttype: An arbitrary string which enables groupingurl: The URL where to redirect to on click. It could be a custom page and not a resource if you want tocontent: Can contain any data that will be used to display the result. If used with the default<SearchResultItem>component, it must contain at least anid,label, and adescription.matches: An optional object containing an extract of the data with matches. Can be anything that will be interpreted by a<SearchResultItem>
As for the total, it can be greater than the number of returned results. This is useful e.g. to show that there are more results.
Here is an example
dataProvider.search("roll").then((response) => console.log(response));
// {
//     data: [
//         { id: 'a7535', type: 'artist', url: '/artists/7535', content: { label: 'The Rolling Stones', description: 'English rock band formed in London in 1962'  } }
//         { id: 'a5352', type: 'artist', url: '/artists/5352', content: { label: 'Sonny Rollins', description: 'American jazz tenor saxophonist'  } }
//         { id: 't7524', type: 'track', url: '/tracks/7524', content: { label: 'Like a Rolling Stone', year: 1965, recordCompany: 'Columbia', artistId: 345, albumId: 435456 } }
//         { id: 't2386', type: 'track', url: '/tracks/2386', content: { label: "It's Only Rock 'N Roll (But I Like It)", year: 1974, artistId: 7535, albumId: 6325 } }
//         { id: 'a6325', type: 'album', url: '/albums/6325', content: { label: "It's Only rock 'N Roll", year: 1974, artistId: 7535 }}
//     ],
//     total: 5
// }
It is your responsibility to add this search method to your dataProvider so that react-admin can send queries to and read responses from the search engine.
If you don’t have a search engine, you can use the addSearchMethod helper to add a dataProvider.search() method that does a parallel dataProvider.getList() query for each resource.
// in src/dataProvider.js
import simpleRestProvider from 'ra-data-simple-rest';
import { addSearchMethod } from '@react-admin/ra-search';
const baseDataProvider = simpleRestProvider('http://path.to.my.api/');
export const dataProvider = addSearchMethod(baseDataProvider, [
    // search across these resources
    'artists',
    'tracks',
    'albums',
]);
Check the ra-search documentation to learn more about the input and output format of dataProvider.search(), as well as the possibilities to customize the addSearchMethod.
Option 1: With <Layout>
If you’re using the <Layout component, include the <Search> component inside a custom <AppBar> component:
// in src/MyAppBar.jsx
import { AppBar, TitlePortal } from "react-admin";
import { Search } from "@react-admin/ra-search";
export const MyAppbar = () => (
  <AppBar>
    <TitlePortal />
    <Search />
  </AppBar>
);
Include that AppBar in a custom layout component:
// in src/MyLayout.jsx
import { Layout } from "react-admin";
import { MyAppbar } from "./MyAppBar";
export const MyLayout = ({ children }) => (
    <Layout appBar={MyAppbar}>
        {children}
    </Layout>
);
Finally, include that custom layout in the <Admin>.
// in src/Admin.ts
import { Admin } from "react-admin";
import { dataProvider } from "./dataProvider";
import { MyLayout } from "./MyLayout";
export const App = () => (
  <Admin
    dataProvider={dataProvider}
    layout={MyLayout}
  >
    // ...
  </Admin>
);
Option 2: With <ContainerLayout>
If you’re using the <ContainerLayout> component, you can use the <Search> component directly in the toolbar prop:
// in src/MyLayout.jsx
import { ContainerLayout } from "@react-admin/ra-navigation";
import { Search } from "@react-admin/ra-search";
const MyLayout = ({ children }) => (
    <ContainerLayout maxWidth="xl" toolbar={<Search />}>
        {children}
    </ContainerLayout>
);
Then, import that custom layout in the <Admin>:
// in src/Admin.ts
import { Admin } from "react-admin";
import { dataProvider } from "./dataProvider";
import { MyLayout } from "./MyLayout";
export const App = () => (
  <Admin
    dataProvider={dataProvider}
    layout={MyLayout}
  >
    // ...
  </Admin>
);
Props
The <Search> component accepts the following props:
| Prop | Required | Type | Default | Description | 
|---|---|---|---|---|
children | 
      Optional | Element | 
      <SearchResultsPanel> | 
      A component that will display the results. | 
disableHighlight | 
      Optional | boolean | 
      false | 
      Disable the highlight of the search term of each result. | 
historySize | 
      Optional | number | 
      5 | The number of past queries to keep in history. | 
isInAppBar | 
      Optional | boolean | 
      true | 
      Apply a dedicated style to the <AppBar> if true | 
    
options | 
      Optional | Object | 
      - | An object containing options to apply to the search. | 
queryOptions | 
      Optional | UseQuery Options | 
      - | react-query options for the search query | 
    
wait | 
      Optional | number | 
      500 | The delay of debounce for the search to launch after typing in ms. | 
Additional props are passed down to the Material UI <TextField> component.
children
The <Search> children allow you to customize the way results are displayed. The child component can grab the search result using the useSearchResult hook.
import { Admin, AppBar, TitlePortal, Layout } from 'react-admin';
import { Search, useSearchResult } from '@react-admin/ra-search';
const CustomSearchResultsPanel = () => {
    const { data, onClose } = useSearchResult();
    return (
        <ul>
            {data.map(searchResult => (
                <li key={searchResult.id}>{searchResult.content.label}</li>
            ))}
        </ul>
    );
};
const MyAppBar = () => (
    <AppBar>
        <TitlePortal />
        <Search>
            <CustomSearchResultsPanel />
        </Search>
    </AppBar>
);
const MyLayout = ({ children }) => (
    <Layout appBar={MyAppBar}>
        {children}
    </Layout>
);
export const App = () => (
    <Admin dataProvider={searchDataProvider} layout={MyLayout}>
        // ...
    </Admin>
);
disableHighlight
The search terms in each result are highlighted. You can disable this feature with the disableHighlight prop as follows:
<Search disableHighlight />
Tip: To customize the highlight style check out the Customizing the result items section below.
historySize
The number of previous user searches to keep in the popover. For example, if a user performs 10 searches and historySize is set to 5, the popover will display the user’s last 5 queries.
<Search historySize={5} />
options
An object containing options to apply to the search:
targets:string[]: an array of the indices on which to perform the search. Defaults to an empty array.{any}:{any}: any custom option to pass to the search engine.
<Search options={{ foo: 'bar' }} />
queryOptions
<Search> accepts a queryOptions prop to pass options to the react-query client.
This can be useful e.g. to override the default side effects such as onSuccess or onError.
<Search queryOptions={{ onSuccess: data => console.log(data) }} />
wait
The number of milliseconds to wait before processing the search request, immediately after the user enters their last character.
<Search wait={200} />
Customizing The Result Items
By default, <Search> displays the results in <SearchResultsPanel>, which displays each results in a <SearchResultItem>. So rendering <Search> without children is equivalent to rendering:
const MySearch = () => (
    <Search>
        <SearchResultsPanel>
            <SearchResultItem />
        </SearchResultsPanel>
    </Search>
);
<SearchResultItem> renders the content.label and content.description for each result. You can customize what it renders by providing a function as the label and the description props. This function takes the search result as a parameter and must return a React element.
For instance:
import {
    Search,
    SearchResultsPanel,
    SearchResultItem,
} from '@react-admin/ra-search';
const MySearch = () => (
    <Search>
        <SearchResultsPanel>
            <SearchResultItem
                label={record => (
                    <>
                        {record.type === 'artists' ? (
                            <PersonIcon />
                        ) : (
                            <MusicIcon />
                        )}
                        <span>{record.content.label}</span>
                    </>
                )}
            />
        </SearchResultsPanel>
    </Search>
);
You can also completely replace the search result item component:
import { Search, SearchResultsPanel } from '@react-admin/ra-search';
const MySearchResultItem = ({ data, onClose }) => (
    <li key={data.id} className="highlight">
        <Link to={data.url} onClick={onClose}>
            <strong>{data.content.label}</strong>
        </Link>
        <p>{data.content.description}</p>
    </li>
);
const MySearch = () => (
    <Search>
        <SearchResultsPanel>
            <MySearchResultItem />
        </SearchResultsPanel>
    </Search>
);
Tip: You can customize the highlight of the search terms by overriding the <SearchResultsPanel sx> prop as following:
const CustomSearch = () => (
    <Search>
        <SearchResultsPanel
            sx={{
                '& ::highlight(search)': {
                    backgroundColor: '#7de5fa',
                },
            }}
        />
    </Search>
);
Customizing the Entire Search Results
Pass a custom React element as a child of <Search> to customize the appearance of the search results. This can be useful e.g. to customize the results grouping, or to arrange search results differently.
ra-search renders the <Search> inside a SearchContext. You can use the useSearchResultContext hook to read the search results, as follows:
import { Search, useSearchResult } from '@react-admin/ra-search';
const MySearch = props => (
    <Search>
        <CustomSearchResultsPanel />
    </Search>
);
const CustomSearchResultsPanel = () => {
    const { data, onClose } = useSearchResult();
    return (
        <ul>
            {data.map(searchResult => (
                <li key={searchResult.id}>
                    <Link to={searchResult.url} onClick={onClose}>
                        <strong>{searchResult.content.label}</strong>
                    </Link>
                    <p>{searchResult.content.description}</p>
                </li>
            ))}
        </ul>
    );
};
