1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-31 13:47:02 +02:00

feat: update configuration menu (#10041)

Updated "Configure" navigation, with all interactions including expanding/collapsing size of the menu.
This commit is contained in:
Tymoteusz Czech 2025-05-29 13:26:26 +02:00 committed by GitHub
parent e67e60a363
commit 016d82a797
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 338 additions and 170 deletions

View File

@ -0,0 +1,77 @@
import { type FC, useEffect, useState } from 'react';
import { MenuListAccordion } from './ListItems.tsx';
import { useExpanded } from './useExpanded.ts';
import type { NavigationMode } from './NavigationMode.tsx';
import { IconRenderer } from './IconRenderer.tsx';
import { ConfigurationNavigationList } from './ConfigurationNavigationList.tsx';
import { useRoutes } from './useRoutes.ts';
type ConfigurationAccordionProps = {
mode: NavigationMode;
setMode;
activeItem?: string;
onClick?: () => void;
};
export const ConfigurationAccordion: FC<ConfigurationAccordionProps> = ({
mode,
setMode,
activeItem,
onClick,
}) => {
const [expanded, changeExpanded] = useExpanded<'configure'>();
const [temporarilyExpanded, setTemporarilyExpanded] = useState(false);
const { routes } = useRoutes();
const subRoutes = routes.mainNavRoutes;
const hasActiveItem = Boolean(
activeItem && subRoutes.some((route) => route.path === activeItem),
);
useEffect(() => {
if (mode === 'mini') {
setTemporarilyExpanded(false);
}
}, [mode]);
const onExpandChange = () => {
changeExpanded('configure', !expanded.includes('configure'));
if (temporarilyExpanded) {
setTemporarilyExpanded(false);
setMode('mini');
}
if (mode === 'mini') {
setTemporarilyExpanded(true);
setMode('full');
}
};
const onItemClick = () => {
if (temporarilyExpanded) {
setTemporarilyExpanded(false);
setMode('mini');
}
onClick?.();
};
return (
<MenuListAccordion
title='Configure'
expanded={
(expanded.includes('configure') || temporarilyExpanded) &&
mode === 'full'
}
onExpandChange={onExpandChange}
mode={mode}
icon={<IconRenderer path='Configure' />}
active={hasActiveItem}
>
<ConfigurationNavigationList
routes={subRoutes}
mode={mode}
onClick={onItemClick}
activeItem={activeItem}
/>
</MenuListAccordion>
);
};

View File

@ -1,6 +1,6 @@
import type React from 'react'; import type React from 'react';
import type { FC } from 'react'; import type { FC } from 'react';
import type { NavigationMode } from './NavigationMode.tsx'; import type { NavigationMode } from './NavigationMode.ts';
import { Typography } from '@mui/material'; import { Typography } from '@mui/material';
import Accordion from '@mui/material/Accordion'; import Accordion from '@mui/material/Accordion';
import AccordionDetails from '@mui/material/AccordionDetails'; import AccordionDetails from '@mui/material/AccordionDetails';
@ -21,7 +21,7 @@ const AccordionHeader: FC<{ children?: React.ReactNode }> = ({ children }) => {
); );
}; };
export const SecondaryNavigation: FC<{ export const ConfigurationNavigation: FC<{
expanded: boolean; expanded: boolean;
onExpandChange: (expanded: boolean) => void; onExpandChange: (expanded: boolean) => void;
mode: NavigationMode; mode: NavigationMode;

View File

@ -1,7 +1,7 @@
import type { FC } from 'react'; import type { FC } from 'react';
import type { INavigationMenuItem } from 'interfaces/route'; import type { INavigationMenuItem } from 'interfaces/route';
import type { NavigationMode } from './NavigationMode.tsx'; import type { NavigationMode } from './NavigationMode.ts';
import { FullListItem, MiniListItem } from './ListItems.tsx'; import { MenuListItem } from './ListItems.tsx';
import { List } from '@mui/material'; import { List } from '@mui/material';
import { IconRenderer } from './IconRenderer.tsx'; import { IconRenderer } from './IconRenderer.tsx';
import { useUiFlag } from 'hooks/useUiFlag.ts'; import { useUiFlag } from 'hooks/useUiFlag.ts';
@ -9,20 +9,19 @@ import StopRoundedIcon from '@mui/icons-material/StopRounded';
import { useShowBadge } from 'component/layout/components/EnterprisePlanBadge/useShowBadge'; import { useShowBadge } from 'component/layout/components/EnterprisePlanBadge/useShowBadge';
import { EnterprisePlanBadge } from 'component/layout/components/EnterprisePlanBadge/EnterprisePlanBadge'; import { EnterprisePlanBadge } from 'component/layout/components/EnterprisePlanBadge/EnterprisePlanBadge';
export const SecondaryNavigationList: FC<{ export const ConfigurationNavigationList: FC<{
routes: INavigationMenuItem[]; routes: INavigationMenuItem[];
mode: NavigationMode; mode: NavigationMode;
onClick: (activeItem: string) => void; onClick: (activeItem: string) => void;
activeItem?: string; activeItem?: string;
}> = ({ routes, mode, onClick, activeItem }) => { }> = ({ routes, mode, onClick, activeItem }) => {
const showBadge = useShowBadge(); const showBadge = useShowBadge();
const DynamicListItem = mode === 'mini' ? MiniListItem : FullListItem;
const sideMenuCleanup = useUiFlag('sideMenuCleanup'); const sideMenuCleanup = useUiFlag('sideMenuCleanup');
return ( return (
<List> <List>
{routes.map((route) => ( {routes.map((route) => (
<DynamicListItem <MenuListItem
key={route.title} key={route.title}
onClick={() => onClick(route.path)} onClick={() => onClick(route.path)}
href={route.path} href={route.path}
@ -33,13 +32,16 @@ export const SecondaryNavigationList: FC<{
<EnterprisePlanBadge /> <EnterprisePlanBadge />
) : null ) : null
} }
> mode={mode}
{sideMenuCleanup ? ( icon={
sideMenuCleanup ? (
<StopRoundedIcon fontSize='small' color='primary' /> <StopRoundedIcon fontSize='small' color='primary' />
) : ( ) : (
<IconRenderer path={route.path} /> <IconRenderer path={route.path} />
)} )
</DynamicListItem> }
secondary={sideMenuCleanup}
/>
))} ))}
</List> </List>
); );

View File

@ -1,6 +1,8 @@
import type React from 'react';
import type { FC, ReactNode } from 'react'; import type { FC, ReactNode } from 'react';
import { import {
Accordion,
AccordionDetails,
AccordionSummary,
ListItem, ListItem,
ListItemButton, ListItemButton,
ListItemIcon, ListItemIcon,
@ -13,6 +15,8 @@ import { Link } from 'react-router-dom';
import { basePath } from 'utils/formatPath'; import { basePath } from 'utils/formatPath';
import SignOutIcon from '@mui/icons-material/ExitToApp'; import SignOutIcon from '@mui/icons-material/ExitToApp';
import type { Theme } from '@mui/material/styles/createTheme'; import type { Theme } from '@mui/material/styles/createTheme';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import type { NavigationMode } from './NavigationMode.tsx';
const listItemButtonStyle = (theme: Theme) => ({ const listItemButtonStyle = (theme: Theme) => ({
borderRadius: theme.spacing(0.5), borderRadius: theme.spacing(0.5),
@ -22,12 +26,17 @@ const listItemButtonStyle = (theme: Theme) => ({
}, },
}); });
const CappedText = styled(Typography)({ const CappedText = styled(Typography)<{
bold?: boolean;
}>(({ theme, bold }) => ({
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
overflow: 'hidden', overflow: 'hidden',
textOverflow: 'ellipsis', textOverflow: 'ellipsis',
width: '100%', width: '100%',
}); fontWeight: bold
? theme.typography.fontWeightBold
: theme.typography.fontWeightRegular,
}));
const StyledListItemIcon = styled(ListItemIcon)(({ theme }) => ({ const StyledListItemIcon = styled(ListItemIcon)(({ theme }) => ({
minWidth: theme.spacing(4), minWidth: theme.spacing(4),
@ -38,37 +47,10 @@ const StyledListItemText = styled(ListItemText)(({ theme }) => ({
margin: 0, margin: 0,
})); }));
export const FullListItem: FC<{
href: string;
text: string;
badge?: ReactNode;
onClick: () => void;
selected?: boolean;
children?: React.ReactNode;
}> = ({ href, text, badge, onClick, selected, children }) => {
return (
<ListItem disablePadding onClick={onClick}>
<ListItemButton
dense={true}
component={Link}
to={href}
sx={listItemButtonStyle}
selected={selected}
>
<StyledListItemIcon>{children}</StyledListItemIcon>
<StyledListItemText>
<CappedText>{text}</CappedText>
</StyledListItemText>
{badge}
</ListItemButton>
</ListItem>
);
};
export const ExternalFullListItem: FC<{ export const ExternalFullListItem: FC<{
href: string; href: string;
text: string; text: string;
children?: React.ReactNode; children?: ReactNode;
}> = ({ href, text, children }) => { }> = ({ href, text, children }) => {
return ( return (
<ListItem disablePadding> <ListItem disablePadding>
@ -88,6 +70,7 @@ export const ExternalFullListItem: FC<{
</ListItem> </ListItem>
); );
}; };
export const SignOutItem = () => { export const SignOutItem = () => {
return ( return (
<form method='POST' action={`${basePath}/logout`}> <form method='POST' action={`${basePath}/logout`}>
@ -110,26 +93,139 @@ export const SignOutItem = () => {
); );
}; };
export const MiniListItem: FC<{ export const MenuListItem: FC<{
href: string; href: string;
text: string; text: string;
selected?: boolean; selected?: boolean;
badge?: ReactNode;
onClick: () => void; onClick: () => void;
children?: React.ReactNode; icon?: ReactNode;
}> = ({ href, text, selected, onClick, children }) => { children?: ReactNode;
mode?: NavigationMode;
secondary?: boolean;
}> = ({
href,
text,
selected,
onClick,
icon,
mode = 'full',
badge,
children,
secondary,
}) => {
return ( return (
<ListItem disablePadding onClick={onClick}> <ListItem disablePadding onClick={onClick}>
<ListItemButton <ListItemButton
dense={true} dense
component={Link} component={Link}
to={href} to={href}
sx={listItemButtonStyle} sx={(theme) => ({
...listItemButtonStyle(theme),
...(mode === 'full' &&
secondary && {
paddingLeft: theme.spacing(4),
}),
})}
selected={selected} selected={selected}
> >
{mode === 'mini' ? (
<Tooltip title={text} placement='right'> <Tooltip title={text} placement='right'>
<StyledListItemIcon>{children}</StyledListItemIcon> <StyledListItemIcon>{icon}</StyledListItemIcon>
</Tooltip> </Tooltip>
) : (
<>
<StyledListItemIcon>{icon}</StyledListItemIcon>
<StyledListItemText>
<CappedText>{text}</CappedText>
</StyledListItemText>
{badge}
</>
)}
</ListItemButton> </ListItemButton>
{children}
</ListItem>
);
};
const StyledAccordion = styled(Accordion)(({ theme }) => ({
flexGrow: 1,
'.MuiAccordionSummary-root': {
minHeight: 'auto',
borderRadius: theme.spacing(1),
borderLeft: `${theme.spacing(0.5)} solid transparent`,
margin: 0,
paddingTop: theme.spacing(0.5),
paddingBottom: theme.spacing(0.5),
'.MuiAccordionSummary-content': { margin: 0 },
'&>.MuiAccordionSummary-content.MuiAccordionSummary-content': {
margin: '0',
alignItems: 'center',
},
},
'.MuiAccordionSummary-content': {
margin: 0,
display: 'flex',
alignItems: 'center',
},
'.MuiAccordionSummary-expandIconWrapper': {
position: 'absolute',
right: theme.spacing(1),
},
}));
export const MenuListAccordion: FC<{
title: string;
expanded: boolean;
onExpandChange: (expanded: boolean) => void;
children?: ReactNode;
mode?: NavigationMode;
icon?: ReactNode;
active?: boolean;
}> = ({ title, expanded, mode, icon, onExpandChange, children, active }) => {
return (
<ListItem disablePadding sx={{ display: 'flex' }}>
<StyledAccordion
disableGutters={true}
sx={{
boxShadow: 'none',
'&:before': {
display: 'none',
},
}}
expanded={expanded}
onChange={(_, expand) => {
onExpandChange(expand);
}}
>
<AccordionSummary
sx={{ padding: 0 }}
expandIcon={mode === 'full' ? <ExpandMoreIcon /> : null}
>
<ListItemButton
dense
sx={listItemButtonStyle}
selected={active && mode === 'mini'}
disableRipple
>
{mode === 'mini' ? (
<Tooltip title={title} placement='right'>
<StyledListItemIcon>{icon}</StyledListItemIcon>
</Tooltip>
) : (
<>
<StyledListItemIcon>{icon}</StyledListItemIcon>
<StyledListItemText>
<CappedText bold={active}>
{title}
</CappedText>
</StyledListItemText>
</>
)}
</ListItemButton>
</AccordionSummary>
<AccordionDetails sx={{ p: 0 }}>{children}</AccordionDetails>
</StyledAccordion>
</ListItem> </ListItem>
); );
}; };

View File

@ -5,24 +5,32 @@ import {
OtherLinksList, OtherLinksList,
} from './NavigationList.tsx'; } from './NavigationList.tsx';
import type { NewInUnleash } from './NewInUnleash/NewInUnleash.tsx'; import type { NewInUnleash } from './NewInUnleash/NewInUnleash.tsx';
import { SecondaryNavigationList } from './SecondaryNavigationList.tsx'; import { ConfigurationNavigationList } from './ConfigurationNavigationList.tsx';
import { useRoutes } from './useRoutes.ts'; import { useRoutes } from './useRoutes.ts';
import { useUiFlag } from 'hooks/useUiFlag.ts';
export const MobileNavigationSidebar: FC<{ export const MobileNavigationSidebar: FC<{
onClick: () => void; onClick: () => void;
NewInUnleash?: typeof NewInUnleash; NewInUnleash?: typeof NewInUnleash;
}> = ({ onClick, NewInUnleash }) => { }> = ({ onClick, NewInUnleash }) => {
const { routes } = useRoutes(); const { routes } = useRoutes();
const sideMenuCleanup = useUiFlag('sideMenuCleanup');
return ( return (
<> <>
{NewInUnleash ? <NewInUnleash /> : null} {NewInUnleash ? <NewInUnleash /> : null}
<PrimaryNavigationList mode='full' onClick={onClick} /> <PrimaryNavigationList
<SecondaryNavigationList mode='full'
onClick={onClick}
setMode={() => {}}
/>
{!sideMenuCleanup ? (
<ConfigurationNavigationList
routes={routes.mainNavRoutes} routes={routes.mainNavRoutes}
mode='full' mode='full'
onClick={onClick} onClick={onClick}
/> />
) : null}
<AdminSettingsLink mode={'full'} onClick={onClick} /> <AdminSettingsLink mode={'full'} onClick={onClick} />
<OtherLinksList /> <OtherLinksList />
</> </>

View File

@ -1,10 +1,9 @@
import type { FC } from 'react'; import type { ComponentProps, FC } from 'react';
import type { INavigationMenuItem } from 'interfaces/route'; import type { INavigationMenuItem } from 'interfaces/route';
import type { NavigationMode } from './NavigationMode.tsx'; import type { NavigationMode } from './NavigationMode.tsx';
import { import {
ExternalFullListItem, ExternalFullListItem,
FullListItem, MenuListItem,
MiniListItem,
SignOutItem, SignOutItem,
} from './ListItems.tsx'; } from './ListItems.tsx';
import { Box, List, Typography } from '@mui/material'; import { Box, List, Typography } from '@mui/material';
@ -16,6 +15,7 @@ import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectO
import { useNewAdminMenu } from 'hooks/useNewAdminMenu'; import { useNewAdminMenu } from 'hooks/useNewAdminMenu';
import { AdminMenuNavigation } from '../AdminMenu/AdminNavigationItems.tsx'; import { AdminMenuNavigation } from '../AdminMenu/AdminNavigationItems.tsx';
import { useUiFlag } from 'hooks/useUiFlag.ts'; import { useUiFlag } from 'hooks/useUiFlag.ts';
import { ConfigurationAccordion } from './ConfigurationAccordion.tsx';
export const OtherLinksList = () => { export const OtherLinksList = () => {
const { uiConfig } = useUiConfig(); const { uiConfig } = useUiConfig();
@ -36,105 +36,92 @@ export const OtherLinksList = () => {
); );
}; };
/**
* @deprecated remove with `sideMenuCleanup` flag
*/
export const RecentProjectsList: FC<{ export const RecentProjectsList: FC<{
projectId: string; projectId: string;
projectName: string; projectName: string;
mode: NavigationMode; mode: NavigationMode;
onClick: () => void; onClick: () => void;
}> = ({ projectId, projectName, mode, onClick }) => { }> = ({ projectId, projectName, mode, onClick }) => (
const DynamicListItem = mode === 'mini' ? MiniListItem : FullListItem;
return (
<List> <List>
<DynamicListItem <MenuListItem
href={`/projects/${projectId}`} href={`/projects/${projectId}`}
text={projectName} text={projectName}
onClick={onClick} onClick={onClick}
selected={false} selected={false}
> mode={mode}
<ProjectIcon /> icon={<ProjectIcon />}
</DynamicListItem> />
</List> </List>
); );
};
/**
* @deprecated remove with `sideMenuCleanup` flag
*/
export const RecentFlagsList: FC<{ export const RecentFlagsList: FC<{
flags: { featureId: string; projectId: string }[]; flags: { featureId: string; projectId: string }[];
mode: NavigationMode; mode: NavigationMode;
onClick: () => void; onClick: () => void;
}> = ({ flags, mode, onClick }) => { }> = ({ flags, mode, onClick }) => (
const DynamicListItem = mode === 'mini' ? MiniListItem : FullListItem;
return (
<List> <List>
{flags.map((flag) => ( {flags.map((flag) => (
<DynamicListItem <MenuListItem
href={`/projects/${flag.projectId}/features/${flag.featureId}`} href={`/projects/${flag.projectId}/features/${flag.featureId}`}
text={flag.featureId} text={flag.featureId}
onClick={onClick} onClick={onClick}
selected={false} selected={false}
key={flag.featureId} key={flag.featureId}
> mode={mode}
<FlagIcon /> icon={<FlagIcon />}
</DynamicListItem> />
))} ))}
</List> </List>
); );
};
export const PrimaryNavigationList: FC<{ export const PrimaryNavigationList: FC<{
mode: NavigationMode; mode: NavigationMode;
setMode: (mode: NavigationMode) => void;
onClick: (activeItem: string) => void; onClick: (activeItem: string) => void;
activeItem?: string; activeItem?: string;
}> = ({ mode, onClick, activeItem }) => { }> = ({ mode, setMode, onClick, activeItem }) => {
const DynamicListItem = mode === 'mini' ? MiniListItem : FullListItem; const PrimaryListItem = ({
href,
text,
}: Pick<ComponentProps<typeof MenuListItem>, 'href' | 'text'>) => (
<MenuListItem
href={href}
text={text}
icon={<IconRenderer path={href} />}
onClick={() => onClick(href)}
selected={activeItem === href}
mode={mode}
/>
);
const { isOss } = useUiConfig(); const { isOss } = useUiConfig();
const sideMenuCleanup = useUiFlag('sideMenuCleanup'); const sideMenuCleanup = useUiFlag('sideMenuCleanup');
return ( return (
<List> <List>
<DynamicListItem <PrimaryListItem href='/personal' text='Dashboard' />
href='/personal' <PrimaryListItem href='/projects' text='Projects' />
text='Dashboard' <PrimaryListItem href='/search' text='Flags overview' />
onClick={() => onClick('/personal')} <PrimaryListItem href='/playground' text='Playground' />
selected={activeItem === '/personal'}
>
<IconRenderer path='/personal' />
</DynamicListItem>
<DynamicListItem
href='/projects'
text='Projects'
onClick={() => onClick('/projects')}
selected={activeItem === '/projects'}
>
<IconRenderer path='/projects' />
</DynamicListItem>
<DynamicListItem
href='/search'
text='Flags overview'
onClick={() => onClick('/search')}
selected={activeItem === '/search'}
>
<IconRenderer path='/search' />
</DynamicListItem>
<DynamicListItem
href='/playground'
text='Playground'
onClick={() => onClick('/playground')}
selected={activeItem === '/playground'}
>
<IconRenderer path='/playground' />
</DynamicListItem>
{!isOss() ? ( {!isOss() ? (
<DynamicListItem <PrimaryListItem
href='/insights' href='/insights'
text={sideMenuCleanup ? 'Analytics' : 'Insights'} text={sideMenuCleanup ? 'Analytics' : 'Insights'}
onClick={() => onClick('/insights')} />
selected={activeItem === '/insights'} ) : null}
> {sideMenuCleanup ? (
<IconRenderer path='/insights' /> <ConfigurationAccordion
</DynamicListItem> mode={mode}
setMode={setMode}
activeItem={activeItem}
onClick={() => onClick('configure')}
/>
) : null} ) : null}
</List> </List>
); );
@ -173,22 +160,19 @@ export const AdminSettingsNavigation: FC<{
export const AdminSettingsLink: FC<{ export const AdminSettingsLink: FC<{
mode: NavigationMode; mode: NavigationMode;
onClick: (activeItem: string) => void; onClick: (activeItem: string) => void;
}> = ({ mode, onClick }) => { }> = ({ mode, onClick }) => (
const DynamicListItem = mode === 'mini' ? MiniListItem : FullListItem;
return (
<Box> <Box>
<List> <List>
<DynamicListItem <MenuListItem
href='/admin' href='/admin'
text='Admin settings' text='Admin settings'
onClick={() => onClick('/admin')} onClick={() => onClick('/admin')}
> mode={mode}
<IconRenderer path='/admin' /> icon={<IconRenderer path='/admin' />}
</DynamicListItem> />
</List> </List>
</Box> </Box>
); );
};
export const RecentProjectsNavigation: FC<{ export const RecentProjectsNavigation: FC<{
mode: NavigationMode; mode: NavigationMode;

View File

@ -10,9 +10,8 @@ import {
RecentProjectsNavigation, RecentProjectsNavigation,
AdminSettingsNavigation, AdminSettingsNavigation,
} from './NavigationList.tsx'; } from './NavigationList.tsx';
import { SecondaryNavigationList } from './SecondaryNavigationList.tsx'; import { ConfigurationNavigationList } from './ConfigurationNavigationList.tsx';
import { SecondaryNavigation } from './SecondaryNavigation.tsx'; import { ConfigurationNavigation } from './ConfigurationNavigation.tsx';
import { FullListItem, MiniListItem } from './ListItems.tsx';
import { useInitialPathname } from './useInitialPathname.ts'; import { useInitialPathname } from './useInitialPathname.ts';
import { useLastViewedProject } from 'hooks/useLastViewedProject'; import { useLastViewedProject } from 'hooks/useLastViewedProject';
import { useLastViewedFlags } from 'hooks/useLastViewedFlags'; import { useLastViewedFlags } from 'hooks/useLastViewedFlags';
@ -105,7 +104,6 @@ export const NavigationSidebar: FC<{ NewInUnleash?: typeof NewInUnleash }> = ({
const { lastViewed: lastViewedFlags } = useLastViewedFlags(); const { lastViewed: lastViewedFlags } = useLastViewedFlags();
const showRecentFlags = const showRecentFlags =
!sideMenuCleanup && mode === 'full' && lastViewedFlags.length > 0; !sideMenuCleanup && mode === 'full' && lastViewedFlags.length > 0;
const DynamicListItem = mode === 'mini' ? MiniListItem : FullListItem;
useEffect(() => { useEffect(() => {
setActiveItem(initialPathname); setActiveItem(initialPathname);
@ -155,10 +153,12 @@ export const NavigationSidebar: FC<{ NewInUnleash?: typeof NewInUnleash }> = ({
<> <>
<PrimaryNavigationList <PrimaryNavigationList
mode={mode} mode={mode}
setMode={setMode}
onClick={setActiveItem} onClick={setActiveItem}
activeItem={activeItem} activeItem={activeItem}
/> />
<SecondaryNavigation {!sideMenuCleanup ? (
<ConfigurationNavigation
expanded={expanded.includes('configure')} expanded={expanded.includes('configure')}
onExpandChange={(expand) => { onExpandChange={(expand) => {
changeExpanded('configure', expand); changeExpanded('configure', expand);
@ -166,13 +166,14 @@ export const NavigationSidebar: FC<{ NewInUnleash?: typeof NewInUnleash }> = ({
mode={mode} mode={mode}
title='Configure' title='Configure'
> >
<SecondaryNavigationList <ConfigurationNavigationList
routes={routes.mainNavRoutes} routes={routes.mainNavRoutes}
mode={mode} mode={mode}
onClick={setActiveItem} onClick={setActiveItem}
activeItem={activeItem} activeItem={activeItem}
/> />
</SecondaryNavigation> </ConfigurationNavigation>
) : null}
<AdminSettingsNavigation <AdminSettingsNavigation
onClick={setActiveItem} onClick={setActiveItem}