diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx
index 251ba49..9e7bdcd 100644
--- a/packages/app/src/components/Root/Root.tsx
+++ b/packages/app/src/components/Root/Root.tsx
@@ -12,7 +12,7 @@ import {
Settings as SidebarSettings,
UserSettingsSignInAvatar,
} from '@backstage/plugin-user-settings';
-import { SidebarSearchModal } from '@backstage/plugin-search';
+import { SearchModalProvider, useSearchModal } from '@backstage/plugin-search';
import {
Sidebar,
sidebarConfig,
@@ -30,6 +30,7 @@ import {
// import { useApp } from '@backstage/core-plugin-api';
import MenuIcon from '@material-ui/icons/Menu';
import SearchIcon from '@material-ui/icons/Search';
+import { CustomSearchModal } from '../search/CustomModal';
import {useApi, configApiRef} from '@backstage/core-plugin-api';
@@ -118,13 +119,27 @@ const SidebarLogo = () => {
);
};
-export const Root = ({ children }: PropsWithChildren<{}>) => (
+export const Root = ({ children }: PropsWithChildren<{}>) => {
+ const { state, toggleModal } = useSearchModal();
+
+ return (
} to="/search">
-
+
+
+
+
}>
@@ -191,4 +206,4 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
{children}
-);
+)};
diff --git a/packages/app/src/components/search/CustomModal.tsx b/packages/app/src/components/search/CustomModal.tsx
new file mode 100644
index 0000000..8978a5a
--- /dev/null
+++ b/packages/app/src/components/search/CustomModal.tsx
@@ -0,0 +1,157 @@
+/*
+ * CustomModal.tsx is a customized version of the original SearchModal.tsx
+ * The searchResultCustomList component is used rather than element
+ */
+
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback, useEffect, useRef } from 'react';
+import { SearchBar, SearchContextProvider, SearchResultPager } from "@backstage/plugin-search-react";
+import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Divider, Grid, IconButton, makeStyles, useTheme } from "@material-ui/core";
+import CloseIcon from '@material-ui/icons/Close';
+import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
+import { searchResultCustomList } from './SearchResultCustomList';
+import { SearchModalChildrenProps, SearchModalProps } from '@backstage/plugin-search';
+import { useNavigate } from 'react-router-dom';
+import { useContent } from '@backstage/core-components';
+
+const useStyles = makeStyles(theme => ({
+ dialogTitle: {
+ gap: theme.spacing(1),
+ display: 'grid',
+ alignItems: 'center',
+ gridTemplateColumns: '1fr auto',
+ '&> button': {
+ marginTop: theme.spacing(1),
+ },
+ },
+ input: {
+ flex: 1,
+ },
+ button: {
+ '&:hover': {
+ background: 'none',
+ },
+ },
+ // Reduces default height of the modal, keeping a gap of 128px between the top and bottom of the page.
+ paperFullWidth: { height: 'calc(100% - 128px)' },
+ dialogActionsContainer: { padding: theme.spacing(1, 3) },
+ viewResultsLink: { verticalAlign: '0.5em' },
+ }));
+
+export const CustomModal = ({ toggleModal }: SearchModalChildrenProps) => {
+ const classes = useStyles();
+ const navigate = useNavigate();
+ const { transitions } = useTheme();
+ const { focusContent } = useContent();
+ const searchBarRef = useRef(null);
+
+ useEffect(() => {
+ searchBarRef?.current?.focus();
+ });
+
+ const handleSearchResultClick = useCallback(() => {
+ setTimeout(focusContent, transitions.duration.leavingScreen);
+ }, [focusContent, transitions]);
+
+ // This handler is called when "enter" is pressed
+ const handleSearchBarSubmit = useCallback(() => {
+ // Using ref to get the current field value without waiting for a query debounce
+ const query = searchBarRef.current?.value ?? '';
+ navigate(`/search?query=${query}`);
+ handleSearchResultClick();
+ }, [navigate, handleSearchResultClick]);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ onClick={handleSearchBarSubmit}
+ disableRipple
+ >
+ View Full Results
+
+
+
+
+
+
+ {searchResultCustomList}
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ };
+
+export const CustomSearchModal = (props: SearchModalProps) => {
+ const { open = true, hidden, toggleModal, children } = props;
+
+ const classes = useStyles();
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx
index 3bc85fc..2602aab 100644
--- a/packages/app/src/components/search/SearchPage.tsx
+++ b/packages/app/src/components/search/SearchPage.tsx
@@ -1,21 +1,17 @@
import React from 'react';
-import { makeStyles, Theme, Grid, Paper, List } from '@material-ui/core';
+import { makeStyles, Theme, Grid, Paper } from '@material-ui/core';
-import { CatalogSearchResultListItem } from '@backstage/plugin-catalog';
import {
catalogApiRef,
CATALOG_FILTER_EXISTS,
} from '@backstage/plugin-catalog-react';
-import { TechDocsSearchResultListItem } from '@backstage/plugin-techdocs';
import { SearchType } from '@backstage/plugin-search';
import {
SearchBar,
SearchFilter,
- SearchResult,
SearchPagination,
- useSearch,
- DefaultResultListItem
+ useSearch
} from '@backstage/plugin-search-react';
import {
CatalogIcon,
@@ -25,7 +21,8 @@ import {
Page,
} from '@backstage/core-components';
import { useApi } from '@backstage/core-plugin-api';
-import { StackOverflowSearchResultListItem, StackOverflowIcon } from '@backstage/plugin-stack-overflow';
+import { StackOverflowIcon } from '@backstage/plugin-stack-overflow';
+import { searchResultCustomList } from './SearchResultCustomList';
const useStyles = makeStyles((theme: Theme) => ({
search: {
@@ -119,56 +116,7 @@ const SearchPage = () => {
-
- {({ results }) => (
-
- {results.map(({ type, document, highlight, rank }) => {
- switch (type) {
- case 'software-catalog':
- return (
- }
- />
- );
- case 'techdocs':
- return (
- }
- />
- );
- case 'stack-overflow':
- return (
- }
- />
- );
- default:
- return (
-
- );
- }
- })}
-
- )}
- {/* } />
- } />
- } /> */}
-
+ {searchResultCustomList}
diff --git a/packages/app/src/components/search/SearchResultCustomList.tsx b/packages/app/src/components/search/SearchResultCustomList.tsx
new file mode 100644
index 0000000..4cfbc5b
--- /dev/null
+++ b/packages/app/src/components/search/SearchResultCustomList.tsx
@@ -0,0 +1,64 @@
+import React from 'react';
+
+import { List } from '@material-ui/core';
+import { SearchResult, DefaultResultListItem } from '@backstage/plugin-search-react';
+
+import { CatalogSearchResultListItem } from '@backstage/plugin-catalog';
+import { StackOverflowSearchResultListItem, StackOverflowIcon } from '@backstage/plugin-stack-overflow';
+import { CatalogIcon, DocsIcon } from '@backstage/core-components';
+import { TechDocsSearchResultCustomListItem } from './TechDocsSearchResultCustomListItem';
+
+const SearchResultCustomList = () => {
+ return (
+
+ {({ results }) => (
+
+ {results.map(({ type, document, highlight, rank }) => {
+ switch (type) {
+ case 'software-catalog':
+ return (
+ }
+ />
+ );
+ case 'techdocs':
+ return (
+ }
+ />
+ );
+ case 'stack-overflow':
+ return (
+ }
+ />
+ );
+ default:
+ return (
+
+ );
+ }
+ })}
+
+ )}
+
+ )
+}
+
+export const searchResultCustomList = ;
\ No newline at end of file
diff --git a/packages/app/src/components/search/TechDocsSearchResultCustomListItem.tsx b/packages/app/src/components/search/TechDocsSearchResultCustomListItem.tsx
new file mode 100644
index 0000000..e485998
--- /dev/null
+++ b/packages/app/src/components/search/TechDocsSearchResultCustomListItem.tsx
@@ -0,0 +1,183 @@
+/*
+ * TechDocsSearchResultCustomListItem.tsx is a customized version of the original TechDocsSearchResultListItem.tsx
+ * This version removes the entityTitle from the result title and places it as a tag instead
+ */
+
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { PropsWithChildren, ReactNode } from 'react';
+import { Box, Chip, Divider, ListItem, ListItemIcon, ListItemText, makeStyles } from '@material-ui/core';
+import Typography from '@material-ui/core/Typography';
+import { Link } from '@backstage/core-components';
+import { ResultHighlight } from '@backstage/plugin-search-common';
+import { HighlightedSearchResultText } from '@backstage/plugin-search-react';
+
+const useStyles = makeStyles({
+ flexContainer: {
+ flexWrap: 'wrap',
+ },
+ itemText: {
+ width: '100%',
+ marginBottom: '1rem',
+ },
+});
+
+/**
+ * Props for {@link TechDocsSearchResultCustomListItem}.
+ *
+ * @public
+ */
+export type TechDocsSearchResultListItemProps = {
+ icon?: ReactNode | ((result: any) => ReactNode);
+ result?: any;
+ highlight?: ResultHighlight;
+ rank?: number;
+ lineClamp?: number;
+ asListItem?: boolean;
+ asLink?: boolean;
+ title?: string;
+};
+
+/**
+ * Component which renders documentation and related metadata.
+ *
+ * @public
+ */
+export const TechDocsSearchResultCustomListItem = (
+ props: TechDocsSearchResultListItemProps,
+) => {
+ const {
+ result,
+ highlight,
+ lineClamp = 5,
+ asListItem = true,
+ asLink = true,
+ title,
+ icon,
+ } = props;
+ const classes = useStyles();
+
+ const LinkWrapper = ({ children }: PropsWithChildren<{}>) =>
+ asLink ? (
+
+ {children}
+
+ ) : (
+ <>{children}>
+ );
+
+ const TextItem = () => {
+ const resultTitle = highlight?.fields.title ? (
+
+ ) : (
+ result.title
+ );
+
+ const entityTitle = highlight?.fields.entityTitle ? (
+
+ ) : (
+ result.entityTitle
+ );
+
+ const resultName = highlight?.fields.name ? (
+
+ ) : (
+ result.name
+ );
+
+ if (!result) return null;
+
+ return (
+ <>
+
+ {icon &&
+ {typeof icon === 'function' ? icon(result) : icon}
+ }
+
+
+ {title ? (
+ title
+ ) : (
+ <>
+ {resultTitle} docs
+ >
+ )}
+
+ }
+ secondary={
+
+ {highlight?.fields.text ? (
+
+ ) : (
+ result.text
+ )}
+
+ }
+ />
+
+
+
+
+ >
+ );
+ };
+
+ const ListItemWrapper = ({ children }: PropsWithChildren<{}>) =>
+ asListItem ? (
+ <>
+ {children}
+ >
+ ) : (
+ <>{children}>
+ );
+
+ return (
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/app/src/components/utils/icons.tsx b/packages/app/src/components/utils/icons.tsx
index 3af2c35..9565547 100644
--- a/packages/app/src/components/utils/icons.tsx
+++ b/packages/app/src/components/utils/icons.tsx
@@ -33,3 +33,16 @@ export const StackOverFlowIcon = createSvgIcon(
, "StackOverflow");
+
+// @see https://icon-sets.iconify.design/logos/openshift/
+export const OpenShiftSvgIcon = createSvgIcon(, "OpenShift");
\ No newline at end of file
diff --git a/packages/app/src/devex-theme.ts b/packages/app/src/devex-theme.ts
index 956c7e0..01a8ad2 100644
--- a/packages/app/src/devex-theme.ts
+++ b/packages/app/src/devex-theme.ts
@@ -252,7 +252,7 @@ const createCustomThemeOverrides = (
MuiChip: {
root: {
borderRadius: 3,
- backgroundColor: theme.palette.grey[50],
+ backgroundColor: 'rgba(0, 0, 0, .11)',
color: theme.palette.primary.dark,
margin: 4,
},