[BugFix A11y] video tile a11y updates (#5345)
* add new strings to better announce the state of the participant * Change files * remove console * update string concatenation * update logic per comment
This commit is contained in:
Родитель
365fcfdb0f
Коммит
734c9053e2
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type": "minor",
|
||||
"area": "fix",
|
||||
"workstream": "A11y",
|
||||
"comment": "add new strings to better announce the state of the participant",
|
||||
"packageName": "@azure/communication-react",
|
||||
"email": "94866715+dmceachernmsft@users.noreply.github.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type": "minor",
|
||||
"area": "fix",
|
||||
"workstream": "A11y",
|
||||
"comment": "add new strings to better announce the state of the participant",
|
||||
"packageName": "@azure/communication-react",
|
||||
"email": "94866715+dmceachernmsft@users.noreply.github.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -5301,6 +5301,10 @@ export interface VideoTilesOptions {
|
|||
// @public
|
||||
export interface VideoTileStrings {
|
||||
moreOptionsButtonAriaLabel: string;
|
||||
moreOptionsParticipantHandRaisedAriaLabel: string;
|
||||
moreOptionsParticipantIsSpeakingAriaLabel: string;
|
||||
moreOptionsParticipantMutedStateMutedAriaLabel: string;
|
||||
moreOptionsParticipantMutedStateUnmutedAriaLabel: string;
|
||||
participantStateHold: string;
|
||||
participantStateRinging: string;
|
||||
}
|
||||
|
|
|
@ -4618,6 +4618,10 @@ export interface VideoTilesOptions {
|
|||
// @public
|
||||
export interface VideoTileStrings {
|
||||
moreOptionsButtonAriaLabel: string;
|
||||
moreOptionsParticipantHandRaisedAriaLabel: string;
|
||||
moreOptionsParticipantIsSpeakingAriaLabel: string;
|
||||
moreOptionsParticipantMutedStateMutedAriaLabel: string;
|
||||
moreOptionsParticipantMutedStateUnmutedAriaLabel: string;
|
||||
participantStateHold: string;
|
||||
participantStateRinging: string;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import useLongPress from './utils/useLongPress';
|
|||
import { moreButtonStyles } from './styles/VideoTile.styles';
|
||||
import { raiseHandContainerStyles } from './styles/VideoTile.styles';
|
||||
import { ReactionResources } from '../types/ReactionTypes';
|
||||
import { formatMoreButtonAriaDescription } from './utils';
|
||||
|
||||
/**
|
||||
* Strings of {@link VideoTile} that can be overridden.
|
||||
|
@ -49,6 +50,14 @@ export interface VideoTileStrings {
|
|||
participantStateRinging: string;
|
||||
/** String for displaying the Hold state of the remote participant */
|
||||
participantStateHold: string;
|
||||
/** String for the announcement of the muted state of the participant when muted */
|
||||
moreOptionsParticipantMutedStateMutedAriaLabel: string;
|
||||
/** String for the announcement of the unmuted state of the participant when unmuted */
|
||||
moreOptionsParticipantMutedStateUnmutedAriaLabel: string;
|
||||
/** String for the announcement of the participant has their hand raised */
|
||||
moreOptionsParticipantHandRaisedAriaLabel: string;
|
||||
/** String for the announcement of whether the participant is speaking or not */
|
||||
moreOptionsParticipantIsSpeakingAriaLabel: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,23 +222,56 @@ const videoTileMoreMenuProps = {
|
|||
};
|
||||
const VideoTileMoreOptionsButton = (props: {
|
||||
contextualMenu?: IContextualMenuProps;
|
||||
participantDisplayName: string | undefined;
|
||||
participantState: string | undefined;
|
||||
participantHandRaised: boolean;
|
||||
participantIsSpeaking: boolean | undefined;
|
||||
participantIsMuted: boolean | undefined;
|
||||
canShowContextMenuButton: boolean;
|
||||
}): JSX.Element => {
|
||||
const locale = useLocale();
|
||||
const locale = useLocale().strings.videoTile;
|
||||
const theme = useTheme();
|
||||
const strings = { ...locale.strings.videoTile };
|
||||
|
||||
const { contextualMenu, canShowContextMenuButton } = props;
|
||||
const {
|
||||
contextualMenu,
|
||||
canShowContextMenuButton,
|
||||
participantDisplayName,
|
||||
participantHandRaised,
|
||||
participantIsSpeaking,
|
||||
participantState,
|
||||
participantIsMuted
|
||||
} = props;
|
||||
const [moreButtonAiraDescription, setMoreButtonAriaDescription] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
setMoreButtonAriaDescription(
|
||||
formatMoreButtonAriaDescription(
|
||||
participantDisplayName,
|
||||
participantIsMuted,
|
||||
participantHandRaised,
|
||||
participantState,
|
||||
participantIsSpeaking,
|
||||
locale
|
||||
)
|
||||
);
|
||||
}, [
|
||||
participantDisplayName,
|
||||
participantHandRaised,
|
||||
participantIsMuted,
|
||||
participantIsSpeaking,
|
||||
participantState,
|
||||
locale
|
||||
]);
|
||||
|
||||
if (!contextualMenu) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const optionsIcon = canShowContextMenuButton ? 'VideoTileMoreOptions' : undefined;
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
data-ui-id="video-tile-more-options-button"
|
||||
ariaLabel={strings?.moreOptionsButtonAriaLabel}
|
||||
ariaLabel={moreButtonAiraDescription}
|
||||
styles={moreButtonStyles(theme)}
|
||||
menuIconProps={videoTileMoreMenuIconProps}
|
||||
menuProps={{ ...videoTileMoreMenuProps, ...contextualMenu }}
|
||||
|
@ -468,6 +510,11 @@ export const VideoTile = (props: VideoTileProps): JSX.Element => {
|
|||
)}
|
||||
<VideoTileMoreOptionsButton
|
||||
contextualMenu={contextualMenu}
|
||||
participantDisplayName={displayName}
|
||||
participantHandRaised={!!raisedHand}
|
||||
participantIsMuted={isMuted}
|
||||
participantState={participantStateString}
|
||||
participantIsSpeaking={isSpeaking}
|
||||
canShowContextMenuButton={canShowContextMenuButton}
|
||||
/>
|
||||
</Stack>
|
||||
|
|
|
@ -5,6 +5,8 @@ import { IIconProps, MessageBarType } from '@fluentui/react';
|
|||
import { ActiveErrorMessage, ErrorType } from './ErrorBar';
|
||||
import { _SupportedSpokenLanguage } from '../types';
|
||||
import { ActiveNotification, NotificationType } from './NotificationStack';
|
||||
import { VideoTileStrings } from './VideoTile';
|
||||
import { _formatString } from '@internal/acs-ui-common';
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
@ -409,3 +411,33 @@ export const isEnterKeyEventFromCompositionSession = (e: KeyboardEvent): boolean
|
|||
* @private
|
||||
*/
|
||||
export const nullToUndefined = <T>(value: T | null): T | undefined => (value === null ? undefined : value);
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export const formatMoreButtonAriaDescription = (
|
||||
displayName?: string,
|
||||
isMuted?: boolean,
|
||||
isHandRaised?: boolean,
|
||||
state?: string,
|
||||
isSpeaking?: boolean,
|
||||
strings?: VideoTileStrings
|
||||
): string => {
|
||||
const mutedState = isMuted
|
||||
? strings?.moreOptionsParticipantMutedStateMutedAriaLabel
|
||||
: strings?.moreOptionsParticipantMutedStateUnmutedAriaLabel;
|
||||
const handRaisedState = isHandRaised ? strings?.moreOptionsParticipantHandRaisedAriaLabel : undefined;
|
||||
const isSpeakingState = isSpeaking ? strings?.moreOptionsParticipantIsSpeakingAriaLabel : undefined;
|
||||
|
||||
const description = strings?.moreOptionsButtonAriaLabel
|
||||
? _formatString(strings?.moreOptionsButtonAriaLabel, {
|
||||
displayName: displayName ?? ' ',
|
||||
isMuted: mutedState ?? ' ',
|
||||
isHandRaised: handRaisedState ?? ' ',
|
||||
state: state ?? ' ',
|
||||
isSpeaking: isSpeakingState ?? ' '
|
||||
})
|
||||
: '';
|
||||
|
||||
return description;
|
||||
};
|
||||
|
|
|
@ -525,7 +525,11 @@
|
|||
"videoTile": {
|
||||
"participantStateRinging": "Calling...",
|
||||
"participantStateHold": "On hold",
|
||||
"moreOptionsButtonAriaLabel": "More Options"
|
||||
"moreOptionsButtonAriaLabel": "More Options {displayName} {isMuted} {isHandRaised} {state} {isSpeaking}",
|
||||
"moreOptionsParticipantMutedStateMutedAriaLabel": "muted",
|
||||
"moreOptionsParticipantMutedStateUnmutedAriaLabel": "unmuted",
|
||||
"moreOptionsParticipantHandRaisedAriaLabel": "Hand raised",
|
||||
"moreOptionsParticipantIsSpeakingAriaLabel": "Speaking"
|
||||
},
|
||||
"CameraAndMicrophoneSitePermissionsRequest": {
|
||||
"primaryText": "Allow {appName} to use your camera and microphone",
|
||||
|
|
Загрузка…
Ссылка в новой задаче