From c6448ee50924cb08e6765a79d16787b852ca9e37 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Wed, 21 Dec 2022 12:06:05 +0100 Subject: [PATCH 1/2] Document how to provide custom search result list items Signed-off-by: Eric Peterson --- .../integrating-search-into-plugins.md | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/docs/plugins/integrating-search-into-plugins.md b/docs/plugins/integrating-search-into-plugins.md index 3855dd5474..20026189d8 100644 --- a/docs/plugins/integrating-search-into-plugins.md +++ b/docs/plugins/integrating-search-into-plugins.md @@ -333,3 +333,85 @@ reading the search context. If you produce something generic and reusable, consider contributing your component upstream so that all users of the Backstage Search Platform can benefit. Issues and pull requests welcome. + +#### Custom search results + +Search results throughout Backstage are rendered as lists so that list items can easily be customized; although a default result list item is available, plugins are in the best position to provide custom result list items that surface relevant information only known to the plugin. + +The example below imagines `YourCustomSearchResult` as a type of search result that contains associated `tags` which could be rendered as chips below the title/text. + +```tsx +import { Link } from '@backstage/core-components'; +import { useAnalytics } from '@backstage/core-plugin-api'; +import { ResultHighlight } from '@backstage/plugin-search-common'; +import { HighlightedSearchResultText } from '@backstage/plugin-search-react'; + +type CustomSearchResultListItemProps = { + result: YourCustomSearchResult; + rank?: number; + highlight?: ResultHighlight; +}; + +export const CustomSearchResultListItem = ( + props: CustomSearchResultListItemProps, +) => { + const { title, text, location, tags } = props.result; + + const analytics = useAnalytics(); + const handleClick = () => { + analytics.captureEvent('discover', title, { + attributes: { to: location }, + value: props.rank, + }); + }; + + return ( + + + + + ) : ( + title + ) + } + secondary={ + highlight?.fields?.text ? ( + + ) : ( + text + ) + } + /> + {tags && + tags.map((tag: string) => ( + + ))} + + + + + ); +}; +``` + +The optional use of the `` component makes it possible to highlight relevant parts of the result based on the user's search query. + +**Note on Analytics**: In order to track and improve search experiences across Backstage, it's important to understand when and what users search for, as well as what they click on after searching. When implementing a custom result component, it's your responsibility to instrument it according to search analytics conventions. In particular: + +- You must use the `analytics.captureEvent` method, from the `useAnalytics()` hook. +- You must ensure that the action of the event, representing a click on a search result item, is `discover`, and the subject is the `title` of the clicked result. In addition, the `to` attribute should be set to the result's `location`, and the `value` of the event must be set to the `rank` (passed in as a prop). +- You must ensure that the aforementioned `captureEvent` method is called when a user clicks the link; you should further ensure that the `noTrack` prop is added to the link (which disables default link click tracking, in favor of this custom instrumentation). + +For other examples and inspiration on custom result list items, check out the [``](https://github.com/backstage/backstage/blob/c981e83/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx) or [``](https://github.com/backstage/backstage/blob/c981e83/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx) components. From 9da74dcee627826c310c63e28065b1d1099fb035 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Wed, 21 Dec 2022 14:48:12 +0100 Subject: [PATCH 2/2] Link to storybook and tweak language for intended audience Signed-off-by: Eric Peterson --- docs/plugins/integrating-search-into-plugins.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/plugins/integrating-search-into-plugins.md b/docs/plugins/integrating-search-into-plugins.md index 20026189d8..524daf18cd 100644 --- a/docs/plugins/integrating-search-into-plugins.md +++ b/docs/plugins/integrating-search-into-plugins.md @@ -336,7 +336,7 @@ benefit. Issues and pull requests welcome. #### Custom search results -Search results throughout Backstage are rendered as lists so that list items can easily be customized; although a default result list item is available, plugins are in the best position to provide custom result list items that surface relevant information only known to the plugin. +Search results throughout Backstage are rendered as lists so that list items can easily be customized; although a [default result list item](https://backstage.io/storybook/?path=/story/plugins-search-defaultresultlistitem--default) is available, plugins are in the best position to provide custom result list items that surface relevant information only known to the plugin. The example below imagines `YourCustomSearchResult` as a type of search result that contains associated `tags` which could be rendered as chips below the title/text. @@ -408,9 +408,9 @@ export const CustomSearchResultListItem = ( The optional use of the `` component makes it possible to highlight relevant parts of the result based on the user's search query. -**Note on Analytics**: In order to track and improve search experiences across Backstage, it's important to understand when and what users search for, as well as what they click on after searching. When implementing a custom result component, it's your responsibility to instrument it according to search analytics conventions. In particular: +**Note on Analytics**: In order for app integrators to track and improve search experiences across Backstage, it's important for them to understand when and what users search for, as well as what they click on after searching. When providing a custom result component, it's your responsibility as a plugin developer to instrument it according to search analytics conventions. In particular: -- You must use the `analytics.captureEvent` method, from the `useAnalytics()` hook. +- You must use the `analytics.captureEvent` method, from the `useAnalytics()` hook (detailed [plugin analytics docs are here](./analytics.md)). - You must ensure that the action of the event, representing a click on a search result item, is `discover`, and the subject is the `title` of the clicked result. In addition, the `to` attribute should be set to the result's `location`, and the `value` of the event must be set to the `rank` (passed in as a prop). - You must ensure that the aforementioned `captureEvent` method is called when a user clicks the link; you should further ensure that the `noTrack` prop is added to the link (which disables default link click tracking, in favor of this custom instrumentation).