diff --git a/packages/grafana-ui/src/components/Menu/MenuItem.test.tsx b/packages/grafana-ui/src/components/Menu/MenuItem.test.tsx index cb64a4e9603..3a7e2dc7057 100644 --- a/packages/grafana-ui/src/components/Menu/MenuItem.test.tsx +++ b/packages/grafana-ui/src/components/Menu/MenuItem.test.tsx @@ -78,4 +78,14 @@ describe('MenuItem', () => { expect(await screen.findByTestId(selectors.components.Menu.SubMenu.container)).toBeInTheDocument(); }); + + it('renders with role="link" when URL is passed', async () => { + render(); + expect(screen.getByRole('link', { name: 'URL Item' })).toBeInTheDocument(); + }); + + it('renders with expected role when URL and role are passed', async () => { + render(); + expect(screen.getByRole('menuitem', { name: 'URL Item' })).toBeInTheDocument(); + }); }); diff --git a/packages/grafana-ui/src/components/Menu/MenuItem.tsx b/packages/grafana-ui/src/components/Menu/MenuItem.tsx index b6947643064..8c0f0f1d21f 100644 --- a/packages/grafana-ui/src/components/Menu/MenuItem.tsx +++ b/packages/grafana-ui/src/components/Menu/MenuItem.tsx @@ -1,5 +1,13 @@ 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'; @@ -29,7 +37,7 @@ export interface MenuItemProps { /** Icon of the menu item */ icon?: IconName; /** Role of the menu item */ - role?: string; + role?: AriaRole; /** Url of the menu item */ url?: string; /** Handler for the click behaviour */ @@ -70,7 +78,7 @@ export const MenuItem = React.memo( disabled, destructive, childItems, - role = 'menuitem', + role, tabIndex = -1, customSubMenuContainerStyles, shortcut, @@ -153,7 +161,10 @@ export const MenuItem = React.memo( onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} 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 ref={localRef} data-testid={testId}