diff --git a/.changeset/mean-moles-relate.md b/.changeset/mean-moles-relate.md new file mode 100644 index 0000000000..1b3d01dd96 --- /dev/null +++ b/.changeset/mean-moles-relate.md @@ -0,0 +1,31 @@ +--- +'@backstage/plugin-search-react': minor +--- + +Allow customizing empty state component through `noResultsComponent` property. + +Example: + +```jsx +No results were found}> + {({ results }) => ( + + {results.map(({ type, document }) => { + switch (type) { + case 'custom-result-item': + return ( + + ); + default: + return ( + + ); + } + })} + + )} + +``` diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index ef3e8b19bd..3d1e4091ea 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -402,6 +402,7 @@ export const SearchResultPager: () => JSX.Element; // @public export type SearchResultProps = Pick & { children: (resultSet: SearchResultSet) => JSX.Element; + noResultsComponent?: JSX.Element; }; // @public diff --git a/plugins/search-react/src/components/SearchResult/SearchResult.stories.tsx b/plugins/search-react/src/components/SearchResult/SearchResult.stories.tsx index 6f536510e8..ef9b0d6b5c 100644 --- a/plugins/search-react/src/components/SearchResult/SearchResult.stories.tsx +++ b/plugins/search-react/src/components/SearchResult/SearchResult.stories.tsx @@ -218,3 +218,32 @@ export const GroupLayout = () => { ); }; + +export const WithCustomNoResultsComponent = () => { + return ( + No results were found}> + {({ results }) => ( + + {results.map(({ type, document }) => { + switch (type) { + case 'custom-result-item': + return ( + + ); + default: + return ( + + ); + } + })} + + )} + + ); +}; diff --git a/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx b/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx index 988d59d7cf..5972eaa891 100644 --- a/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx +++ b/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx @@ -93,6 +93,22 @@ describe('SearchResult', () => { }); }); + it('On empty result value state with custom component', async () => { + (useSearch as jest.Mock).mockReturnValueOnce({ + result: { loading: false, error: '', value: { results: [] } }, + }); + + const { getByText } = await renderInTestApp( + No results found}> + {() => <>} + , + ); + + await waitFor(() => { + expect(getByText('No results found')).toBeInTheDocument(); + }); + }); + it('Calls children with results set to result.value', async () => { (useSearch as jest.Mock).mockReturnValueOnce({ result: { diff --git a/plugins/search-react/src/components/SearchResult/SearchResult.tsx b/plugins/search-react/src/components/SearchResult/SearchResult.tsx index dd11f42903..333156aab9 100644 --- a/plugins/search-react/src/components/SearchResult/SearchResult.tsx +++ b/plugins/search-react/src/components/SearchResult/SearchResult.tsx @@ -167,6 +167,7 @@ export const SearchResultState = (props: SearchResultStateProps) => { */ export type SearchResultProps = Pick & { children: (resultSet: SearchResultSet) => JSX.Element; + noResultsComponent?: JSX.Element; }; /** @@ -176,7 +177,13 @@ export type SearchResultProps = Pick & { * @public */ export const SearchResultComponent = (props: SearchResultProps) => { - const { query, children } = props; + const { + query, + children, + noResultsComponent = ( + + ), + } = props; return ( @@ -195,9 +202,7 @@ export const SearchResultComponent = (props: SearchResultProps) => { } if (!value?.results.length) { - return ( - - ); + return noResultsComponent; } return children(value);