Adding customization of SidebarSearchModal search item renderers

Signed-off-by: Joshua Jung <joshua.p.jung@gmail.com>
This commit is contained in:
Joshua Jung
2024-08-16 10:56:05 -05:00
parent 140a61ab8d
commit eca03bdae9
6 changed files with 57 additions and 12 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-search': patch
---
Added ability to customize the search items within the SidebarSearchModal
+1 -1
View File
@@ -30,7 +30,7 @@ This search plugin is primarily responsible for the following:
- Providing a `<SearchPage />` routable extension.
- Exposing various search-related components (like `<SearchModal />`,
`<SidebarSearch />`, etc), which can be composed by a Backstage App or by
`<SidebarSearch />`, etc.), which can be composed by a Backstage App or by
other Backstage Plugins to power search experiences of all kinds.
Don't forget, a lot of functionality is available in web libraries and backend plugins:
@@ -37,12 +37,12 @@ import CloseIcon from '@material-ui/icons/Close';
import React, { useCallback, useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { rootRouteRef } from '../../plugin';
import { rootRouteRef, SearchResultChildrenProvider } from '../../plugin';
/**
* @public
*/
export interface SearchModalChildrenProps {
export interface SearchModalChildrenProps extends SearchResultChildrenProvider {
/**
* A function that should be invoked when navigating away from the modal.
*/
@@ -52,7 +52,7 @@ export interface SearchModalChildrenProps {
/**
* @public
*/
export interface SearchModalProps {
export interface SearchModalProps extends SearchResultChildrenProvider {
/**
* If true, it renders the modal.
*/
@@ -100,7 +100,10 @@ const useStyles = makeStyles(theme => ({
viewResultsLink: { verticalAlign: '0.5em' },
}));
export const Modal = ({ toggleModal }: SearchModalChildrenProps) => {
export const Modal = ({
toggleModal,
searchResultChildren,
}: SearchModalChildrenProps) => {
const classes = useStyles();
const navigate = useNavigate();
const { transitions } = useTheme();
@@ -163,7 +166,9 @@ export const Modal = ({ toggleModal }: SearchModalChildrenProps) => {
<SearchResult
onClick={handleSearchResultClick}
onKeyDown={handleSearchResultClick}
/>
>
{searchResultChildren}
</SearchResult>
</DialogContent>
<DialogActions className={classes.dialogActionsContainer}>
<Grid container direction="row">
@@ -180,7 +185,13 @@ export const Modal = ({ toggleModal }: SearchModalChildrenProps) => {
* @public
*/
export const SearchModal = (props: SearchModalProps) => {
const { open = true, hidden, toggleModal, children } = props;
const {
open = true,
hidden,
toggleModal,
children,
searchResultChildren,
} = props;
const classes = useStyles();
@@ -199,8 +210,15 @@ export const SearchModal = (props: SearchModalProps) => {
>
{open && (
<SearchContextProvider inheritParentContextIfAvailable>
{(children && children({ toggleModal })) ?? (
<Modal toggleModal={toggleModal} />
{(children &&
children({
toggleModal,
searchResultChildren: searchResultChildren || [],
})) ?? (
<Modal
toggleModal={toggleModal}
searchResultChildren={searchResultChildren || []}
/>
)}
</SearchContextProvider>
)}
@@ -20,7 +20,7 @@ import Tab from '@material-ui/core/Tab';
import Tabs from '@material-ui/core/Tabs';
import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles(theme => ({
const useStyles = makeStyles((theme: any) => ({
tabs: {
borderBottom: `1px solid ${theme.palette.textVerySubtle}`,
},
@@ -23,13 +23,14 @@ import {
SearchModalProvider,
useSearchModal,
} from '../SearchModal';
import { SearchResultChildrenProvider } from '../../plugin';
/**
* Props for {@link SidebarSearchModal}.
*
* @public
*/
export type SidebarSearchModalProps = {
export type SidebarSearchModalProps = SearchResultChildrenProvider & {
icon?: IconComponent;
children?: (props: SearchModalChildrenProps) => JSX.Element;
};
@@ -49,6 +50,7 @@ const SidebarSearchModalContent = (props: SidebarSearchModalProps) => {
<SearchModal
{...state}
toggleModal={toggleModal}
searchResultChildren={props.searchResultChildren}
children={props.children}
/>
</>
+21 -1
View File
@@ -25,6 +25,24 @@ import {
createComponentExtension,
fetchApiRef,
} from '@backstage/core-plugin-api';
import { ReactNode } from 'react';
import { SearchResultSet } from '@backstage/plugin-search-common';
/**
* This type allows us to pass children to the <SearchResult> component via the <SideBarSearchModal />.
*
* This allows us to customize the search result items displayed in the SidebarSearchModal, like so:
*
* <SidebarSearchModal searchResultChildren={[
* <MyCustomSearchResultListItem />,
* <TechDocsSearchResultListItem icon={<DocsIcon />} />
* ]} />
*/
export type SearchResultChildrenProvider = {
searchResultChildren?:
| ReactNode
| ((resultSet: SearchResultSet) => JSX.Element);
};
export const rootRouteRef = createRouteRef({
id: 'search',
@@ -63,7 +81,9 @@ export const SearchPage = searchPlugin.provide(
/**
* @public
*/
export const SidebarSearchModal = searchPlugin.provide(
export const SidebarSearchModal = searchPlugin.provide<
(props: SearchResultChildrenProvider) => JSX.Element | null
>(
createComponentExtension({
name: 'SidebarSearchModal',
component: {