Merge pull request #10981 from kuangp/feat/search/highlight
feat(search): highlight search result terms
This commit is contained in:
@@ -17,6 +17,7 @@ import { IdentityApi } from '@backstage/core-plugin-api';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { default as React_2 } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
import { ResultHighlight } from '@backstage/plugin-search-common';
|
||||
import { RouteRef } from '@backstage/core-plugin-api';
|
||||
import { TableColumn } from '@backstage/core-components';
|
||||
import { TableProps } from '@backstage/core-components';
|
||||
@@ -388,6 +389,7 @@ export const TechDocsSearchResultListItem: (
|
||||
// @public
|
||||
export type TechDocsSearchResultListItemProps = {
|
||||
result: any;
|
||||
highlight?: ResultHighlight;
|
||||
lineClamp?: number;
|
||||
asListItem?: boolean;
|
||||
asLink?: boolean;
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"@backstage/integration": "^1.2.0-next.0",
|
||||
"@backstage/integration-react": "^1.1.0-next.1",
|
||||
"@backstage/plugin-catalog-react": "^1.1.0-next.1",
|
||||
"@backstage/plugin-search-common": "^0.3.3",
|
||||
"@backstage/plugin-search-react": "^0.2.0-next.1",
|
||||
"@backstage/plugin-techdocs-react": "^0.1.1-next.1",
|
||||
"@backstage/theme": "^0.2.15",
|
||||
@@ -58,7 +59,6 @@
|
||||
"react-helmet": "6.1.0",
|
||||
"react-router": "6.0.0-beta.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-text-truncate": "^0.18.0",
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -143,13 +143,14 @@ const TechDocsSearchBar = (props: TechDocsSearchProps) => {
|
||||
noOptionsText="No results found"
|
||||
value={null}
|
||||
options={options}
|
||||
renderOption={({ document }) => (
|
||||
renderOption={({ document, highlight }) => (
|
||||
<TechDocsSearchResultListItem
|
||||
result={document}
|
||||
lineClamp={3}
|
||||
asListItem={false}
|
||||
asLink={false}
|
||||
title={document.title}
|
||||
highlight={highlight}
|
||||
/>
|
||||
)}
|
||||
loading={loading}
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { Divider, ListItem, ListItemText, makeStyles } from '@material-ui/core';
|
||||
import { Link } from '@backstage/core-components';
|
||||
import TextTruncate from 'react-text-truncate';
|
||||
import { ResultHighlight } from '@backstage/plugin-search-common';
|
||||
import { HighlightedSearchResultText } from '@backstage/plugin-search-react';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
flexContainer: {
|
||||
@@ -36,6 +37,7 @@ const useStyles = makeStyles({
|
||||
*/
|
||||
export type TechDocsSearchResultListItemProps = {
|
||||
result: any;
|
||||
highlight?: ResultHighlight;
|
||||
lineClamp?: number;
|
||||
asListItem?: boolean;
|
||||
asLink?: boolean;
|
||||
@@ -52,31 +54,80 @@ export const TechDocsSearchResultListItem = (
|
||||
) => {
|
||||
const {
|
||||
result,
|
||||
highlight,
|
||||
lineClamp = 5,
|
||||
asListItem = true,
|
||||
asLink = true,
|
||||
title,
|
||||
} = props;
|
||||
const classes = useStyles();
|
||||
const TextItem = () => (
|
||||
<ListItemText
|
||||
className={classes.itemText}
|
||||
primaryTypographyProps={{ variant: 'h6' }}
|
||||
primary={
|
||||
title
|
||||
? title
|
||||
: `${result.title} | ${result.entityTitle ?? result.name} docs`
|
||||
}
|
||||
secondary={
|
||||
<TextTruncate
|
||||
line={lineClamp}
|
||||
truncateText="…"
|
||||
text={result.text}
|
||||
element="span"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
const TextItem = () => {
|
||||
const resultTitle = highlight?.fields.title ? (
|
||||
<HighlightedSearchResultText
|
||||
text={highlight.fields.title}
|
||||
preTag={highlight.preTag}
|
||||
postTag={highlight.postTag}
|
||||
/>
|
||||
) : (
|
||||
result.title
|
||||
);
|
||||
|
||||
const entityTitle = highlight?.fields.entityTitle ? (
|
||||
<HighlightedSearchResultText
|
||||
text={highlight.fields.entityTitle}
|
||||
preTag={highlight.preTag}
|
||||
postTag={highlight.postTag}
|
||||
/>
|
||||
) : (
|
||||
result.entityTitle
|
||||
);
|
||||
|
||||
const resultName = highlight?.fields.name ? (
|
||||
<HighlightedSearchResultText
|
||||
text={highlight.fields.name}
|
||||
preTag={highlight.preTag}
|
||||
postTag={highlight.postTag}
|
||||
/>
|
||||
) : (
|
||||
result.name
|
||||
);
|
||||
|
||||
return (
|
||||
<ListItemText
|
||||
className={classes.itemText}
|
||||
primaryTypographyProps={{ variant: 'h6' }}
|
||||
primary={
|
||||
title ? (
|
||||
title
|
||||
) : (
|
||||
<>
|
||||
{resultTitle} | {entityTitle ?? resultName} docs
|
||||
</>
|
||||
)
|
||||
}
|
||||
secondary={
|
||||
<span
|
||||
style={{
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
WebkitLineClamp: lineClamp,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
{highlight?.fields.text ? (
|
||||
<HighlightedSearchResultText
|
||||
text={highlight.fields.text}
|
||||
preTag={highlight.preTag}
|
||||
postTag={highlight.postTag}
|
||||
/>
|
||||
) : (
|
||||
result.text
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const LinkWrapper = ({ children }: PropsWithChildren<{}>) =>
|
||||
asLink ? <Link to={result.location}>{children}</Link> : <>{children}</>;
|
||||
|
||||
Reference in New Issue
Block a user