Skip to content

Commit e6a83b3

Browse files
authored
[Chat] Fixed Keyboard Focus Issues Related to File Sharing (#4735)
1 parent 295428e commit e6a83b3

6 files changed

Lines changed: 62 additions & 34 deletions

File tree

packages/react-components/src/components/Attachment/AttachmentCard.tsx

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -136,20 +136,26 @@ export const _AttachmentCard = (props: _AttachmentCardProps): JSX.Element => {
136136
target: '#attachment-' + attachment.id
137137
}}
138138
>
139-
<Text className={attachmentCardStyles.title} title={attachment.name}>
140-
{attachment.name}
141-
</Text>
139+
<div className={attachmentCardStyles.fileNameLabel}>
140+
<Text className={attachmentCardStyles.title} aria-label={attachment.name}>
141+
{attachment.name}
142+
</Text>
143+
</div>
142144
</TooltipHost>
143145
</div>
144146
}
145-
action={MappedMenuItems(
146-
menuActions,
147-
{
148-
...attachment,
149-
url: attachment.url ?? ''
150-
},
151-
onActionHandlerFailed
152-
)}
147+
action={
148+
<div className={attachmentCardStyles.focusState}>
149+
{MappedMenuItems(
150+
menuActions,
151+
{
152+
...attachment,
153+
url: attachment.url ?? ''
154+
},
155+
onActionHandlerFailed
156+
)}
157+
</div>
158+
}
153159
/>
154160
</Card>
155161
{isUploadInProgress ? (

packages/react-components/src/components/Attachment/AttachmentDownloadCards.tsx

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { useMemo } from 'react';
88
import { useLocale } from '../../localization';
99
import { _AttachmentCard } from './AttachmentCard';
1010
import { _AttachmentCardGroup, _AttachmentCardGroupLayout } from './AttachmentCardGroup';
11-
/* @conditional-compile-remove(file-sharing-teams-interop) @conditional-compile-remove(file-sharing-acs) */
12-
import { getAttachmentCountLiveMessage } from '../ChatMessage/ChatMessageContent';
1311
import { _formatString } from '@internal/acs-ui-common';
1412
import { AttachmentMenuAction } from '../../types/Attachment';
1513
import { AttachmentMetadata } from '@internal/acs-ui-common';
@@ -97,18 +95,6 @@ export const _AttachmentDownloadCards = (props: _AttachmentDownloadCardsProps):
9795
[]
9896
);
9997

100-
const attachmentCardGroupDescription = useMemo(
101-
() => () => {
102-
/* @conditional-compile-remove(file-sharing-teams-interop) @conditional-compile-remove(file-sharing-acs) */
103-
return getAttachmentCountLiveMessage(
104-
attachments ?? [],
105-
props.strings?.attachmentCardGroupMessage ?? localeStrings.attachmentCardGroupMessage
106-
);
107-
return '';
108-
},
109-
[props.strings?.attachmentCardGroupMessage, localeStrings.attachmentCardGroupMessage, attachments]
110-
);
111-
11298
const hasMultipleAttachments = useMemo(() => {
11399
return (props.attachments?.length ?? 0) > 1;
114100
}, [props.attachments]);
@@ -127,10 +113,7 @@ export const _AttachmentDownloadCards = (props: _AttachmentDownloadCardsProps):
127113
)}
128114
data-ui-id="attachment-download-card-group"
129115
>
130-
<_AttachmentCardGroup
131-
ariaLabel={attachmentCardGroupDescription()}
132-
attachmentGroupLayout={_AttachmentCardGroupLayout.Grid}
133-
>
116+
<_AttachmentCardGroup attachmentGroupLayout={_AttachmentCardGroupLayout.Grid}>
134117
{attachments &&
135118
attachments.map((attachment) => (
136119
<_AttachmentCard

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ export const RichTextEditor = React.forwardRef<RichTextEditorComponentRef, RichT
317317
<div className={richTextEditorWrapperStyle(theme, !showRichTextEditorFormatting)}>
318318
{/* div that is used by Rooster JS as a parent of the editor */}
319319
<div
320+
id="richTextSendBox"
320321
ref={editorDiv}
321322
tabIndex={0}
322323
role="textbox"

packages/react-components/src/components/styles/AttachmentCard.styles.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ export const useAttachmentCardStyles = makeStyles({
4141
},
4242
title: {
4343
width: '100%'
44+
},
45+
focusState: {
46+
'& > * button:focus': {
47+
border: `black solid ${_pxToRem(1)}`
48+
}
49+
},
50+
fileNameLabel: {
51+
textOverflow: 'ellipsis',
52+
whiteSpace: 'nowrap',
53+
overflowX: 'clip'
4454
}
4555
});
4656

packages/react-composites/src/composites/ChatComposite/ChatScreen.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,30 @@ export const ChatScreen = (props: ChatScreenProps): JSX.Element => {
216216

217217
const userId = toFlatCommunicationIdentifier(adapter.getState().userId);
218218

219+
/* @conditional-compile-remove(file-sharing-acs) */
220+
const setKeyboardFocusAfterFileSelection = useCallback(() => {
221+
// look up sendbox by ID for now, we will use `useRef`
222+
// once attachment button is moved inside of send box component
223+
// see ADO workitem #3764245
224+
/* @conditional-compile-remove(rich-text-editor-composite-support) */
225+
if (props.options?.richTextEditor) {
226+
const richTextSendBox = document?.querySelector(`[id="richTextSendBox"]`) as HTMLDivElement;
227+
richTextSendBox?.focus();
228+
return;
229+
}
230+
const sendBox = document?.querySelector(`[id="sendbox"]`) as HTMLTextAreaElement;
231+
// set send box on focus after file selection per A11y requirement
232+
sendBox?.focus();
233+
}, [
234+
/* @conditional-compile-remove(rich-text-editor-composite-support) */
235+
props.options?.richTextEditor
236+
]);
237+
219238
/* @conditional-compile-remove(file-sharing-acs) */
220239
const attachmentUploadButtonOnChange = useCallback(
221240
(files: FileList | null): void => {
241+
setKeyboardFocusAfterFileSelection();
242+
222243
if (!files) {
223244
return;
224245
}
@@ -254,7 +275,7 @@ export const ChatScreen = (props: ChatScreenProps): JSX.Element => {
254275
handleUploadAction({ type: AttachmentUploadActionType.Set, newUploads });
255276
attachmentOptions?.uploadOptions?.handleAttachmentSelection(newUploads);
256277
},
257-
[attachmentOptions?.uploadOptions]
278+
[attachmentOptions?.uploadOptions, setKeyboardFocusAfterFileSelection]
258279
);
259280

260281
/* @conditional-compile-remove(file-sharing-acs) */

packages/react-composites/src/composites/ChatComposite/file-sharing/AttachmentUploadButton.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33

44
/* @conditional-compile-remove(file-sharing-acs) */
5-
import { IconButton, mergeStyles, Stack, useTheme } from '@fluentui/react';
5+
import { IconButton, mergeStyles, Stack, TooltipHost, useTheme } from '@fluentui/react';
66
/* @conditional-compile-remove(file-sharing-acs) */
77
import React from 'react';
88
/* @conditional-compile-remove(file-sharing-acs) */
@@ -79,13 +79,20 @@ export const AttachmentUploadButton = (props: AttachmentUploadButtonProps): JSX.
7979
inputRef.current?.click();
8080
}}
8181
>
82-
<IconButton className={iconButtonClassName} ariaLabel={uploadAttachmentButtonStringTrampoline()}>
83-
<SendBoxAttachFileIconTrampoline />
84-
</IconButton>
82+
<TooltipHost content={uploadAttachmentButtonStringTrampoline()} data-ui-id="chat-composite-message-tooltip">
83+
<IconButton
84+
className={iconButtonClassName}
85+
ariaLabel={uploadAttachmentButtonStringTrampoline()}
86+
autoFocus={false}
87+
>
88+
<SendBoxAttachFileIconTrampoline />
89+
</IconButton>
90+
</TooltipHost>
8591
</Stack>
8692
<input
8793
data-testid="attachment-upload-button"
8894
ref={inputRef}
95+
autoFocus={false}
8996
hidden
9097
multiple={!disableMultipleUploads}
9198
accept={supportedMediaTypes.join(',')}

0 commit comments

Comments
 (0)