Skip to content

Commit a047adb

Browse files
committed
Enhance ReactionButton accessibility by focusing the first emoji button on callout positioning
1 parent 24ff570 commit a047adb

1 file changed

Lines changed: 10 additions & 1 deletion

File tree

packages/react-components/src/components/ReactionButton.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
TooltipHost,
1414
useTheme
1515
} from '@fluentui/react';
16-
import React, { useRef, useState } from 'react';
16+
import React, { useRef, useState, useCallback } from 'react';
1717
import { ControlBarButton, ControlBarButtonProps } from './ControlBarButton';
1818
import { _HighContrastAwareIcon } from './HighContrastAwareIcon';
1919
import { useLocale } from '../localization';
@@ -121,9 +121,15 @@ export const ReactionButton = (props: ReactionButtonProps): JSX.Element => {
121121

122122
const reactionButtonCalloutRef = useRef<HTMLDivElement>(null);
123123
const reactionButtonRef = useRef<IButton>(null);
124+
const firstEmojiButtonRef = useRef<IButton>(null);
124125

125126
const [calloutIsVisible, setCalloutIsVisible] = useState(false);
126127

128+
// Focus the first emoji button when callout finishes positioning
129+
const handleCalloutPositioned = useCallback(() => {
130+
firstEmojiButtonRef.current?.focus();
131+
}, []);
132+
127133
return (
128134
<Stack>
129135
{calloutIsVisible && (
@@ -132,13 +138,15 @@ export const ReactionButton = (props: ReactionButtonProps): JSX.Element => {
132138
isBeakVisible={false}
133139
styles={reactionButtonCalloutStyles}
134140
target={reactionButtonCalloutRef.current}
141+
onPositioned={handleCalloutPositioned}
135142
onDismiss={() => {
136143
reactionButtonRef.current?.focus();
137144
setCalloutIsVisible(false);
138145
}}
139146
>
140147
<FocusTrapZone
141148
isClickableOutsideFocusTrap={true}
149+
disableFirstFocus={true}
142150
// Allowing escape key to close the callout and return focus to the main reaction button. Tooltips also use
143151
// escape key to close themselves, so we need to use onKeyDownCapture to ensure the callout closes first.
144152
onKeyDownCapture={(e) => {
@@ -169,6 +177,7 @@ export const ReactionButton = (props: ReactionButtonProps): JSX.Element => {
169177
>
170178
<DefaultButton
171179
key={index}
180+
componentRef={index === 0 ? firstEmojiButtonRef : undefined}
172181
onClick={() => {
173182
props.onReactionClick(emoji);
174183
reactionButtonRef.current?.focus();

0 commit comments

Comments
 (0)