Skip to content

Commit 97af685

Browse files
authored
MenuButton Narrator A11y Bug Fix (#3920)
* expand collapse * Change files * fix prettier * update snapshot
1 parent 622840d commit 97af685

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "expand collapse",
4+
"packageName": "@fluentui-react-native/experimental-menu-button",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/experimental/MenuButton/src/MenuButton.tsx

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/** @jsxRuntime classic */
22
/** @jsx withSlots */
3-
import React, { useRef, useState, useCallback } from 'react';
3+
import React, { useRef, useState, useCallback, useMemo } from 'react';
4+
import { Platform } from 'react-native';
45

56
import { ButtonV1 as Button } from '@fluentui-react-native/button';
67
import type { UseSlots } from '@fluentui-react-native/framework';
@@ -37,6 +38,38 @@ export const MenuButton = compose<MenuButtonType>({
3738
setShowContextualMenu(!showContextualMenu);
3839
}, [showContextualMenu, setShowContextualMenu]);
3940

41+
// Default accessibility actions to help screen readers announce expanded/collapsed state
42+
// Only provide on win32 to follow platform-specific accessibility patterns
43+
const defaultAccessibilityActions = useMemo(() => {
44+
if (Platform.OS === ('win32' as any)) {
45+
return [
46+
{ name: 'Expand', label: 'Expand menu' },
47+
{ name: 'Collapse', label: 'Collapse menu' },
48+
];
49+
}
50+
return [];
51+
}, []);
52+
53+
const onAccessibilityAction = useCallback(
54+
(event) => {
55+
if (Platform.OS === ('win32' as any)) {
56+
switch (event.nativeEvent.actionName) {
57+
case 'Expand':
58+
if (!showContextualMenu) {
59+
setShowContextualMenu(true);
60+
}
61+
break;
62+
case 'Collapse':
63+
if (showContextualMenu) {
64+
setShowContextualMenu(false);
65+
}
66+
break;
67+
}
68+
}
69+
},
70+
[showContextualMenu],
71+
);
72+
4073
const buttonProps = {
4174
disabled,
4275
appearance,
@@ -45,6 +78,9 @@ export const MenuButton = compose<MenuButtonType>({
4578
componentRef: stdBtnRef,
4679
onClick: toggleShowContextualMenu,
4780
iconOnly: content ? false : true,
81+
accessibilityState: { expanded: showContextualMenu },
82+
accessibilityActions: defaultAccessibilityActions,
83+
onAccessibilityAction,
4884
...rest,
4985
};
5086

packages/experimental/MenuButton/src/__tests__/__snapshots__/MenuButton.test.tsx.snap

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,26 @@
22

33
exports[`ContextualMenu default 1`] = `
44
<View
5+
accessibilityActions={
6+
[
7+
{
8+
"label": "Expand menu",
9+
"name": "Expand",
10+
},
11+
{
12+
"label": "Collapse menu",
13+
"name": "Collapse",
14+
},
15+
]
16+
}
517
accessibilityLabel="Press for Nested MenuButton"
618
accessibilityRole="button"
719
accessibilityState={
820
{
921
"busy": undefined,
1022
"checked": undefined,
1123
"disabled": false,
12-
"expanded": undefined,
24+
"expanded": false,
1325
"multiselectable": undefined,
1426
"required": undefined,
1527
"selected": undefined,
@@ -36,6 +48,7 @@ exports[`ContextualMenu default 1`] = `
3648
},
3749
]
3850
}
51+
onAccessibilityAction={[Function]}
3952
onAccessibilityTap={[Function]}
4053
onBlur={[Function]}
4154
onClick={[Function]}

0 commit comments

Comments
 (0)