UNPKG

@grafana/ui

Version:
1 lines 15.9 kB
{"version":3,"file":"MenuItem.mjs","sources":["../../../../src/components/Menu/MenuItem.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { ReactElement, useCallback, useState, useRef, useImperativeHandle, CSSProperties, AriaRole } from 'react';\nimport * as React from 'react';\n\nimport { GrafanaTheme2, LinkTarget } from '@grafana/data';\nimport { t } from '@grafana/i18n';\n\nimport { useStyles2 } from '../../themes/ThemeContext';\nimport { getFocusStyles } from '../../themes/mixins';\nimport { IconName } from '../../types/icon';\nimport { Icon } from '../Icon/Icon';\nimport { Stack } from '../Layout/Stack/Stack';\n\nimport { SubMenu } from './SubMenu';\n\n/** @internal */\nexport type MenuItemElement = HTMLAnchorElement & HTMLButtonElement & HTMLDivElement;\n\n/** @internal */\nexport interface MenuItemProps<T = unknown> {\n /** Label of the menu item */\n label: string;\n /** Description of item */\n description?: string;\n /** Aria label for accessibility support */\n ariaLabel?: string;\n /** Aria checked for accessibility support */\n ariaChecked?: boolean;\n /** Target of the menu item (i.e. new window) */\n target?: LinkTarget;\n /** Icon of the menu item */\n icon?: IconName;\n /** Role of the menu item */\n role?: AriaRole;\n /** Url of the menu item */\n url?: string;\n /** Handler for the click behaviour */\n onClick?: (event: React.MouseEvent<HTMLElement>, payload?: T) => void;\n /** Custom MenuItem styles*/\n className?: string;\n /** Active */\n active?: boolean;\n /** Disabled */\n disabled?: boolean;\n /** Show in destructive style (error color) */\n destructive?: boolean;\n tabIndex?: number;\n /** List of menu items for the subMenu */\n childItems?: Array<ReactElement<MenuItemProps>>;\n /** Custom style for SubMenu */\n customSubMenuContainerStyles?: CSSProperties;\n /** Shortcut key combination */\n shortcut?: string;\n /** Test id for e2e tests and fullstory*/\n testId?: string;\n /* Optional component that will be shown together with other options. Does not get passed any props. */\n component?: React.ComponentType;\n}\n\n/** @internal */\nexport const MenuItem = React.memo(\n React.forwardRef<MenuItemElement, MenuItemProps>((props, ref) => {\n const {\n url,\n icon,\n label,\n description,\n ariaLabel,\n ariaChecked,\n target,\n onClick,\n className,\n active,\n disabled,\n destructive,\n childItems,\n role,\n tabIndex = -1,\n customSubMenuContainerStyles,\n shortcut,\n testId,\n } = props;\n const styles = useStyles2(getStyles);\n const [isActive, setIsActive] = useState(active);\n const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);\n const onMouseEnter = useCallback(() => {\n if (disabled) {\n return;\n }\n\n setIsSubMenuOpen(true);\n setIsActive(true);\n }, [disabled]);\n const onMouseLeave = useCallback(() => {\n if (disabled) {\n return;\n }\n\n setIsSubMenuOpen(false);\n setIsActive(false);\n }, [disabled]);\n\n const hasSubMenu = childItems && childItems.length > 0;\n const ItemElement = hasSubMenu ? 'div' : url === undefined ? 'button' : 'a';\n const itemStyle = cx(\n {\n [styles.item]: true,\n [styles.active]: isActive,\n [styles.disabled]: disabled,\n [styles.destructive]: destructive && !disabled,\n },\n className\n );\n\n const disabledProps = {\n [ItemElement === 'button' ? 'disabled' : 'aria-disabled']: disabled,\n ...(ItemElement === 'a' && disabled && { href: undefined, onClick: undefined }),\n ...(disabled && {\n tabIndex: -1,\n ['data-disabled']: disabled, // used to identify disabled items in Menu.tsx\n }),\n };\n\n const localRef = useRef<MenuItemElement>(null);\n useImperativeHandle(ref, () => localRef.current!);\n\n const handleKeys = (event: React.KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowRight':\n event.preventDefault();\n event.stopPropagation();\n if (hasSubMenu) {\n setIsSubMenuOpen(true);\n setIsActive(true);\n }\n break;\n default:\n break;\n }\n };\n\n const closeSubMenu = () => {\n setIsSubMenuOpen(false);\n setIsActive(false);\n localRef?.current?.focus();\n };\n\n const hasShortcut = Boolean(shortcut && shortcut.length > 0);\n\n return (\n <ItemElement\n target={target}\n className={itemStyle}\n rel={target === '_blank' ? 'noopener noreferrer' : undefined}\n href={url}\n onClick={(event) => {\n if (hasSubMenu && !isSubMenuOpen) {\n event.preventDefault();\n event.stopPropagation();\n }\n onClick?.(event);\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onKeyDown={handleKeys}\n // If there's no URL, then set either the role from the props, or fallback to menuitem\n // If there IS a URL, then use the role from props - which will result in this either being a\n // link (default role of an anchor), or whatever the user of this component specified\n role={!url ? role || 'menuitem' : role}\n data-role=\"menuitem\" // used to identify menuitem in Menu.tsx\n ref={localRef}\n data-testid={testId}\n aria-label={ariaLabel}\n aria-checked={ariaChecked}\n tabIndex={tabIndex}\n {...disabledProps}\n >\n <Stack direction=\"row\" justifyContent=\"flex-start\" alignItems=\"center\">\n {icon && <Icon name={icon} className={styles.icon} aria-hidden />}\n <span className={styles.ellipsis}>{label}</span>\n <div className={cx(styles.rightWrapper, { [styles.withShortcut]: hasShortcut })}>\n {hasShortcut && (\n <div className={styles.shortcut}>\n <Icon name=\"keyboard\" title={t('grafana-ui.menu-item.keyboard-shortcut-label', 'Keyboard shortcut')} />\n {shortcut}\n </div>\n )}\n {hasSubMenu && (\n <SubMenu\n items={childItems}\n isOpen={isSubMenuOpen}\n close={closeSubMenu}\n customStyle={customSubMenuContainerStyles}\n />\n )}\n </div>\n </Stack>\n {description && (\n <div\n className={cx(styles.description, styles.ellipsis, {\n [styles.descriptionWithIcon]: icon !== undefined,\n })}\n >\n {description}\n </div>\n )}\n {props.component ? <props.component /> : null}\n </ItemElement>\n );\n })\n);\n\nMenuItem.displayName = 'MenuItem';\n\nconst getStyles = (theme: GrafanaTheme2) => {\n return {\n item: css({\n background: 'none',\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n color: theme.colors.text.primary,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'stretch',\n justifyContent: 'center',\n padding: theme.spacing(0.5, 1.5),\n minHeight: theme.spacing(4),\n borderRadius: theme.shape.radius.default,\n margin: 0,\n border: 'none',\n width: '100%',\n position: 'relative',\n\n '&:hover, &:focus-visible': {\n background: theme.colors.action.hover,\n color: theme.colors.text.primary,\n textDecoration: 'none',\n },\n\n '&:focus-visible': getFocusStyles(theme),\n }),\n active: css({\n background: theme.colors.action.hover,\n }),\n destructive: css({\n color: theme.colors.error.text,\n\n svg: {\n color: theme.colors.error.text,\n },\n\n '&:hover, &:focus, &:focus-visible': {\n background: theme.colors.error.main,\n color: theme.colors.error.contrastText,\n\n svg: {\n color: theme.colors.error.contrastText,\n },\n },\n }),\n disabled: css({\n color: theme.colors.action.disabledText,\n label: 'menu-item-disabled',\n '&:hover, &:focus, &:focus-visible': {\n cursor: 'not-allowed',\n background: 'none',\n color: theme.colors.action.disabledText,\n },\n }),\n icon: css({\n opacity: 0.7,\n color: theme.colors.text.secondary,\n }),\n rightWrapper: css({\n display: 'flex',\n alignItems: 'center',\n marginLeft: 'auto',\n }),\n withShortcut: css({\n minWidth: theme.spacing(10.5),\n }),\n shortcut: css({\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n marginLeft: theme.spacing(2),\n color: theme.colors.text.secondary,\n opacity: 0.7,\n }),\n description: css({\n ...theme.typography.bodySmall,\n color: theme.colors.text.secondary,\n textAlign: 'start',\n }),\n descriptionWithIcon: css({\n marginLeft: theme.spacing(3),\n }),\n ellipsis: css({\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }),\n };\n};\n"],"names":[],"mappings":"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"}