Chore: Allow MenuItems to have `role=menuitem` when URL is set (#86886)

Allow passing a role into a MenuItem component, and fallback to default behaviour if not passed
pull/87448/head
Tom Ratcliffe 1 year ago committed by GitHub
parent c6975e06d2
commit a597300027
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      packages/grafana-ui/src/components/Menu/MenuItem.test.tsx
  2. 19
      packages/grafana-ui/src/components/Menu/MenuItem.tsx

@ -78,4 +78,14 @@ describe('MenuItem', () => {
expect(await screen.findByTestId(selectors.components.Menu.SubMenu.container)).toBeInTheDocument(); expect(await screen.findByTestId(selectors.components.Menu.SubMenu.container)).toBeInTheDocument();
}); });
it('renders with role="link" when URL is passed', async () => {
render(<MenuItem label="URL Item" url="/some-url" />);
expect(screen.getByRole('link', { name: 'URL Item' })).toBeInTheDocument();
});
it('renders with expected role when URL and role are passed', async () => {
render(<MenuItem label="URL Item" url="/some-url" role="menuitem" />);
expect(screen.getByRole('menuitem', { name: 'URL Item' })).toBeInTheDocument();
});
}); });

@ -1,5 +1,13 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { ReactElement, useCallback, useState, useRef, useImperativeHandle, CSSProperties } from 'react'; import React, {
ReactElement,
useCallback,
useState,
useRef,
useImperativeHandle,
CSSProperties,
AriaRole,
} from 'react';
import { GrafanaTheme2, LinkTarget } from '@grafana/data'; import { GrafanaTheme2, LinkTarget } from '@grafana/data';
@ -29,7 +37,7 @@ export interface MenuItemProps<T = unknown> {
/** Icon of the menu item */ /** Icon of the menu item */
icon?: IconName; icon?: IconName;
/** Role of the menu item */ /** Role of the menu item */
role?: string; role?: AriaRole;
/** Url of the menu item */ /** Url of the menu item */
url?: string; url?: string;
/** Handler for the click behaviour */ /** Handler for the click behaviour */
@ -70,7 +78,7 @@ export const MenuItem = React.memo(
disabled, disabled,
destructive, destructive,
childItems, childItems,
role = 'menuitem', role,
tabIndex = -1, tabIndex = -1,
customSubMenuContainerStyles, customSubMenuContainerStyles,
shortcut, shortcut,
@ -153,7 +161,10 @@ export const MenuItem = React.memo(
onMouseEnter={onMouseEnter} onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}
onKeyDown={handleKeys} onKeyDown={handleKeys}
role={url === undefined ? role : undefined} // If there's no URL, then set either the role from the props, or fallback to menuitem
// If there IS a URL, then use the role from props - which will result in this either being a
// link (default role of an anchor), or whatever the user of this component specified
role={!url ? role || 'menuitem' : role}
data-role="menuitem" // used to identify menuitem in Menu.tsx data-role="menuitem" // used to identify menuitem in Menu.tsx
ref={localRef} ref={localRef}
data-testid={testId} data-testid={testId}

Loading…
Cancel
Save