grafana/public/app/core/components/MegaMenu/NavBarMenuItemWrapper.tsx
Torkel Ödegaard 8440baab91
NavBarMenu: Section as links and design tweak (#55538)
* scaffold new component + remove storing of expanded state

* some padding fixes

* simplify!

* move browse back to being a child of dashboards

* behaviour working

* improve child matcher to look recursively

* increase NavBarMenu zIndex to ensure it overlays explore drawer

* some renaming

* fix unit test

* make dashboards a top level item again and make chevrons their own buttons

* remove active background state

* Finished tweaks

* remove theme change

* Remove exit animation

* align button centrally + fix empty message alignment

* only show the empty message if there are no children

* ensure overflowing menu items truncate correctly

Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
2022-09-21 11:57:30 +02:00

113 lines
3.1 KiB
TypeScript

import { css } from '@emotion/css';
import { useLingui } from '@lingui/react';
import React from 'react';
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
import { toIconName, useStyles2 } from '@grafana/ui';
import menuItemTranslations from '../NavBar/navBarItem-translations';
import { isMatchOrChildMatch } from '../NavBar/utils';
import { NavBarMenuItem } from './NavBarMenuItem';
import { NavBarMenuSection } from './NavBarMenuSection';
export function NavBarMenuItemWrapper({
link,
activeItem,
onClose,
}: {
link: NavModelItem;
activeItem?: NavModelItem;
onClose: () => void;
}) {
const { i18n } = useLingui();
const styles = useStyles2(getStyles);
if (link.emptyMessageId && !linkHasChildren(link)) {
const emptyMessageTranslated = i18n._(menuItemTranslations[link.emptyMessageId]);
return (
<NavBarMenuSection link={link}>
<ul className={styles.children}>
<div className={styles.emptyMessage}>{emptyMessageTranslated}</div>
</ul>
</NavBarMenuSection>
);
}
return (
<NavBarMenuSection onClose={onClose} link={link} activeItem={activeItem}>
{linkHasChildren(link) && (
<ul className={styles.children}>
{link.children.map((childLink) => {
const icon = childLink.icon ? toIconName(childLink.icon) : undefined;
return (
!childLink.divider && (
<NavBarMenuItem
key={`${link.text}-${childLink.text}`}
isActive={isMatchOrChildMatch(childLink, activeItem)}
isChild
icon={childLink.showIconInNavbar ? icon : undefined}
onClick={() => {
childLink.onClick?.();
onClose();
}}
target={childLink.target}
url={childLink.url}
>
{childLink.text}
</NavBarMenuItem>
)
);
})}
</ul>
)}
</NavBarMenuSection>
);
}
const getStyles = (theme: GrafanaTheme2) => ({
children: css({
display: 'flex',
flexDirection: 'column',
}),
flex: css({
display: 'flex',
}),
itemWithoutMenu: css({
position: 'relative',
placeItems: 'inherit',
justifyContent: 'start',
display: 'flex',
flexGrow: 1,
alignItems: 'center',
}),
fullWidth: css({
height: '100%',
width: '100%',
}),
iconContainer: css({
display: 'flex',
placeContent: 'center',
}),
itemWithoutMenuContent: css({
display: 'grid',
gridAutoFlow: 'column',
gridTemplateColumns: `${theme.spacing(7)} auto`,
alignItems: 'center',
height: '100%',
}),
linkText: css({
fontSize: theme.typography.pxToRem(14),
justifySelf: 'start',
}),
emptyMessage: css({
color: theme.colors.text.secondary,
fontStyle: 'italic',
padding: theme.spacing(1, 1.5, 1, 7),
}),
});
function linkHasChildren(link: NavModelItem): link is NavModelItem & { children: NavModelItem[] } {
return Boolean(link.children && link.children.length > 0);
}