diff --git a/frontend/src/component/commandBar/CommandBar.tsx b/frontend/src/component/commandBar/CommandBar.tsx index 7dffb52eca..f0d427495f 100644 --- a/frontend/src/component/commandBar/CommandBar.tsx +++ b/frontend/src/component/commandBar/CommandBar.tsx @@ -14,7 +14,6 @@ import { useKeyboardShortcut } from 'hooks/useKeyboardShortcut'; import { SEARCH_INPUT } from 'utils/testIds'; import { useOnClickOutside } from 'hooks/useOnClickOutside'; import { useOnBlur } from 'hooks/useOnBlur'; -import { CommandRecent } from './CommandRecent'; import { useRecentlyVisited } from 'hooks/useRecentlyVisited'; import { CommandResultGroup, @@ -26,6 +25,8 @@ import { useAsyncDebounce } from 'react-table'; import useProjects from 'hooks/api/getters/useProjects/useProjects'; import { CommandFeatures } from './CommandFeatures'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; +import { CommandRecent } from './CommandRecent'; +import { CommandPages } from './CommandPages'; export const CommandResultsPaper = styled(Paper)(({ theme }) => ({ position: 'absolute', @@ -259,11 +260,7 @@ export const CommandBar = () => { icon={'flag'} items={searchedProjects} /> - + } elseShow={ diff --git a/frontend/src/component/commandBar/CommandPageSuggestions.tsx b/frontend/src/component/commandBar/CommandPageSuggestions.tsx index 16b01c6e9a..90e8e963b9 100644 --- a/frontend/src/component/commandBar/CommandPageSuggestions.tsx +++ b/frontend/src/component/commandBar/CommandPageSuggestions.tsx @@ -1,49 +1,16 @@ import { - List, - ListItemButton, - ListItemIcon, - ListItemText, - styled, - Typography, -} from '@mui/material'; + CommandResultGroup, + listItemButtonStyle, + StyledButtonTypography, + StyledListItemIcon, + StyledListItemText, +} from './RecentlyVisited/CommandResultGroup'; +import { ListItemButton } from '@mui/material'; import { Link } from 'react-router-dom'; import { IconRenderer } from 'component/layout/MainLayout/NavigationSidebar/IconRenderer'; -import type { Theme } from '@mui/material/styles/createTheme'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; import type { JSX } from 'react'; -const listItemButtonStyle = (theme: Theme) => ({ - border: `1px solid transparent`, - borderLeft: `${theme.spacing(0.5)} solid transparent`, - '&:hover': { - border: `1px solid ${theme.palette.primary.main}`, - borderLeft: `${theme.spacing(0.5)} solid ${theme.palette.primary.main}`, - }, -}); - -const StyledContainer = styled('div')(({ theme }) => ({ - marginBottom: theme.spacing(3), -})); - -const StyledButtonTypography = styled(Typography)(({ theme }) => ({ - fontSize: theme.fontSizes.smallerBody, -})); - -const StyledTypography = styled(Typography)(({ theme }) => ({ - fontSize: theme.fontSizes.smallBody, - padding: theme.spacing(0, 2.5), -})); - -const StyledListItemIcon = styled(ListItemIcon)(({ theme }) => ({ - minWidth: theme.spacing(4), - margin: theme.spacing(0.25, 0), -})); - -const StyledListItemText = styled(ListItemText)(({ theme }) => ({ - margin: 0, - fontSize: theme.fontSizes.smallBody, -})); - interface IPageSuggestionItem { icon: JSX.Element; name: string; @@ -93,38 +60,34 @@ export const CommandPageSuggestions = ({ }); }; return ( - - Pages - - {pageItems.map((item, index) => ( - { - onClick(item); - }} - sx={listItemButtonStyle} + + {pageItems.map((item, index) => ( + { + onClick(item); + }} + sx={listItemButtonStyle} + > + ({ + fontSize: theme.fontSizes.smallBody, + minWidth: theme.spacing(0.5), + margin: theme.spacing(0, 1, 0, 0), + })} > - ({ - color: theme.palette.primary.main, - fontSize: theme.fontSizes.smallBody, - minWidth: theme.spacing(0.5), - margin: theme.spacing(0, 1, 0, 0), - })} - > - {item.icon} - - - - {item.name} - - - - ))} - - + {item.icon} + + + + {item.name} + + + + ))} + ); }; diff --git a/frontend/src/component/commandBar/CommandPages.tsx b/frontend/src/component/commandBar/CommandPages.tsx new file mode 100644 index 0000000000..8b1d336910 --- /dev/null +++ b/frontend/src/component/commandBar/CommandPages.tsx @@ -0,0 +1,63 @@ +import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; +import { Link } from 'react-router-dom'; +import { + CommandResultGroup, + StyledButtonTypography, + StyledListItemIcon, + StyledListItemText, + listItemButtonStyle, + type CommandResultGroupItem, +} from './RecentlyVisited/CommandResultGroup'; +import { ListItemButton } from '@mui/material'; +import { IconRenderer } from 'component/layout/MainLayout/NavigationSidebar/IconRenderer'; + +export const CommandPages = ({ + items, +}: { + items: CommandResultGroupItem[]; +}) => { + const { trackEvent } = usePlausibleTracker(); + const groupName = 'Pages'; + + const onClick = (item: CommandResultGroupItem) => { + trackEvent('command-bar', { + props: { + eventType: `click`, + source: 'search', + eventTarget: groupName, + ...(groupName === 'Pages' && { pageType: item.name }), + }, + }); + }; + return ( + + {items.map((item, index) => ( + { + onClick(item); + }} + sx={listItemButtonStyle} + > + ({ + fontSize: theme.fontSizes.smallBody, + minWidth: theme.spacing(0.5), + margin: theme.spacing(0, 1, 0, 0), + })} + > + + + + + {item.name} + + + + ))} + + ); +}; diff --git a/frontend/src/component/commandBar/CommandRecent.tsx b/frontend/src/component/commandBar/CommandRecent.tsx index c6339f2b09..96977e3e0a 100644 --- a/frontend/src/component/commandBar/CommandRecent.tsx +++ b/frontend/src/component/commandBar/CommandRecent.tsx @@ -1,60 +1,11 @@ import { - Icon, - List, - ListItemButton, - ListItemIcon, - ListItemText, - styled, - Typography, -} from '@mui/material'; -import { Link } from 'react-router-dom'; -import { - IconRenderer, - StyledProjectIcon, -} from 'component/layout/MainLayout/NavigationSidebar/IconRenderer'; + CommandResultGroup, + RecentlyVisitedFeatureButton, + RecentlyVisitedPathButton, + RecentlyVisitedProjectButton, +} from './RecentlyVisited/CommandResultGroup'; +import { List } from '@mui/material'; import type { LastViewedPage } from 'hooks/useRecentlyVisited'; -import type { Theme } from '@mui/material/styles/createTheme'; -import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; -import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; - -const listItemButtonStyle = (theme: Theme) => ({ - border: `1px solid transparent`, - borderLeft: `${theme.spacing(0.5)} solid transparent`, - '&:hover': { - border: `1px solid ${theme.palette.primary.main}`, - borderLeft: `${theme.spacing(0.5)} solid ${theme.palette.primary.main}`, - }, -}); - -const StyledContainer = styled('div')(({ theme }) => ({ - marginBottom: theme.spacing(3), -})); - -const StyledButtonTypography = styled(Typography)(({ theme }) => ({ - fontSize: theme.fontSizes.smallerBody, -})); - -const ColoredStyledProjectIcon = styled(StyledProjectIcon)(({ theme }) => ({ - fill: theme.palette.primary.main, - stroke: theme.palette.primary.main, -})); - -const StyledTypography = styled(Typography)(({ theme }) => ({ - fontSize: theme.fontSizes.smallBody, - padding: theme.spacing(0, 2.5), -})); - -const StyledListItemIcon = styled(ListItemIcon)(({ theme }) => ({ - minWidth: theme.spacing(0.5), - margin: theme.spacing(0, 1, 0, 0), - color: theme.palette.primary.main, -})); - -const StyledListItemText = styled(ListItemText)(({ theme }) => ({ - margin: 0, - fontSize: theme.fontSizes.smallBody, -})); const toListItemButton = ( item: LastViewedPage, @@ -86,127 +37,6 @@ const toListItemButton = ( ); }; -const RecentlyVisitedFeatureButton = ({ - key, - projectId, - featureId, -}: { key: string; projectId: string; featureId: string }) => { - const { trackEvent } = usePlausibleTracker(); - - const onClick = () => { - trackEvent('command-bar', { - props: { - eventType: `click`, - source: 'recently-visited', - eventTarget: 'Flags', - }, - }); - }; - return ( - - - {'flag'} - - - - {featureId} - - - - ); -}; - -const RecentlyVisitedPathButton = ({ - path, - key, - name, -}: { path: string; key: string; name: string }) => { - const { trackEvent } = usePlausibleTracker(); - - const onClick = () => { - trackEvent('command-bar', { - props: { - eventType: `click`, - source: 'recently-visited', - eventTarget: 'Pages', - pageType: name, - }, - }); - }; - return ( - - ({ color: theme.palette.primary.main })} - > - } - elseShow={} - /> - - - - {name} - - - - ); -}; - -const RecentlyVisitedProjectButton = ({ - projectId, - key, -}: { projectId: string; key: string }) => { - const { trackEvent } = usePlausibleTracker(); - const { project, loading } = useProjectOverview(projectId); - const projectDeleted = !project.name && !loading; - - const onClick = () => { - trackEvent('command-bar', { - props: { - eventType: `click`, - source: 'recently-visited', - eventTarget: 'Projects', - }, - }); - }; - - if (projectDeleted) return null; - return ( - - - - - - - {project.name} - - - - ); -}; - export const CommandRecent = ({ lastVisited, routes, @@ -218,11 +48,8 @@ export const CommandRecent = ({ toListItemButton(item, routes, index), ); return ( - - - Recently visited - + {buttons} - + ); }; diff --git a/frontend/src/component/commandBar/RecentlyVisited/CommandResultGroup.tsx b/frontend/src/component/commandBar/RecentlyVisited/CommandResultGroup.tsx index 1b99392332..726e01fe64 100644 --- a/frontend/src/component/commandBar/RecentlyVisited/CommandResultGroup.tsx +++ b/frontend/src/component/commandBar/RecentlyVisited/CommandResultGroup.tsx @@ -10,30 +10,43 @@ import { import { Link } from 'react-router-dom'; import type { Theme } from '@mui/material/styles/createTheme'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; -import { StyledProjectIcon } from 'component/layout/MainLayout/NavigationSidebar/IconRenderer'; +import { + IconRenderer, + StyledProjectIcon, +} from 'component/layout/MainLayout/NavigationSidebar/IconRenderer'; import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; +import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview'; -const listItemButtonStyle = (theme: Theme) => ({ - borderRadius: theme.spacing(0.5), +export const listItemButtonStyle = (theme: Theme) => ({ + border: `1px solid transparent`, borderLeft: `${theme.spacing(0.5)} solid transparent`, - '&.Mui-selected': { + '&:hover, &:focus': { + border: `1px solid ${theme.palette.primary.main}`, borderLeft: `${theme.spacing(0.5)} solid ${theme.palette.primary.main}`, }, }); +const StyledContainer = styled('div')(({ theme }) => ({ + marginBottom: theme.spacing(3), +})); -const StyledTypography = styled(Typography)(({ theme }) => ({ +export const StyledTypography = styled(Typography)(({ theme }) => ({ fontSize: theme.fontSizes.bodySize, - padding: theme.spacing(0, 3), + padding: theme.spacing(0, 2.5), })); -const StyledListItemIcon = styled(ListItemIcon)(({ theme }) => ({ - minWidth: theme.spacing(4), - margin: theme.spacing(0.25, 0), +export const StyledListItemIcon = styled(ListItemIcon)(({ theme }) => ({ + minWidth: theme.spacing(0.5), + margin: theme.spacing(0, 1, 0, 0), })); -const StyledListItemText = styled(ListItemText)(({ theme }) => ({ +export const StyledListItemText = styled(ListItemText)(({ theme }) => ({ margin: 0, + fontSize: theme.fontSizes.bodySize, +})); + +export const StyledButtonTypography = styled(Typography)(({ theme }) => ({ + fontSize: theme.fontSizes.bodySize, })); export interface CommandResultGroupItem { @@ -42,24 +55,150 @@ export interface CommandResultGroupItem { description?: string | null; } +export const RecentlyVisitedPathButton = ({ + path, + key, + name, +}: { path: string; key: string; name: string }) => { + const { trackEvent } = usePlausibleTracker(); + + const onClick = () => { + trackEvent('command-bar', { + props: { + eventType: `click`, + source: 'recently-visited', + eventTarget: 'Pages', + pageType: name, + }, + }); + }; + + return ( + + + } + elseShow={} + /> + + + + {name} + + + + ); +}; + +export const RecentlyVisitedProjectButton = ({ + projectId, + key, +}: { projectId: string; key: string }) => { + const { trackEvent } = usePlausibleTracker(); + const { project, loading } = useProjectOverview(projectId); + const projectDeleted = !project.name && !loading; + + const onClick = () => { + trackEvent('command-bar', { + props: { + eventType: `click`, + source: 'recently-visited', + eventTarget: 'Projects', + }, + }); + }; + + if (projectDeleted) return null; + return ( + + + + + + + {project.name} + + + + ); +}; + +export const RecentlyVisitedFeatureButton = ({ + key, + projectId, + featureId, +}: { + key: string; + projectId: string; + featureId: string; +}) => { + const onClick = () => { + const { trackEvent } = usePlausibleTracker(); + + trackEvent('command-bar', { + props: { + eventType: `click`, + source: 'recently-visited', + eventTarget: 'Flags', + }, + }); + }; + return ( + + + {'flag'} + + + + {featureId} + + + + ); +}; + interface CommandResultGroupProps { icon: string; groupName: string; - items: CommandResultGroupItem[]; + items?: CommandResultGroupItem[]; + children?: React.ReactNode; } export const CommandResultGroup = ({ icon, groupName, items, + children, }: CommandResultGroupProps) => { const { trackEvent } = usePlausibleTracker(); - const slicedItems = items.slice(0, 3); - - if (items.length === 0) { + if (!children && (!items || items.length === 0)) { return null; } + const slicedItems = items?.slice(0, 3); + const onClick = (item: CommandResultGroupItem) => { trackEvent('command-bar', { props: { @@ -70,13 +209,15 @@ export const CommandResultGroup = ({ }, }); }; + return ( - <> + {groupName} - {slicedItems.map((item, index) => ( + {children} + {slicedItems?.map((item, index) => ( - {item.name} + + {item.name} + ))} - + ); };