diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/__tests__/context.spec.tsx b/packages/react-storage/src/components/StorageBrowser/displayText/__tests__/context.spec.tsx
new file mode 100644
index 00000000000..e8c4ec8d149
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/__tests__/context.spec.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { renderHook } from '@testing-library/react';
+
+import { DisplayTextProvider, useDisplayText } from '../context';
+import { DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT } from '../libraries';
+
+describe('useDisplayText', () => {
+ it('returns default displayText`', () => {
+ const { result } = renderHook(useDisplayText, {
+ wrapper: (props) => ,
+ });
+
+ expect(result.current.LocationDetailView).toStrictEqual(
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT['LocationDetailView']
+ );
+ expect(result.current.LocationsView).toStrictEqual(
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT['LocationsView']
+ );
+ expect(result.current.UploadView).toStrictEqual(
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT['UploadView']
+ );
+ });
+});
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/context.tsx b/packages/react-storage/src/components/StorageBrowser/displayText/context.tsx
new file mode 100644
index 00000000000..7016ef1803e
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/context.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import { createContextUtilities } from '@aws-amplify/ui-react-core';
+
+import { DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT } from './libraries';
+import {
+ DefaultStorageBrowserDisplayText,
+ StorageBrowserDisplayText,
+} from './types';
+
+export const { DisplayTextContext, useDisplayText } = createContextUtilities<
+ DefaultStorageBrowserDisplayText,
+ 'DisplayText'
+>({
+ contextName: 'DisplayText',
+ errorMessage: '`useDisplayText` must be called inside `DisplayTextProvider`',
+});
+
+export function DisplayTextProvider({
+ children,
+ displayText: _override,
+}: {
+ children?: React.ReactNode;
+ displayText?: StorageBrowserDisplayText;
+}): React.JSX.Element {
+ // do deep merge here of default and override here
+ return (
+
+ {children}
+
+ );
+}
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/index.ts b/packages/react-storage/src/components/StorageBrowser/displayText/index.ts
new file mode 100644
index 00000000000..19ffbdbe2d6
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/index.ts
@@ -0,0 +1 @@
+export { DisplayTextProvider, useDisplayText } from './context';
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/__tests__/__snapshots__/index.spec.ts.snap b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/__tests__/__snapshots__/index.spec.ts.snap
new file mode 100644
index 00000000000..dfc95def098
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/__tests__/__snapshots__/index.spec.ts.snap
@@ -0,0 +1,101 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationDetailView should have expected keys 1`] = `
+{
+ "getListResultsMessage": [Function],
+ "searchExhaustedMessage": "Showing results for up to the first 10,000 items",
+ "searchIncludeSubfoldersLabel": "Include subfolders",
+ "searchPlaceholder": "Search current folder",
+ "searchSubmitLabel": "Search",
+ "tableColumnLastModifiedHeader": "Last modified",
+ "tableColumnNameHeader": "Name",
+ "tableColumnSizeHeader": "Size",
+ "tableColumnTypeHeader": "Type",
+ "title": [Function],
+}
+`;
+
+exports[`DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationsView should match snapshot 1`] = `
+{
+ "getListResultsMessage": [Function],
+ "searchPlaceholder": "Filter files and folders",
+ "searchSubmitLabel": "Search",
+ "tableColumnBucketHeader": "Bucket",
+ "tableColumnFolderHeader": "Folder",
+ "tableColumnPermissionsHeader": "Permissions",
+}
+`;
+
+exports[`DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.UploadView should match snapshot 1`] = `
+{
+ "actionCancelLabel": "Cancel",
+ "actionDestinationLabel": "Destination",
+ "actionExitLabel": "Exit",
+ "actionStartLabel": "Upload",
+ "addFilesLabel": "Add files",
+ "addFolderLabel": "Add folder",
+ "getActionCompleteMessage": [Function],
+ "overwriteExistingLabel": "Overwrite existing files",
+ "statusDisplayCanceledLabel": "Canceled",
+ "statusDisplayCompletedLabel": "Completed",
+ "statusDisplayFailedLabel": "Failed",
+ "statusDisplayOverridePreventedLabel": "Overwrite prevented",
+ "statusDisplayQueuedLabel": "Not Started",
+ "statusDisplayTotalLabel": "Total",
+ "tableColumnCancelHeader": "",
+ "tableColumnFolderHeader": "Folder",
+ "tableColumnNameHeader": "Name",
+ "tableColumnSizeHeader": "Size",
+ "tableColumnStatusHeader": "Status",
+ "tableColumnTypeHeader": "Type",
+ "title": "Upload",
+}
+`;
+
+exports[`DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT should match snapshot 1`] = `
+{
+ "LocationDetailView": {
+ "getListResultsMessage": [Function],
+ "searchExhaustedMessage": "Showing results for up to the first 10,000 items",
+ "searchIncludeSubfoldersLabel": "Include subfolders",
+ "searchPlaceholder": "Search current folder",
+ "searchSubmitLabel": "Search",
+ "tableColumnLastModifiedHeader": "Last modified",
+ "tableColumnNameHeader": "Name",
+ "tableColumnSizeHeader": "Size",
+ "tableColumnTypeHeader": "Type",
+ "title": [Function],
+ },
+ "LocationsView": {
+ "getListResultsMessage": [Function],
+ "searchPlaceholder": "Filter files and folders",
+ "searchSubmitLabel": "Search",
+ "tableColumnBucketHeader": "Bucket",
+ "tableColumnFolderHeader": "Folder",
+ "tableColumnPermissionsHeader": "Permissions",
+ },
+ "UploadView": {
+ "actionCancelLabel": "Cancel",
+ "actionDestinationLabel": "Destination",
+ "actionExitLabel": "Exit",
+ "actionStartLabel": "Upload",
+ "addFilesLabel": "Add files",
+ "addFolderLabel": "Add folder",
+ "getActionCompleteMessage": [Function],
+ "overwriteExistingLabel": "Overwrite existing files",
+ "statusDisplayCanceledLabel": "Canceled",
+ "statusDisplayCompletedLabel": "Completed",
+ "statusDisplayFailedLabel": "Failed",
+ "statusDisplayOverridePreventedLabel": "Overwrite prevented",
+ "statusDisplayQueuedLabel": "Not Started",
+ "statusDisplayTotalLabel": "Total",
+ "tableColumnCancelHeader": "",
+ "tableColumnFolderHeader": "Folder",
+ "tableColumnNameHeader": "Name",
+ "tableColumnSizeHeader": "Size",
+ "tableColumnStatusHeader": "Status",
+ "tableColumnTypeHeader": "Type",
+ "title": "Upload",
+ },
+}
+`;
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/__tests__/index.spec.ts b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/__tests__/index.spec.ts
new file mode 100644
index 00000000000..d3975f00469
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/__tests__/index.spec.ts
@@ -0,0 +1,83 @@
+import { StatusCounts } from '../../../../tasks';
+import { DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT } from '../default';
+
+describe('DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT', () => {
+ it('should match snapshot', () => {
+ expect(DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT).toMatchSnapshot();
+ });
+
+ describe('DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationDetailView', () => {
+ it('should have expected keys', () => {
+ expect(
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationDetailView
+ ).toMatchObject({
+ getListResultsMessage: expect.any(Function),
+ searchExhaustedMessage: expect.any(String),
+ searchIncludeSubfoldersLabel: expect.any(String),
+ searchPlaceholder: expect.any(String),
+ tableColumnLastModifiedHeader: expect.any(String),
+ tableColumnNameHeader: expect.any(String),
+ tableColumnSizeHeader: expect.any(String),
+ tableColumnTypeHeader: expect.any(String),
+ title: expect.any(Function),
+ });
+
+ expect(
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationDetailView
+ ).toMatchSnapshot();
+ });
+
+ it('returns string values from callbacks', () => {
+ const { getListResultsMessage } =
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationDetailView;
+
+ expect(
+ typeof getListResultsMessage({
+ key: '',
+ id: '',
+ lastModified: new Date(),
+ size: 1000,
+ type: 'FILE',
+ })
+ ).toBe('string');
+ });
+ });
+
+ describe('DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationsView', () => {
+ it('should match snapshot', () => {
+ expect(
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationsView
+ ).toMatchSnapshot();
+ });
+
+ it('returns string values from callbacks', () => {
+ const { getListResultsMessage } =
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.LocationsView;
+
+ expect(
+ typeof getListResultsMessage({
+ bucket: '',
+ permission: 'READ',
+ prefix: '',
+ id: '',
+ type: 'PREFIX',
+ })
+ ).toBe('string');
+ });
+ });
+
+ describe('DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.UploadView', () => {
+ it('should match snapshot', () => {
+ expect(DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.UploadView).toMatchSnapshot();
+ });
+
+ it('returns string values from callbacks', () => {
+ const { getActionCompleteMessage } =
+ DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT.UploadView;
+
+ expect(typeof getActionCompleteMessage({} as StatusCounts)).toBe(
+ 'string'
+ );
+ });
+ });
+});
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/default.ts b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/default.ts
new file mode 100644
index 00000000000..9b3c7bfb97e
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/default.ts
@@ -0,0 +1,12 @@
+import { DefaultStorageBrowserDisplayText } from '../../types';
+
+import { DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT } from './locationDetailView';
+import { DEFAULT_LOCATIONS_VIEW_DISPLAY_TEXT } from './locationsView';
+import { DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT } from './uploadView';
+
+export const DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT: DefaultStorageBrowserDisplayText =
+ {
+ LocationDetailView: DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT,
+ LocationsView: DEFAULT_LOCATIONS_VIEW_DISPLAY_TEXT,
+ UploadView: DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT,
+ };
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/locationDetailView.ts b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/locationDetailView.ts
new file mode 100644
index 00000000000..411b9d158b9
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/locationDetailView.ts
@@ -0,0 +1,16 @@
+import { DEFAULT_LIST_VIEW_DISPLAY_TEXT } from './shared';
+import { DefaultLocationDetailViewDisplayText } from '../../types';
+
+export const DEFAULT_LOCATION_DETAIL_VIEW_DISPLAY_TEXT: DefaultLocationDetailViewDisplayText =
+ {
+ ...DEFAULT_LIST_VIEW_DISPLAY_TEXT,
+ getListResultsMessage: () => 'help me',
+ searchExhaustedMessage: 'Showing results for up to the first 10,000 items',
+ searchIncludeSubfoldersLabel: 'Include subfolders',
+ searchPlaceholder: 'Search current folder',
+ tableColumnLastModifiedHeader: 'Last modified',
+ tableColumnNameHeader: 'Name',
+ tableColumnSizeHeader: 'Size',
+ tableColumnTypeHeader: 'Type',
+ title: (_locations) => 'use _location to derive display value',
+ };
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/locationsView.ts b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/locationsView.ts
new file mode 100644
index 00000000000..5f798ecd345
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/locationsView.ts
@@ -0,0 +1,12 @@
+import { DEFAULT_LIST_VIEW_DISPLAY_TEXT } from './shared';
+import { DefaultLocationsViewDisplayText } from '../../types';
+
+export const DEFAULT_LOCATIONS_VIEW_DISPLAY_TEXT: DefaultLocationsViewDisplayText =
+ {
+ ...DEFAULT_LIST_VIEW_DISPLAY_TEXT,
+ searchPlaceholder: 'Filter files and folders',
+ getListResultsMessage: () => 'lol',
+ tableColumnBucketHeader: 'Bucket',
+ tableColumnFolderHeader: 'Folder',
+ tableColumnPermissionsHeader: 'Permissions',
+ };
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/shared.ts b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/shared.ts
new file mode 100644
index 00000000000..927976d446e
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/shared.ts
@@ -0,0 +1,32 @@
+import {
+ DefaultActionViewDisplayText,
+ DefaultListViewDisplayText,
+} from '../../types';
+
+export const DEFAULT_ACTION_VIEW_DISPLAY_TEXT: Omit<
+ DefaultActionViewDisplayText,
+ 'actionStartLabel' | 'getActionCompleteMessage' | 'title'
+> = {
+ actionCancelLabel: 'Cancel',
+ actionExitLabel: 'Exit',
+ actionDestinationLabel: 'Destination',
+ statusDisplayCanceledLabel: 'Canceled',
+ statusDisplayCompletedLabel: 'Completed',
+ statusDisplayFailedLabel: 'Failed',
+ statusDisplayTotalLabel: 'Total',
+ statusDisplayQueuedLabel: 'Not Started',
+ // empty by default
+ tableColumnCancelHeader: '',
+ tableColumnStatusHeader: 'Status',
+ tableColumnFolderHeader: 'Folder',
+ tableColumnNameHeader: 'Name',
+ tableColumnTypeHeader: 'Type',
+ tableColumnSizeHeader: 'Size',
+};
+
+export const DEFAULT_LIST_VIEW_DISPLAY_TEXT: Omit<
+ DefaultListViewDisplayText,
+ 'getListResultsMessage' | 'searchPlaceholder'
+> = {
+ searchSubmitLabel: 'Search',
+};
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/uploadView.ts b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/uploadView.ts
new file mode 100644
index 00000000000..c65575159d3
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/en/uploadView.ts
@@ -0,0 +1,62 @@
+import { DEFAULT_ACTION_VIEW_DISPLAY_TEXT } from './shared';
+import { DefaultUploadViewDisplayText } from '../../types';
+
+export const DEFAULT_UPLOAD_VIEW_DISPLAY_TEXT: DefaultUploadViewDisplayText = {
+ ...DEFAULT_ACTION_VIEW_DISPLAY_TEXT,
+ title: 'Upload',
+ actionStartLabel: 'Upload',
+ addFilesLabel: 'Add files',
+ addFolderLabel: 'Add folder',
+ getActionCompleteMessage: (_counts) => {
+ // if (counts.FAILED === counts.TOTAL) {
+ // return 'All uploads failed to complete.';
+ // }
+
+ // if (counts.CANCELED === counts.TOTAL) {
+ // return 'All uploads canceled.';
+ // }
+
+ // if (counts.OVERWRITE_PREVENTED === counts.TOTAL) {
+ // return 'Overwrite prevention applied to all uploads.';
+ // }
+
+ // if (counts.TOTAL === counts.COMPLETE) {
+ // return 'All uploads completed successfully.';
+ // }
+
+ // const prefix = 'All uploads complete';
+
+ // const succeeded = `${counts.COMPLETE} uploads successful`;
+ // const overwritePrevented = `overwrite prevention applied to ${counts.OVERWRITE_PREVENTED} uploads`;
+ // const _canceled = `${counts.CANCELED} uploads canceled`;
+ // const _failed = `${counts.FAILED} uploads failed`;
+
+ // // succeeded & errors
+ // // succeeded & errors & cancellations
+ // // succeeded & errors & cancellations & overwrite prevented
+ // // succeeded & cancellations
+ // // succeeded & cancellations & overwrite prevented
+ // // errors & cancellations
+ // // errors & cancellations & overwrite prevented
+ // // succeeded & cancellations & overwrite prevented
+ // // succeeded & overwrite prevented
+ // if (counts.TOTAL === counts.COMPLETE + counts.OVERWRITE_PREVENTED) {
+ // return `${prefix}. ${succeeded}, ${overwritePrevented}.`;
+ // }
+
+ // const hasErrors = counts.FAILED > 0;
+ // const _hasCanceledTasks = counts.CANCELED > 0;
+
+ // if (hasErrors) {
+ // return `All uploads complete. ${counts.COMPLETE} of ${counts.TOTAL} uploads successful, ${counts.FAILED} uploads failed to complete.`;
+ // }
+
+ return '🤷';
+ },
+ statusDisplayCanceledLabel: 'Canceled',
+ statusDisplayCompletedLabel: 'Completed',
+ statusDisplayFailedLabel: 'Failed',
+ statusDisplayOverridePreventedLabel: 'Overwrite prevented',
+ statusDisplayQueuedLabel: 'Not Started',
+ overwriteExistingLabel: 'Overwrite existing files',
+};
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/libraries/index.ts b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/index.ts
new file mode 100644
index 00000000000..56dfd99703b
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/libraries/index.ts
@@ -0,0 +1 @@
+export { DEFAULT_STORAGE_BROWSER_DISPLAY_TEXT } from './en/default';
diff --git a/packages/react-storage/src/components/StorageBrowser/displayText/types.ts b/packages/react-storage/src/components/StorageBrowser/displayText/types.ts
new file mode 100644
index 00000000000..85f686235e2
--- /dev/null
+++ b/packages/react-storage/src/components/StorageBrowser/displayText/types.ts
@@ -0,0 +1,84 @@
+import { StatusCounts } from '../tasks';
+import { LocationData, LocationItemData } from '../actions';
+
+/**
+ * Common display text values available on each action view (e.g. upload, copy, etc)
+ */
+export interface DefaultActionViewDisplayText {
+ actionCancelLabel: string;
+ actionDestinationLabel: string;
+ actionExitLabel: string;
+ actionStartLabel: string;
+ getActionCompleteMessage: (counts: StatusCounts) => string;
+ statusDisplayCanceledLabel: string;
+ statusDisplayCompletedLabel: string;
+ statusDisplayFailedLabel: string;
+ statusDisplayQueuedLabel: string;
+ statusDisplayTotalLabel: string;
+ title: string;
+ tableColumnCancelHeader: string;
+ tableColumnStatusHeader: string;
+ tableColumnFolderHeader: string;
+ tableColumnNameHeader: string;
+ tableColumnTypeHeader: string;
+ tableColumnSizeHeader: string;
+}
+
+/**
+ * Common list view display text values
+ */
+export interface DefaultListViewDisplayText {
+ searchPlaceholder: string;
+ searchSubmitLabel: string;
+ getListResultsMessage: (data: T, error?: Error) => string;
+}
+
+export interface DefaultLocationsViewDisplayText
+ extends DefaultListViewDisplayText {
+ tableColumnFolderHeader: string;
+ tableColumnBucketHeader: string;
+ tableColumnPermissionsHeader: string;
+}
+
+export interface DefaultLocationDetailViewDisplayText
+ extends DefaultListViewDisplayText {
+ title: string | ((location: LocationData) => string);
+ searchExhaustedMessage: string;
+ searchIncludeSubfoldersLabel: string;
+ tableColumnLastModifiedHeader: string;
+ tableColumnNameHeader: string;
+ tableColumnSizeHeader: string;
+ tableColumnTypeHeader: string;
+}
+
+export interface DefaultUploadViewDisplayText
+ extends DefaultActionViewDisplayText {
+ addFilesLabel: string;
+ addFolderLabel: string;
+ statusDisplayOverridePreventedLabel: string;
+ overwriteExistingLabel: string;
+}
+
+export interface DefaultStorageBrowserDisplayText {
+ LocationsView: DefaultLocationsViewDisplayText;
+ LocationDetailView: DefaultLocationDetailViewDisplayText;
+ UploadView: DefaultUploadViewDisplayText;
+ // CopyView
+ // DeleteView
+ // CreateFolderView
+}
+
+interface LocationsViewDisplayText
+ extends Partial {}
+interface LocationDetailViewDisplayText
+ extends Partial {}
+interface UploadViewDisplayText extends Partial {}
+
+export interface StorageBrowserDisplayText {
+ LocationsView?: LocationsViewDisplayText;
+ LocationDetailView?: LocationDetailViewDisplayText;
+ UploadView?: UploadViewDisplayText;
+ // CopyView
+ // DeleteView
+ // CreateFolderView
+}