Skip to content

Commit

Permalink
Merge pull request #3764 from carbon-design-system/fix-3763
Browse files Browse the repository at this point in the history
fix(header): tooltips for header action menu
  • Loading branch information
kodiakhq[bot] committed Apr 17, 2023
2 parents 272ddc7 + 7ffcec5 commit bf9ed30
Show file tree
Hide file tree
Showing 12 changed files with 1,002 additions and 338 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { HeaderMenuItem } from 'carbon-components-react/es/components/UIShell';

import { ChildContentPropTypes } from '../HeaderPropTypes';
import { handleSpecificKeyDown } from '../../../utils/componentUtilityFunctions';
import Button from '../../Button/Button';

const { prefix } = settings;

Expand Down Expand Up @@ -111,39 +112,31 @@ class HeaderActionMenu extends React.Component {

const className = classnames(`${prefix}--header__submenu`, customClassName);

// Prevents the a element from navigating to it's href target
const handleDefaultClick = (event) => {
event.preventDefault();
event.stopPropagation();
onToggleExpansion();
};

// Notes on eslint comments and based on the examples in:
// https://www.w3.org/TR/wai-aria-practices/examples/menubar/menubar-1/menubar-1.html#
// - The focus is handled by the <a> menuitem, onMouseOver is for mouse
// users
// - aria-haspopup can definitely have the value "menu"
// - aria-expanded is on their example node with role="menuitem"
// - href can be set to javascript:void(0), ideally this will be a button

return (
// TODO: CAN WE REMOVE THIS DIV WRAPPER AND ATTACH THE CLASS DIRECTLY
<div className={className}>
<a // eslint-disable-line jsx-a11y/role-supports-aria-props,jsx-a11y/anchor-is-valid
aria-haspopup="menu" // eslint-disable-line jsx-a11y/aria-proptypes
<Button
hasIconOnly
iconDescription={ariaLabel}
tooltipPosition="bottom"
aria-haspopup="menu"
aria-expanded={isExpanded}
className={classnames(`${prefix}--header__menu-item`, `${prefix}--header__menu-title`)}
href="#"
onKeyDown={handleSpecificKeyDown(['Enter', 'Space', 'Escape'], handleDefaultClick)}
onClick={handleDefaultClick}
onClick={onToggleExpansion}
ref={focusRef}
data-testid="menuitem"
tabIndex={0}
testId="menuitem"
aria-label={ariaLabel}
role="menuitem"
>
<MenuContent ariaLabel={ariaLabel} />
</a>
</Button>
<ul {...accessibilityLabel} className={`${prefix}--header__menu`} role="menu">
{childContent.map((childItem, index) => {
const { isOverflowing } = this.state;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { settings } from '../../../constants/Settings';

import HeaderActionMenu from './HeaderActionMenu';

const { prefix } = settings;

describe('HeaderActionMenu', () => {
const mockProps = {
'aria-label': 'Accessibility label',
Expand Down Expand Up @@ -53,15 +58,14 @@ describe('HeaderActionMenu', () => {
it('should render aria-label', () => {
render(<HeaderActionMenu {...mockProps} />);

expect(screen.getByText('Accessibility label')).toBeInTheDocument();
expect(screen.getByTestId('menuitem')).toHaveAttribute('aria-label', 'Accessibility label');
});

it('should render content prop', () => {
const menuContent = () => <p>Some other text</p>;
render(<HeaderActionMenu renderMenuContent={menuContent} {...mockProps} />);

expect(screen.queryByText('Accessibility label')).not.toBeInTheDocument();
expect(screen.getByText('Some other text')).toBeInTheDocument();
expect(screen.getByTestId('menuitem')).toHaveTextContent('Some other text');
});

it("should add a title to long items that truncate if they don't have one.", () => {
Expand All @@ -78,4 +82,11 @@ describe('HeaderActionMenu', () => {

jest.clearAllMocks();
});

it('should display tooltip on hover', () => {
render(<HeaderActionMenu {...mockProps} />);
const actionMenu = screen.getByTestId('menuitem');
userEvent.hover(actionMenu);
expect(actionMenu).not.toHaveClass(`${prefix}--tooltip--hidden`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ exports[`HeaderActionMenu should render 1`] = `
<div
class="bx--header__submenu custom-class"
>
<a
<button
aria-expanded="false"
aria-haspopup="menu"
aria-label="Accessibility label"
class="bx--header__menu-item bx--header__menu-title"
class="bx--header__menu-item bx--header__menu-title iot--btn bx--btn bx--btn--primary bx--tooltip--hidden bx--btn--icon-only bx--tooltip__trigger bx--tooltip--a11y bx--btn--icon-only--bottom bx--tooltip--align-center"
data-testid="menuitem"
href="#"
role="menuitem"
tabindex="0"
type="button"
>
<div
class="bx--assistive-text"
>
Accessibility label
</div>
Accessibility label
<svg
aria-hidden="true"
Expand All @@ -31,7 +36,7 @@ exports[`HeaderActionMenu should render 1`] = `
d="M16 22L6 12 7.4 10.6 16 19.2 24.6 10.6 26 12z"
/>
</svg>
</a>
</button>
<ul
aria-label="Accessibility label"
class="bx--header__menu"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,18 +231,30 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
<div
className="bx--header__submenu bx--header-action-btn"
>
<a
<button
aria-describedby={null}
aria-expanded={false}
aria-haspopup="menu"
aria-label="user"
className="bx--header__menu-item bx--header__menu-title"
aria-pressed={null}
className="bx--header__menu-item bx--header__menu-title iot--btn bx--btn bx--btn--primary bx--tooltip--hidden bx--btn--icon-only bx--tooltip__trigger bx--tooltip--a11y bx--btn--icon-only--bottom bx--tooltip--align-center"
data-testid="menuitem"
href="#"
disabled={false}
onBlur={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
onFocus={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
role="menuitem"
tabIndex={0}
type="button"
>
<div
className="bx--assistive-text"
onMouseEnter={[Function]}
>
user
</div>
<svg
aria-hidden={true}
description="Icon"
Expand All @@ -261,7 +273,7 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
d="M8,3C6.6,3,5.5,4.1,5.5,5.5S6.6,8,8,8s2.5-1.1,2.5-2.5S9.4,3,8,3z M8,7C7.2,7,6.5,6.3,6.5,5.5S7.2,4,8,4s1.5,0.7,1.5,1.5 S8.8,7,8,7z"
/>
</svg>
</a>
</button>
<ul
aria-label="user"
className="bx--header__menu"
Expand Down Expand Up @@ -600,18 +612,30 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
<div
className="bx--header__submenu bx--header-action-btn"
>
<a
<button
aria-describedby={null}
aria-expanded={false}
aria-haspopup="menu"
aria-label="user"
className="bx--header__menu-item bx--header__menu-title"
aria-pressed={null}
className="bx--header__menu-item bx--header__menu-title iot--btn bx--btn bx--btn--primary bx--tooltip--hidden bx--btn--icon-only bx--tooltip__trigger bx--tooltip--a11y bx--btn--icon-only--bottom bx--tooltip--align-center"
data-testid="menuitem"
href="#"
disabled={false}
onBlur={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
onFocus={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
role="menuitem"
tabIndex={0}
type="button"
>
<div
className="bx--assistive-text"
onMouseEnter={[Function]}
>
user
</div>
<svg
aria-hidden={true}
description="Icon"
Expand All @@ -630,7 +654,7 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
d="M8,3C6.6,3,5.5,4.1,5.5,5.5S6.6,8,8,8s2.5-1.1,2.5-2.5S9.4,3,8,3z M8,7C7.2,7,6.5,6.3,6.5,5.5S7.2,4,8,4s1.5,0.7,1.5,1.5 S8.8,7,8,7z"
/>
</svg>
</a>
</button>
<ul
aria-label="user"
className="bx--header__menu"
Expand Down Expand Up @@ -787,18 +811,30 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
<div
className="bx--header__submenu bx--header-action-btn"
>
<a
<button
aria-describedby={null}
aria-expanded={false}
aria-haspopup="menu"
aria-label="user"
className="bx--header__menu-item bx--header__menu-title"
aria-pressed={null}
className="bx--header__menu-item bx--header__menu-title iot--btn bx--btn bx--btn--primary bx--tooltip--hidden bx--btn--icon-only bx--tooltip__trigger bx--tooltip--a11y bx--btn--icon-only--bottom bx--tooltip--align-center"
data-testid="menuitem"
href="#"
disabled={false}
onBlur={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
onFocus={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
role="menuitem"
tabIndex={0}
type="button"
>
<div
className="bx--assistive-text"
onMouseEnter={[Function]}
>
user
</div>
<svg
aria-hidden={true}
description="Icon"
Expand All @@ -817,7 +853,7 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
d="M8,3C6.6,3,5.5,4.1,5.5,5.5S6.6,8,8,8s2.5-1.1,2.5-2.5S9.4,3,8,3z M8,7C7.2,7,6.5,6.3,6.5,5.5S7.2,4,8,4s1.5,0.7,1.5,1.5 S8.8,7,8,7z"
/>
</svg>
</a>
</button>
<ul
aria-label="user"
className="bx--header__menu"
Expand Down Expand Up @@ -996,18 +1032,30 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
<div
className="bx--header__submenu bx--header-action-btn"
>
<a
<button
aria-describedby={null}
aria-expanded={false}
aria-haspopup="menu"
aria-label="user"
className="bx--header__menu-item bx--header__menu-title"
aria-pressed={null}
className="bx--header__menu-item bx--header__menu-title iot--btn bx--btn bx--btn--primary bx--tooltip--hidden bx--btn--icon-only bx--tooltip__trigger bx--tooltip--a11y bx--btn--icon-only--bottom bx--tooltip--align-center"
data-testid="menuitem"
href="#"
disabled={false}
onBlur={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
onFocus={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
role="menuitem"
tabIndex={0}
type="button"
>
<div
className="bx--assistive-text"
onMouseEnter={[Function]}
>
user
</div>
<svg
aria-hidden={true}
description="Icon"
Expand All @@ -1026,7 +1074,7 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
d="M8,3C6.6,3,5.5,4.1,5.5,5.5S6.6,8,8,8s2.5-1.1,2.5-2.5S9.4,3,8,3z M8,7C7.2,7,6.5,6.3,6.5,5.5S7.2,4,8,4s1.5,0.7,1.5,1.5 S8.8,7,8,7z"
/>
</svg>
</a>
</button>
<ul
aria-label="user"
className="bx--header__menu"
Expand Down Expand Up @@ -1561,18 +1609,30 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
<div
className="bx--header__submenu bx--header-action-btn"
>
<a
<button
aria-describedby={null}
aria-expanded={false}
aria-haspopup="menu"
aria-label="user"
className="bx--header__menu-item bx--header__menu-title"
aria-pressed={null}
className="bx--header__menu-item bx--header__menu-title iot--btn bx--btn bx--btn--primary bx--tooltip--hidden bx--btn--icon-only bx--tooltip__trigger bx--tooltip--a11y bx--btn--icon-only--bottom bx--tooltip--align-center"
data-testid="menuitem"
href="#"
disabled={false}
onBlur={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
onFocus={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
role="menuitem"
tabIndex={0}
type="button"
>
<div
className="bx--assistive-text"
onMouseEnter={[Function]}
>
user
</div>
<svg
aria-hidden={true}
description="Icon"
Expand All @@ -1591,7 +1651,7 @@ exports[`Storybook Snapshot tests and console checks Storyshots 1 - Watson IoT/U
d="M8,3C6.6,3,5.5,4.1,5.5,5.5S6.6,8,8,8s2.5-1.1,2.5-2.5S9.4,3,8,3z M8,7C7.2,7,6.5,6.3,6.5,5.5S7.2,4,8,4s1.5,0.7,1.5,1.5 S8.8,7,8,7z"
/>
</svg>
</a>
</button>
<ul
aria-label="user"
className="bx--header__menu"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,21 @@ exports[`Header should render 1`] = `
<div
class="bx--header__submenu bx--header-action-btn"
>
<a
<button
aria-expanded="false"
aria-haspopup="menu"
aria-label="user"
class="bx--header__menu-item bx--header__menu-title"
class="bx--header__menu-item bx--header__menu-title iot--btn bx--btn bx--btn--primary bx--tooltip--hidden bx--btn--icon-only bx--tooltip__trigger bx--tooltip--a11y bx--btn--icon-only--bottom bx--tooltip--align-center"
data-testid="menuitem"
href="#"
role="menuitem"
tabindex="0"
type="button"
>
<div
class="bx--assistive-text"
>
user
</div>
<svg
aria-hidden="true"
description="Icon"
Expand All @@ -183,7 +188,7 @@ exports[`Header should render 1`] = `
d="M16 4a5 5 0 11-5 5 5 5 0 015-5m0-2a7 7 0 107 7A7 7 0 0016 2zM26 30H24V25a5 5 0 00-5-5H13a5 5 0 00-5 5v5H6V25a7 7 0 017-7h6a7 7 0 017 7z"
/>
</svg>
</a>
</button>
<ul
aria-label="user"
class="bx--header__menu"
Expand Down

0 comments on commit bf9ed30

Please sign in to comment.