Skip to content

Commit de201ff

Browse files
committed
feat: supprt listbox role for language selection menu
1 parent d4b7672 commit de201ff

File tree

3 files changed

+76
-19
lines changed

3 files changed

+76
-19
lines changed

client/components/Menubar/MenubarItem.jsx

+17-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import React, { useContext, useMemo } from 'react';
33
import ButtonOrLink from '../../common/ButtonOrLink';
44
import { MenubarContext, ParentMenuContext } from './contexts';
55

6-
function MenubarItem({ hideIf, className, ...rest }) {
6+
function MenubarItem({
7+
hideIf,
8+
className,
9+
role: customRole,
10+
selected,
11+
...rest
12+
}) {
713
const parent = useContext(ParentMenuContext);
814

915
const { createMenuItemHandlers } = useContext(MenubarContext);
@@ -17,9 +23,12 @@ function MenubarItem({ hideIf, className, ...rest }) {
1723
return null;
1824
}
1925

26+
const role = customRole || 'menuitem';
27+
const ariaSelected = role === 'option' ? { 'aria-selected': selected } : {};
28+
2029
return (
2130
<li className={className}>
22-
<ButtonOrLink {...rest} {...handlers} role="menuitem" />
31+
<ButtonOrLink {...rest} {...handlers} {...ariaSelected} role={role} />
2332
</li>
2433
);
2534
}
@@ -32,14 +41,18 @@ MenubarItem.propTypes = {
3241
* Provides a way to deal with optional items.
3342
*/
3443
hideIf: PropTypes.bool,
35-
className: PropTypes.string
44+
className: PropTypes.string,
45+
role: PropTypes.oneOf(['menuitem', 'option']),
46+
selected: PropTypes.bool
3647
};
3748

3849
MenubarItem.defaultProps = {
3950
onClick: null,
4051
value: null,
4152
hideIf: false,
42-
className: 'nav__dropdown-item'
53+
className: 'nav__dropdown-item',
54+
role: 'menuitem',
55+
selected: false
4356
};
4457

4558
export default MenubarItem;

client/components/Menubar/MenubarSubmenu.jsx

+46-13
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ export function useMenuProps(id) {
2525
* MenubarTrigger
2626
* -----------------------------------------------------------------------------------------------*/
2727

28-
function MenubarTrigger({ id, title, ...props }) {
28+
function MenubarTrigger({ id, title, role, hasPopup, ...props }) {
2929
const { isOpen, handlers } = useMenuProps(id);
3030

3131
return (
3232
<button
3333
{...handlers}
3434
{...props}
35-
role="menuitem"
36-
aria-haspopup="menu"
35+
role={role}
36+
aria-haspopup={hasPopup}
3737
aria-expanded={isOpen}
3838
>
3939
<span className="nav__item-header">{title}</span>
@@ -48,16 +48,23 @@ function MenubarTrigger({ id, title, ...props }) {
4848

4949
MenubarTrigger.propTypes = {
5050
id: PropTypes.string.isRequired,
51-
title: PropTypes.node.isRequired
51+
title: PropTypes.node.isRequired,
52+
role: PropTypes.string,
53+
hasPopup: PropTypes.oneOf(['menu', 'listbox', 'true'])
54+
};
55+
56+
MenubarTrigger.defaultProps = {
57+
role: 'menuitem',
58+
hasPopup: 'menu'
5259
};
5360

5461
/* -------------------------------------------------------------------------------------------------
5562
* MenubarList
5663
* -----------------------------------------------------------------------------------------------*/
5764

58-
function MenubarList({ id, children }) {
65+
function MenubarList({ id, children, role, ...props }) {
5966
return (
60-
<ul className="nav__dropdown" role="menu">
67+
<ul className="nav__dropdown" role={role} {...props}>
6168
<ParentMenuContext.Provider value={id}>
6269
{children}
6370
</ParentMenuContext.Provider>
@@ -67,36 +74,62 @@ function MenubarList({ id, children }) {
6774

6875
MenubarList.propTypes = {
6976
id: PropTypes.string.isRequired,
70-
children: PropTypes.node
77+
children: PropTypes.node,
78+
role: PropTypes.oneOf(['menu', 'listbox'])
7179
};
7280

7381
MenubarList.defaultProps = {
74-
children: null
82+
children: null,
83+
role: 'menu'
7584
};
7685

7786
/* -------------------------------------------------------------------------------------------------
7887
* MenubarSubmenu
7988
* -----------------------------------------------------------------------------------------------*/
8089

81-
function MenubarSubmenu({ id, title, children }) {
90+
function MenubarSubmenu({
91+
id,
92+
title,
93+
children,
94+
triggerRole: customTriggerRole,
95+
listRole: customListRole,
96+
...props
97+
}) {
8298
const { isOpen } = useMenuProps(id);
8399

100+
const triggerRole = customTriggerRole || 'menuitem';
101+
const listRole = customListRole || 'menu';
102+
103+
const hasPopup = listRole === 'listbox' ? 'listbox' : 'menu';
104+
84105
return (
85106
<li className={classNames('nav__item', isOpen && 'nav__item--open')}>
86-
<MenubarTrigger id={id} title={title} />
87-
<MenubarList id={id}>{children}</MenubarList>
107+
<MenubarTrigger
108+
id={id}
109+
title={title}
110+
role={triggerRole}
111+
hasPopup={hasPopup}
112+
{...props}
113+
/>
114+
<MenubarList id={id} role={listRole}>
115+
{children}
116+
</MenubarList>
88117
</li>
89118
);
90119
}
91120

92121
MenubarSubmenu.propTypes = {
93122
id: PropTypes.string.isRequired,
94123
title: PropTypes.node.isRequired,
95-
children: PropTypes.node
124+
children: PropTypes.node,
125+
triggerRole: PropTypes.string,
126+
listRole: PropTypes.string
96127
};
97128

98129
MenubarSubmenu.defaultProps = {
99-
children: null
130+
children: null,
131+
triggerRole: 'menuitem',
132+
listRole: 'menu'
100133
};
101134

102135
export default MenubarSubmenu;

client/modules/IDE/components/Header/Nav.jsx

+13-2
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,21 @@ const LanguageMenu = () => {
266266
}
267267

268268
return (
269-
<MenubarSubmenu id="lang" title={languageKeyToLabel(language)}>
269+
<MenubarSubmenu
270+
id="lang"
271+
title={languageKeyToLabel(language)}
272+
triggerRole="button"
273+
listRole="listbox"
274+
>
270275
{sortBy(availableLanguages).map((key) => (
271276
// eslint-disable-next-line react/jsx-no-bind
272-
<MenubarItem key={key} value={key} onClick={handleLangSelection}>
277+
<MenubarItem
278+
key={key}
279+
value={key}
280+
onClick={handleLangSelection}
281+
role="option"
282+
selected={key === language}
283+
>
273284
{languageKeyToLabel(key)}
274285
</MenubarItem>
275286
))}

0 commit comments

Comments
 (0)