From 316851dc3e3be42eac8124eb643c1af35c80701a Mon Sep 17 00:00:00 2001 From: aadimch Date: Wed, 9 Apr 2025 11:05:34 -0700 Subject: [PATCH 1/4] fix: upload status not annouced to AT users --- .../StorageManager/StorageManager.tsx | 4 +- .../ui/FileList/FileStatusMessage.tsx | 126 +++++++++++------- .../__tests__/FileStatusMessage.test.tsx | 47 +++++++ .../__snapshots__/FileControl.test.tsx.snap | 24 ++++ .../__snapshots__/FileList.test.tsx.snap | 18 +++ .../FileStatusMessage.test.tsx.snap | 47 ++++++- 6 files changed, 215 insertions(+), 51 deletions(-) diff --git a/packages/react-storage/src/components/StorageManager/StorageManager.tsx b/packages/react-storage/src/components/StorageManager/StorageManager.tsx index 35cc2199d07..e48004d99b9 100644 --- a/packages/react-storage/src/components/StorageManager/StorageManager.tsx +++ b/packages/react-storage/src/components/StorageManager/StorageManager.tsx @@ -183,7 +183,9 @@ const StorageManagerBase = React.forwardRef(function StorageManager( }; const onUploadAll = () => { - queueFiles(); + setTimeout(() => { + queueFiles(); + }, 5000); }; const onPauseUpload: TaskHandler = ({ id, uploadTask }) => { diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/FileStatusMessage.tsx b/packages/react-storage/src/components/StorageManager/ui/FileList/FileStatusMessage.tsx index 9fcb634e10b..09214afb77b 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/FileStatusMessage.tsx +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/FileStatusMessage.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { classNames } from '@aws-amplify/ui'; import { ComponentClassName } from '@aws-amplify/ui'; -import { Text, View } from '@aws-amplify/ui-react'; +import { Text, View, VisuallyHidden } from '@aws-amplify/ui-react'; import { IconCheck, IconError, useIcons } from '@aws-amplify/ui-react/internal'; import { classNameModifier } from '@aws-amplify/ui'; import { FileStatus } from '../../../FileUploader/types'; @@ -17,55 +17,83 @@ export const FileStatusMessage = ({ uploadSuccessfulText, }: FileStatusMessageProps): React.JSX.Element | null => { const icons = useIcons('storageManager'); - switch (status) { - case FileStatus.UPLOADING: { - return ( - - {getUploadingText(percentage)} - - ); + + // Generate the screen reader announcement text + const announcementText = () => { + switch (status) { + case FileStatus.UPLOADING: + return `File upload status changed: Uploading ${percentage}%`; + case FileStatus.PAUSED: + return `File upload status changed: Paused at ${percentage}%`; + case FileStatus.UPLOADED: + return `File upload status changed: Upload completed successfully`; + case FileStatus.ERROR: + return `File upload status changed: Error`; + case FileStatus.QUEUED: + return `File upload status changed: Queued`; + default: + return ''; } - case FileStatus.PAUSED: - return ( - - {getPausedText(percentage)} - - ); - case FileStatus.UPLOADED: - return ( - { + switch (status) { + case FileStatus.UPLOADING: { + return ( + + {getUploadingText(percentage)} + + ); + } + case FileStatus.PAUSED: + return ( + + {getPausedText(percentage)} + + ); + case FileStatus.UPLOADED: + return ( + - - {icons?.success ?? } - - {uploadSuccessfulText} - - ); - case FileStatus.ERROR: - return ( - + + {icons?.success ?? } + + {uploadSuccessfulText} + + ); + case FileStatus.ERROR: + return ( + - - {icons?.error ?? } - - {errorMessage} - - ); - default: - return null; - } + classNameModifier( + ComponentClassName.StorageManagerFileStatus, + 'error' + ) + )} + > + + {icons?.error ?? } + + {errorMessage} + + ); + default: + return null; + } + }; + + return ( + <> + {announcementText()} + {renderStatusMessage()} + + ); }; diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/FileStatusMessage.test.tsx b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/FileStatusMessage.test.tsx index b90660460c5..ad84c29550c 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/FileStatusMessage.test.tsx +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/FileStatusMessage.test.tsx @@ -105,4 +105,51 @@ describe('FileStatusMessage', () => { expect(screen.getByTestId('error')).toBeInTheDocument(); expect(container).toMatchSnapshot(); }); + + it('announces upload progress when status is uploading', () => { + render( + + ); + + const announcement = screen.getByRole('status'); + expect(announcement).toHaveTextContent( + 'File upload status changed: Uploading 50%' + ); + }); + + it('announces paused status with progress', () => { + render(); + + const announcement = screen.getByRole('status'); + expect(announcement).toHaveTextContent( + 'File upload status changed: Paused at 50%' + ); + }); + + it('announces successful upload completion', () => { + render( + + ); + + const announcement = screen.getByRole('status'); + expect(announcement).toHaveTextContent( + 'File upload status changed: Upload completed successfully' + ); + }); + + it('announces error status', () => { + render(); + + const announcement = screen.getByRole('status'); + expect(announcement).toHaveTextContent('File upload status changed: Error'); + }); + + it('has no announcement for queued status', () => { + render(); + + const announcement = screen.getByRole('status'); + expect(announcement).toHaveTextContent( + 'File upload status changed: Queued' + ); + }); }); diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileControl.test.tsx.snap b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileControl.test.tsx.snap index bb8a73ced68..df905a58c08 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileControl.test.tsx.snap +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileControl.test.tsx.snap @@ -75,6 +75,12 @@ exports[`FileControl renders as expected when file is uploading 1`] = ` + + File upload status changed: Uploading 0% +

@@ -137,6 +143,12 @@ exports[`FileControl renders as expected when uploading is paused 1`] = ` + + File upload status changed: Paused at 0% +

@@ -242,6 +254,12 @@ exports[`FileControl renders thumbnails 1`] = ` + + File upload status changed: Uploading 0% +

@@ -347,6 +365,12 @@ exports[`FileControl should default to showThumbnails being true 1`] = ` + + File upload status changed: Uploading 0% +

diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileList.test.tsx.snap b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileList.test.tsx.snap index 615ca3b0a97..ace48284046 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileList.test.tsx.snap +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileList.test.tsx.snap @@ -85,6 +85,12 @@ exports[`FileList renders an alert in case of error 1`] = ` + + File upload status changed: Uploading 0% +

@@ -219,6 +225,12 @@ exports[`FileList renders as expected 1`] = ` + + File upload status changed: Uploading 0% +

@@ -311,6 +323,12 @@ exports[`FileList renders as expected when upload is resumable 1`] = ` + + File upload status changed: Uploading 0% +

diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileStatusMessage.test.tsx.snap b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileStatusMessage.test.tsx.snap index 676c3ab42b7..df2462dc359 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileStatusMessage.test.tsx.snap +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/__snapshots__/FileStatusMessage.test.tsx.snap @@ -2,6 +2,12 @@ exports[`FileStatusMessage renders as expected when file is uploaded 1`] = `

+ + File upload status changed: Upload completed successfully +

@@ -31,6 +37,12 @@ exports[`FileStatusMessage renders as expected when file is uploaded 1`] = ` exports[`FileStatusMessage renders as expected when file is uploading 1`] = `

+ + File upload status changed: Uploading 50% +

@@ -41,6 +53,12 @@ exports[`FileStatusMessage renders as expected when file is uploading 1`] = ` exports[`FileStatusMessage renders as expected when file uploading is paused 1`] = `

+ + File upload status changed: Paused at 50% +

@@ -51,6 +69,12 @@ exports[`FileStatusMessage renders as expected when file uploading is paused 1`] exports[`FileStatusMessage renders as expected when there is an error uploading 1`] = `

+ + File upload status changed: Error +

@@ -80,6 +104,12 @@ exports[`FileStatusMessage renders as expected when there is an error uploading exports[`FileStatusMessage renders custom icons from IconProvider 1`] = `

+ + File upload status changed: Error +

@@ -90,6 +120,12 @@ exports[`FileStatusMessage renders custom icons from IconProvider 1`] = ` Error

+ + File upload status changed: Upload completed successfully +

@@ -103,4 +139,13 @@ exports[`FileStatusMessage renders custom icons from IconProvider 1`] = `

`; -exports[`FileStatusMessage renders nothing when status is queued 1`] = `
`; +exports[`FileStatusMessage renders nothing when status is queued 1`] = ` +
+ + File upload status changed: Queued + +
+`; From 6abf5d61a21729ca9f593117006e61fdcb77132a Mon Sep 17 00:00:00 2001 From: aadimch Date: Thu, 10 Apr 2025 10:24:11 -0700 Subject: [PATCH 2/4] chore: remove debug artifact --- .../src/components/StorageManager/StorageManager.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/react-storage/src/components/StorageManager/StorageManager.tsx b/packages/react-storage/src/components/StorageManager/StorageManager.tsx index e48004d99b9..35cc2199d07 100644 --- a/packages/react-storage/src/components/StorageManager/StorageManager.tsx +++ b/packages/react-storage/src/components/StorageManager/StorageManager.tsx @@ -183,9 +183,7 @@ const StorageManagerBase = React.forwardRef(function StorageManager( }; const onUploadAll = () => { - setTimeout(() => { - queueFiles(); - }, 5000); + queueFiles(); }; const onPauseUpload: TaskHandler = ({ id, uploadTask }) => { From a5ef05d25ba0ffec101894bfe7bd7f2a60b5349a Mon Sep 17 00:00:00 2001 From: aadimch Date: Fri, 11 Apr 2025 14:21:14 -0700 Subject: [PATCH 3/4] Create fluffy-pandas-heal.md --- .changeset/fluffy-pandas-heal.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fluffy-pandas-heal.md diff --git a/.changeset/fluffy-pandas-heal.md b/.changeset/fluffy-pandas-heal.md new file mode 100644 index 00000000000..cca7d813d24 --- /dev/null +++ b/.changeset/fluffy-pandas-heal.md @@ -0,0 +1,5 @@ +--- +"@aws-amplify/ui-react-storage": patch +--- + +fix(react-storage): upload status not annouced to AT users From 604d9f1a4011706d472ff26e60686f70f4c4ab0e Mon Sep 17 00:00:00 2001 From: aadimch Date: Fri, 2 May 2025 13:45:13 -0700 Subject: [PATCH 4/4] chore: create a top level getStatusAnnouncementText and pass them through displayText to allow customer override --- .../FileUploader/utils/displayText.ts | 21 +++++++++++++++++ .../ui/FileList/FileControl.tsx | 2 ++ .../ui/FileList/FileStatusMessage.tsx | 23 ++++--------------- .../__tests__/FileStatusMessage.test.tsx | 18 ++++++++++++++- .../StorageManager/ui/FileList/types.ts | 5 +++- 5 files changed, 48 insertions(+), 21 deletions(-) diff --git a/packages/react-storage/src/components/FileUploader/utils/displayText.ts b/packages/react-storage/src/components/FileUploader/utils/displayText.ts index 403cb3420e9..cb56f3c25a9 100644 --- a/packages/react-storage/src/components/FileUploader/utils/displayText.ts +++ b/packages/react-storage/src/components/FileUploader/utils/displayText.ts @@ -1,4 +1,5 @@ import { DisplayTextTemplate } from '@aws-amplify/ui'; +import { FileStatus } from '../types'; export type FileUploaderDisplayText = DisplayTextTemplate<{ getFilesUploadedText?: (count: number) => string; @@ -9,6 +10,10 @@ export type FileUploaderDisplayText = DisplayTextTemplate<{ getUploadButtonText?: (count: number) => string; getMaxFilesErrorText?: (count: number) => string; getErrorText?: (message: string) => string; + getStatusAnnouncementText?: ( + status: FileStatus, + percentage?: number + ) => string; doneButtonText?: string; clearAllButtonText?: string; extensionNotAllowedText?: string; @@ -49,6 +54,22 @@ export const defaultFileUploaderDisplayText: FileUploaderDisplayTextDefault = { getErrorText(message: string): string { return message; }, + getStatusAnnouncementText(status: FileStatus, percentage?: number): string { + switch (status) { + case FileStatus.UPLOADING: + return `File upload status changed: Uploading ${percentage}%`; + case FileStatus.PAUSED: + return `File upload status changed: Paused at ${percentage}%`; + case FileStatus.UPLOADED: + return `File upload status changed: Upload completed successfully`; + case FileStatus.ERROR: + return `File upload status changed: Error`; + case FileStatus.QUEUED: + return `File upload status changed: Queued`; + default: + return ''; + } + }, doneButtonText: 'Done', clearAllButtonText: 'Clear all', extensionNotAllowedText: 'Extension not allowed', diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/FileControl.tsx b/packages/react-storage/src/components/StorageManager/ui/FileList/FileControl.tsx index 3baba83b2ba..365f3396b8f 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/FileControl.tsx +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/FileControl.tsx @@ -30,6 +30,7 @@ export function FileControl({ const { getPausedText, getUploadingText, + getStatusAnnouncementText, uploadSuccessfulText, pauseButtonText, resumeButtonText, @@ -76,6 +77,7 @@ export function FileControl({ uploadSuccessfulText={uploadSuccessfulText} getUploadingText={getUploadingText} getPausedText={getPausedText} + getStatusAnnouncementText={getStatusAnnouncementText} status={status} errorMessage={errorMessage} percentage={progress} diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/FileStatusMessage.tsx b/packages/react-storage/src/components/StorageManager/ui/FileList/FileStatusMessage.tsx index 09214afb77b..72df09a041f 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/FileStatusMessage.tsx +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/FileStatusMessage.tsx @@ -12,30 +12,13 @@ export const FileStatusMessage = ({ errorMessage, getPausedText, getUploadingText, + getStatusAnnouncementText, percentage, status, uploadSuccessfulText, }: FileStatusMessageProps): React.JSX.Element | null => { const icons = useIcons('storageManager'); - // Generate the screen reader announcement text - const announcementText = () => { - switch (status) { - case FileStatus.UPLOADING: - return `File upload status changed: Uploading ${percentage}%`; - case FileStatus.PAUSED: - return `File upload status changed: Paused at ${percentage}%`; - case FileStatus.UPLOADED: - return `File upload status changed: Upload completed successfully`; - case FileStatus.ERROR: - return `File upload status changed: Error`; - case FileStatus.QUEUED: - return `File upload status changed: Queued`; - default: - return ''; - } - }; - const renderStatusMessage = () => { switch (status) { case FileStatus.UPLOADING: { @@ -92,7 +75,9 @@ export const FileStatusMessage = ({ return ( <> - {announcementText()} + + {getStatusAnnouncementText(status, percentage)} + {renderStatusMessage()} ); diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/FileStatusMessage.test.tsx b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/FileStatusMessage.test.tsx index ad84c29550c..c3b6b66b532 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/FileStatusMessage.test.tsx +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/__tests__/FileStatusMessage.test.tsx @@ -16,6 +16,22 @@ const defaultProps: Omit = { errorMessage: errorUploading, percentage: 50, getUploadingText: (percentage: number) => `${uploadingText} ${percentage}%`, + getStatusAnnouncementText: (status: FileStatus, percentage?: number) => { + switch (status) { + case FileStatus.UPLOADING: + return `File upload status changed: Uploading ${percentage}%`; + case FileStatus.PAUSED: + return `File upload status changed: Paused at ${percentage}%`; + case FileStatus.UPLOADED: + return 'File upload status changed: Upload completed successfully'; + case FileStatus.ERROR: + return 'File upload status changed: Error'; + case FileStatus.QUEUED: + return 'File upload status changed: Queued'; + default: + return ''; + } + }, getPausedText: () => uploadingPausedText, uploadSuccessfulText: uploadSuccessful, }; @@ -144,7 +160,7 @@ describe('FileStatusMessage', () => { expect(announcement).toHaveTextContent('File upload status changed: Error'); }); - it('has no announcement for queued status', () => { + it('announces queued status', () => { render(); const announcement = screen.getByRole('status'); diff --git a/packages/react-storage/src/components/StorageManager/ui/FileList/types.ts b/packages/react-storage/src/components/StorageManager/ui/FileList/types.ts index 265317f32d5..147a117ff10 100644 --- a/packages/react-storage/src/components/StorageManager/ui/FileList/types.ts +++ b/packages/react-storage/src/components/StorageManager/ui/FileList/types.ts @@ -38,7 +38,10 @@ export interface FileControlProps { export interface FileStatusMessageProps extends Pick< StorageManagerDisplayTextDefault, - 'getUploadingText' | 'getPausedText' | 'uploadSuccessfulText' + | 'getUploadingText' + | 'getPausedText' + | 'uploadSuccessfulText' + | 'getStatusAnnouncementText' > { status: FileStatus; errorMessage: string;