diff --git a/.changeset/search-clouds-begin.md b/.changeset/search-clouds-begin.md
new file mode 100644
index 0000000000..b3c6fa4b69
--- /dev/null
+++ b/.changeset/search-clouds-begin.md
@@ -0,0 +1,23 @@
+---
+'@backstage/plugin-search-react': minor
+---
+
+The `` component now accepts an optional property `disableRenderingWithNoResults` to disable rendering when no results are returned.
+Possibility to provide a custom no results component if needed through the `noResultsComponent` property.
+
+Examples:
+
+_Rendering a custom no results component_
+
+```jsx
+}
+/>
+```
+
+_Disable rendering when there are no results_
+
+```jsx
+
+```
diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md
index 194b285e49..1160675c5a 100644
--- a/plugins/search-react/api-report.md
+++ b/plugins/search-react/api-report.md
@@ -329,9 +329,14 @@ export const SearchResultListLayout: (
// @public
export type SearchResultListLayoutProps = ListProps & {
resultItems?: SearchResult_2[];
- renderResultItem?: (resultItem: SearchResult_2) => JSX.Element;
+ renderResultItem?: (
+ value: SearchResult_2,
+ index: number,
+ array: SearchResult_2[],
+ ) => JSX.Element | null;
error?: Error;
loading?: boolean;
+ noResultsComponent?: ReactNode;
};
// @public
@@ -340,6 +345,7 @@ export type SearchResultListProps = Omit<
'loading' | 'error' | 'resultItems'
> & {
query: Partial;
+ disableRenderingWithNoResults?: boolean;
};
// @public (undocumented)
diff --git a/plugins/search-react/src/components/SearchResultList/SearchResultList.stories.tsx b/plugins/search-react/src/components/SearchResultList/SearchResultList.stories.tsx
index 5762aba2d8..fcda4cec87 100644
--- a/plugins/search-react/src/components/SearchResultList/SearchResultList.stories.tsx
+++ b/plugins/search-react/src/components/SearchResultList/SearchResultList.stories.tsx
@@ -119,7 +119,7 @@ export const WithError = () => {
);
};
-export const WithNoResults = () => {
+export const WithDefaultNoResultsComponent = () => {
const [query] = useState>({
types: ['techdocs'],
});
@@ -131,6 +131,21 @@ export const WithNoResults = () => {
);
};
+export const WithCustomNoResultsComponent = () => {
+ const [query] = useState>({
+ types: ['techdocs'],
+ });
+
+ return (
+
+ }
+ />
+
+ );
+};
+
const CustomResultListItem = (props: any) => {
const { icon, result } = props;
diff --git a/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx b/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx
index 20e5a1cba1..93bbaa5602 100644
--- a/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx
+++ b/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx
@@ -121,6 +121,42 @@ describe('SearchResultList', () => {
});
});
+ it('Does not render result group if no results returned and disableRenderingWithNoResults prop is provided', async () => {
+ query.mockResolvedValueOnce({ results: [] });
+ await renderWithEffects(
+ wrapInTestApp(
+
+
+ ,
+ ),
+ );
+
+ await waitFor(() => {
+ expect(screen.queryByText('Documentation')).not.toBeInTheDocument();
+ });
+ });
+
+ it('Should render custom component when no results returned', async () => {
+ query.mockResolvedValueOnce({ results: [] });
+ await renderWithEffects(
+ wrapInTestApp(
+
+
+ ,
+ ),
+ );
+
+ await waitFor(() => {
+ expect(screen.getByText('No results were found')).toBeInTheDocument();
+ });
+ });
+
it('Shows an error panel when results rendering fails', async () => {
query.mockRejectedValueOnce(new Error());
await renderWithEffects(
diff --git a/plugins/search-react/src/components/SearchResultList/SearchResultList.tsx b/plugins/search-react/src/components/SearchResultList/SearchResultList.tsx
index 8f184f7080..4279e8936a 100644
--- a/plugins/search-react/src/components/SearchResultList/SearchResultList.tsx
+++ b/plugins/search-react/src/components/SearchResultList/SearchResultList.tsx
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-import React from 'react';
+import React, { ReactNode } from 'react';
-import { List, ListProps } from '@material-ui/core';
+import { List, ListItem, ListProps } from '@material-ui/core';
import {
EmptyState,
@@ -41,7 +41,11 @@ export type SearchResultListLayoutProps = ListProps & {
/**
* Function to customize how result items are rendered.
*/
- renderResultItem?: (resultItem: SearchResult) => JSX.Element;
+ renderResultItem?: (
+ value: SearchResult,
+ index: number,
+ array: SearchResult[],
+ ) => JSX.Element | null;
/**
* If defined, will render a default error panel.
*/
@@ -50,6 +54,10 @@ export type SearchResultListLayoutProps = ListProps & {
* If defined, will render a default loading progress.
*/
loading?: boolean;
+ /**
+ * Optional component to render when no results. Default to component.
+ */
+ noResultsComponent?: ReactNode;
};
/**
@@ -58,7 +66,21 @@ export type SearchResultListLayoutProps = ListProps & {
* @public
*/
export const SearchResultListLayout = (props: SearchResultListLayoutProps) => {
- const { loading, error, resultItems, renderResultItem, ...rest } = props;
+ const {
+ loading,
+ error,
+ resultItems,
+ renderResultItem = resultItem => (
+
+ ),
+ noResultsComponent = (
+
+ ),
+ ...rest
+ } = props;
return (
@@ -70,10 +92,10 @@ export const SearchResultListLayout = (props: SearchResultListLayoutProps) => {
/>
) : null}
{!loading && !error && resultItems?.length
- ? resultItems.map(resultItem => renderResultItem?.(resultItem) ?? null)
+ ? resultItems.map(renderResultItem)
: null}
{!loading && !error && !resultItems?.length ? (
-
+ {noResultsComponent}
) : null}
);
@@ -91,6 +113,10 @@ export type SearchResultListProps = Omit<
* A search query used for requesting the results to be listed.
*/
query: Partial;
+ /**
+ * Optional property to provide if component should not render the component when no results are found.
+ */
+ disableRenderingWithNoResults?: boolean;
};
/**
@@ -99,13 +125,7 @@ export type SearchResultListProps = Omit<
* @public
*/
export const SearchResultList = (props: SearchResultListProps) => {
- const {
- query,
- renderResultItem = ({ document }) => (
-
- ),
- ...rest
- } = props;
+ const { query, disableRenderingWithNoResults, ...rest } = props;
return (
{
}}
>
- {({ loading, error, value }) => (
-
- )}
+ {({ loading, error, value }) => {
+ if (!value?.results?.length && disableRenderingWithNoResults) {
+ return null;
+ }
+
+ return (
+
+ );
+ }}
);