Skip to content

Commit 3461cd4

Browse files
johannes-weberJohannes Webergeorgylobko
authored
chore: Change aria role in AppLayout drawer's overflow menu items to menuitem (#3402)
Co-authored-by: Johannes Weber <jowejowe@amazon.com> Co-authored-by: Georgii Lobko <47106899+georgylobko@users.noreply.github.com>
1 parent 2bc4eac commit 3461cd4

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

src/app-layout/__tests__/drawers.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,21 @@ describeEachAppLayout(({ size, theme }) => {
8282
);
8383
});
8484

85+
test('overflow menu item have aria-role set to `menuitem`', () => {
86+
const { wrapper } = renderComponent(<AppLayout drawers={manyDrawers} />);
87+
const buttonDropdown = wrapper.findDrawersOverflowTrigger();
88+
89+
buttonDropdown!.openDropdown();
90+
91+
const countItems = buttonDropdown!.findItems();
92+
const countRoleMenuItemRole = buttonDropdown!
93+
.findOpenDropdown()!
94+
.find('[role="menu"]')!
95+
.findAll('[role="menuitem"]');
96+
97+
expect(countItems.length).toBe(countRoleMenuItemRole.length);
98+
});
99+
85100
test('renders aria-labels', () => {
86101
const { wrapper } = renderComponent(<AppLayout drawers={[testDrawer]} />);
87102
expect(wrapper.findDrawerTriggerById('security')!.getElement()).toHaveAttribute(

src/app-layout/__tests__/runtime-drawers.test.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
findActiveDrawerLandmark,
1515
getActiveDrawerWidth,
1616
getGlobalDrawersTestUtils,
17+
manyDrawers,
1718
testDrawer,
1819
} from './utils';
1920

@@ -1386,5 +1387,58 @@ describe('toolbar mode only features', () => {
13861387
globalDrawersWrapper.findCloseButtonByActiveDrawerId(drawerIdWithToggle)!.click();
13871388
expect(onToggle).toHaveBeenCalledWith({ isOpen: false, initiatedByUserAction: true });
13881389
});
1390+
1391+
describe('global drawers aria role in overflow menu', () => {
1392+
const registerGlobalDrawers = (count: number) => {
1393+
for (let i = 1; i <= count; i++) {
1394+
awsuiPlugins.appLayout.registerDrawer({
1395+
...drawerDefaults,
1396+
id: `global-drawer${i}`,
1397+
type: 'global',
1398+
});
1399+
}
1400+
};
1401+
1402+
test('assigns correct ARIA roles when mixing global and regular drawers', async () => {
1403+
registerGlobalDrawers(2);
1404+
const { wrapper } = await renderComponent(<AppLayout drawers={manyDrawers} />);
1405+
const buttonDropdown = wrapper.findDrawersOverflowTrigger();
1406+
1407+
buttonDropdown!.openDropdown();
1408+
1409+
expect(buttonDropdown!.findItemById('global-drawer1')).toBeTruthy();
1410+
expect(buttonDropdown!.findItemById('global-drawer2')).toBeTruthy();
1411+
1412+
const menu = buttonDropdown!.findOpenDropdown()!.find('[role="menu"]')!;
1413+
// Global drawers should have role=menuitemcheckbox
1414+
const menuItemCheckboxesLength = menu.findAll('[role="menuitemcheckbox"]').length;
1415+
expect(menuItemCheckboxesLength).toBe(2);
1416+
1417+
// Regular drawers should have role=menuitem
1418+
const menuItemsLength = menu.findAll('[role="menuitem"]').length;
1419+
expect(menuItemsLength).toBe(manyDrawers.length - menuItemCheckboxesLength);
1420+
});
1421+
1422+
test('assigns menuitemcheckbox role to global drawers in overflow menu', async () => {
1423+
registerGlobalDrawers(3);
1424+
1425+
// In mobile view, two drawers are visible in the toolbar, the others are placed in the overflow menu
1426+
const { wrapper, globalDrawersWrapper } = await renderComponent(<AppLayout drawers={[testDrawer]} />);
1427+
const buttonDropdown = wrapper.findDrawersOverflowTrigger();
1428+
1429+
expect(globalDrawersWrapper.findDrawerById('global-drawer2')).toBeFalsy();
1430+
expect(globalDrawersWrapper.findDrawerById('global-drawer3')).toBeFalsy();
1431+
1432+
buttonDropdown!.openDropdown();
1433+
1434+
const menuItemCheckboxItemsLength = buttonDropdown!
1435+
.findOpenDropdown()!
1436+
.find('[role="menu"]')!
1437+
.findAll('[role="menuitemcheckbox"]').length;
1438+
expect(menuItemCheckboxItemsLength).toBe(2);
1439+
expect(buttonDropdown!.findItemById('global-drawer2')).toBeTruthy();
1440+
expect(buttonDropdown!.findItemById('global-drawer3')).toBeTruthy();
1441+
});
1442+
});
13891443
});
13901444
});

src/app-layout/drawer/overflow-menu.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ interface OverflowMenuProps {
2323
globalDrawersStartIndex?: number;
2424
}
2525

26-
const mapDrawerToItem = (drawer: Drawer) => ({
26+
const mapDrawerToItem = (drawer: Drawer, isTypeCheckbox: boolean) => ({
2727
id: drawer.id,
2828
text: drawer.ariaLabels.drawerName,
2929
iconName: drawer.trigger!.iconName,
3030
iconSvg: drawer.trigger!.iconSvg,
3131
badge: drawer.badge,
32-
itemType: 'checkbox' as ButtonDropdownProps.ItemType,
32+
itemType: isTypeCheckbox ? ('checkbox' as ButtonDropdownProps.ItemType) : undefined,
3333
checked: drawer.active,
3434
});
3535

@@ -40,9 +40,12 @@ export default function OverflowMenu({
4040
ariaLabel,
4141
globalDrawersStartIndex,
4242
}: OverflowMenuProps) {
43-
const itemsFlatList = drawers.map(mapDrawerToItem);
43+
const hasGlobalDrawers = globalDrawersStartIndex !== undefined;
44+
const itemsFlatList = drawers.map((item, index) =>
45+
mapDrawerToItem(item, hasGlobalDrawers && index >= globalDrawersStartIndex)
46+
);
4447
let items: ReadonlyArray<InternalItemOrGroup>;
45-
if (globalDrawersStartIndex !== undefined && globalDrawersStartIndex > 0) {
48+
if (hasGlobalDrawers) {
4649
items = [
4750
{ items: itemsFlatList.slice(0, globalDrawersStartIndex) },
4851
{ items: itemsFlatList.slice(globalDrawersStartIndex) },

0 commit comments

Comments
 (0)