You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
2.1 KiB
72 lines
2.1 KiB
import React, { ReactElement, useRef, useState } from 'react';
|
|
import { css } from '@emotion/css';
|
|
import { useTheme2 } from '@grafana/ui';
|
|
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
|
|
import { useMenuItem } from '@react-aria/menu';
|
|
import { useFocus } from '@react-aria/interactions';
|
|
import { TreeState } from '@react-stately/tree';
|
|
import { mergeProps } from '@react-aria/utils';
|
|
import { Node } from '@react-types/shared';
|
|
|
|
import { useNavBarItemMenuContext } from './context';
|
|
|
|
export interface NavBarItemMenuItemProps {
|
|
item: Node<NavModelItem>;
|
|
state: TreeState<NavModelItem>;
|
|
onNavigate: (item: NavModelItem) => void;
|
|
}
|
|
|
|
export function NavBarItemMenuItem({ item, state, onNavigate }: NavBarItemMenuItemProps): ReactElement {
|
|
const { onClose } = useNavBarItemMenuContext();
|
|
const { key, rendered } = item;
|
|
const ref = useRef<HTMLLIElement>(null);
|
|
const isDisabled = state.disabledKeys.has(key);
|
|
|
|
// style to the focused menu item
|
|
const [isFocused, setFocused] = useState(false);
|
|
const { focusProps } = useFocus({ onFocusChange: setFocused, isDisabled });
|
|
const theme = useTheme2();
|
|
const styles = getStyles(theme, isFocused);
|
|
const onAction = () => {
|
|
onNavigate(item.value);
|
|
onClose();
|
|
};
|
|
|
|
let { menuItemProps } = useMenuItem(
|
|
{
|
|
isDisabled,
|
|
'aria-label': item['aria-label'],
|
|
key,
|
|
closeOnSelect: true,
|
|
onClose,
|
|
onAction,
|
|
},
|
|
state,
|
|
ref
|
|
);
|
|
|
|
return (
|
|
<li {...mergeProps(menuItemProps, focusProps)} ref={ref} className={styles.menuItem}>
|
|
{rendered}
|
|
</li>
|
|
);
|
|
}
|
|
|
|
function getStyles(theme: GrafanaTheme2, isFocused: boolean) {
|
|
return {
|
|
menuItem: css`
|
|
background-color: ${isFocused ? theme.colors.action.hover : 'transparent'};
|
|
color: ${isFocused ? 'white' : theme.colors.text.primary};
|
|
|
|
&:focus-visible {
|
|
background-color: ${theme.colors.action.hover};
|
|
box-shadow: none;
|
|
color: ${theme.colors.text.primary};
|
|
outline: 2px solid ${theme.colors.primary.main};
|
|
// Need to add condition, header is 0, otherwise -2
|
|
outline-offset: -0px;
|
|
transition: none;
|
|
}
|
|
`,
|
|
};
|
|
}
|
|
|