diff --git a/.changeset/polite-months-change.md b/.changeset/polite-months-change.md new file mode 100644 index 0000000000000..84436def02ee6 --- /dev/null +++ b/.changeset/polite-months-change.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Restores initial focus on description input in file upload modal for improved usability diff --git a/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx b/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx index 5be3948fa7a86..90b29fc94a16a 100644 --- a/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx +++ b/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx @@ -1,4 +1,5 @@ import { Modal, Box, Field, FieldGroup, FieldLabel, FieldRow, FieldError, TextInput, Button } from '@rocket.chat/fuselage'; +import { useAutoFocus, useMergedRefs } from '@rocket.chat/fuselage-hooks'; import { useToastMessageDispatch, useTranslation, useSetting } from '@rocket.chat/ui-contexts'; import fileSize from 'filesize'; import type { ReactElement, ComponentProps } from 'react'; @@ -75,6 +76,13 @@ const FileUploadModal = ({ const fileUploadFormId = useId(); const fileNameField = useId(); const fileDescriptionField = useId(); + const autoFocusRef = useAutoFocus(); + + const { ref, ...descriptionField } = register('description', { + validate: (value) => isDescriptionValid(value || ''), + }); + + const descriptionRef = useMergedRefs(ref, autoFocusRef); return ( {t('FileUpload')} - + @@ -115,9 +123,8 @@ const FileUploadModal = ({ isDescriptionValid(value || ''), - })} + ref={descriptionRef} + {...descriptionField} error={errors.description?.message} aria-invalid={errors.description ? 'true' : 'false'} aria-describedby={`${fileDescriptionField}-error`} diff --git a/apps/meteor/tests/e2e/file-upload.spec.ts b/apps/meteor/tests/e2e/file-upload.spec.ts index 626162df47d3f..7e61c39c60e09 100644 --- a/apps/meteor/tests/e2e/file-upload.spec.ts +++ b/apps/meteor/tests/e2e/file-upload.spec.ts @@ -27,20 +27,22 @@ test.describe.serial('file-upload', () => { expect((await api.post('/channels.delete', { roomName: targetChannel })).status()).toBe(200); }); - test('expect successfully cancel upload', async () => { + test('should successfully cancel upload', async () => { await poHomeChannel.content.dragAndDropTxtFile(); await poHomeChannel.content.btnModalCancel.click(); await expect(poHomeChannel.content.modalFilePreview).not.toBeVisible(); }); - test('expect send file not show modal', async () => { + test('should not display modal when clicking in send file', async () => { await poHomeChannel.content.dragAndDropTxtFile(); await poHomeChannel.content.btnModalConfirm.click(); await expect(poHomeChannel.content.modalFilePreview).not.toBeVisible(); }); - test('expect send file with name/description updated', async () => { + test('should send file with name/description updated', async () => { await poHomeChannel.content.dragAndDropTxtFile(); + await expect(poHomeChannel.content.descriptionInput).toBeFocused(); + await poHomeChannel.content.descriptionInput.fill('any_description'); await poHomeChannel.content.fileNameInput.fill('any_file1.txt'); await poHomeChannel.content.btnModalConfirm.click(); @@ -49,7 +51,7 @@ test.describe.serial('file-upload', () => { await expect(poHomeChannel.content.lastMessageFileName).toContainText('any_file1.txt'); }); - test('expect send lst file succesfully', async () => { + test('should send lst file successfully', async () => { await poHomeChannel.content.dragAndDropLstFile(); await poHomeChannel.content.descriptionInput.fill('lst_description'); await poHomeChannel.content.btnModalConfirm.click(); @@ -58,7 +60,7 @@ test.describe.serial('file-upload', () => { await expect(poHomeChannel.content.lastMessageFileName).toContainText('lst-test.lst'); }); - test('expect send drawio (unknown media type) file succesfully', async ({ page }) => { + test('should send drawio (unknown media type) file successfully', async ({ page }) => { await page.reload(); await poHomeChannel.content.sendFileMessage('diagram.drawio'); await poHomeChannel.content.descriptionInput.fill('drawio_description'); @@ -68,7 +70,7 @@ test.describe.serial('file-upload', () => { await expect(poHomeChannel.content.lastMessageFileName).toContainText('diagram.drawio'); }); - test('expect not to send drawio file (unknown media type) when the default media type is blocked', async ({ api, page }) => { + test('should not to send drawio file (unknown media type) when the default media type is blocked', async ({ api, page }) => { await setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'application/octet-stream'); await page.reload(); @@ -96,7 +98,7 @@ test.describe('file-upload-not-member', () => { expect((await api.post('/channels.delete', { roomName: targetChannel })).status()).toBe(200); }); - test('expect not be able to upload if not a member', async () => { + test('should not be able to upload if not a member', async () => { await poHomeChannel.content.dragAndDropTxtFile(); await expect(poHomeChannel.content.modalFilePreview).not.toBeVisible(); });