diff --git a/examples/next/pages/ui/components/storage/storage-browser/composable-playground/index.page.tsx b/examples/next/pages/ui/components/storage/storage-browser/composable-playground/index.page.tsx
index 66db5fb3850..f1ca05f4d87 100644
--- a/examples/next/pages/ui/components/storage/storage-browser/composable-playground/index.page.tsx
+++ b/examples/next/pages/ui/components/storage/storage-browser/composable-playground/index.page.tsx
@@ -11,7 +11,6 @@ import { Auth } from '../managedAuthAdapter';
import { Button, Flex, Breadcrumbs } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react-storage/styles.css';
-import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
const components: CreateStorageBrowserInput['components'] = {
Navigation: ({ items }) => (
diff --git a/examples/next/pages/ui/components/storage/storage-browser/custom-actions/index.page.tsx b/examples/next/pages/ui/components/storage/storage-browser/custom-actions/index.page.tsx
new file mode 100644
index 00000000000..f5eccbf88b1
--- /dev/null
+++ b/examples/next/pages/ui/components/storage/storage-browser/custom-actions/index.page.tsx
@@ -0,0 +1,129 @@
+import React from 'react';
+
+import { createStorageBrowser } from '@aws-amplify/ui-react-storage/browser';
+
+import { Flex } from '@aws-amplify/ui-react';
+
+import '@aws-amplify/ui-react-storage/styles.css';
+
+const { StorageBrowser } = createStorageBrowser({
+ actions: {
+ default: {
+ copy: {
+ actionListItem: {
+ icon: 'copy-file',
+ label: 'Override Copy',
+ },
+ handler: ({ data }) => {
+ const { key } = data;
+ return {
+ result: Promise.resolve({ status: 'COMPLETE', value: { key } }),
+ };
+ },
+ viewName: 'CopyView',
+ },
+ createFolder: {
+ actionListItem: {
+ icon: 'create-folder',
+ label: 'Override Create Folder',
+ },
+ handler: ({ data }) => {
+ const { key } = data;
+ return {
+ result: Promise.resolve({ status: 'COMPLETE', value: { key } }),
+ };
+ },
+ viewName: 'CreateFolderView',
+ },
+ delete: {
+ actionListItem: {
+ icon: 'delete-file',
+ label: 'Override Delete',
+ },
+ handler: ({ data }) => {
+ const { key } = data;
+ return {
+ result: Promise.resolve({ status: 'COMPLETE', value: { key } }),
+ };
+ },
+ viewName: 'DeleteView',
+ },
+ download: () => {
+ return {
+ result: Promise.resolve({
+ status: 'COMPLETE',
+ value: { url: new URL('') },
+ }),
+ };
+ },
+ upload: {
+ actionListItem: {
+ icon: 'upload-file',
+ label: 'Override Upload',
+ },
+ handler: ({ data }) => {
+ const { key } = data;
+ return {
+ result: Promise.resolve({ status: 'COMPLETE', value: { key } }),
+ };
+ },
+ viewName: 'UploadView',
+ },
+ listLocationItems: () =>
+ Promise.resolve({
+ items: [
+ {
+ id: 'jaskjkaska',
+ key: 'item-key',
+ lastModified: new Date(),
+ size: 1008,
+ type: 'FILE' as const,
+ },
+ ],
+ nextToken: undefined,
+ }),
+ },
+ },
+ config: {
+ getLocationCredentials: () =>
+ Promise.resolve({
+ credentials: {
+ accessKeyId: '',
+ expiration: new Date(),
+ secretAccessKey: '',
+ sessionToken: '',
+ },
+ }),
+ region: '',
+ registerAuthListener: () => null,
+ listLocations: () =>
+ Promise.resolve({
+ items: [
+ {
+ bucket: 'my-bucket',
+ id: crypto.randomUUID(),
+ permissions: ['delete', 'get', 'list', 'write'],
+ prefix: 'my-prefix',
+ type: 'PREFIX',
+ },
+ ],
+ nextToken: undefined,
+ }),
+ },
+});
+
+function Example() {
+ return (
+
+
+
+ );
+}
+
+export default Example;
diff --git a/examples/next/pages/ui/components/storage/storage-browser/default-auth/index.page.tsx b/examples/next/pages/ui/components/storage/storage-browser/default-auth/index.page.tsx
index 494fc67d94f..2af0d66bc65 100644
--- a/examples/next/pages/ui/components/storage/storage-browser/default-auth/index.page.tsx
+++ b/examples/next/pages/ui/components/storage/storage-browser/default-auth/index.page.tsx
@@ -12,7 +12,6 @@ import {
import { StorageBrowser } from '@aws-amplify/ui-react-storage';
import '@aws-amplify/ui-react-storage/styles.css';
-import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
import config from './aws-exports';
diff --git a/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/StorageBrowser.ts b/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/StorageBrowser.ts
index de650f99e9c..30eb2ac6093 100644
--- a/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/StorageBrowser.ts
+++ b/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/StorageBrowser.ts
@@ -4,8 +4,6 @@ import {
createAmplifyAuthAdapter,
createStorageBrowser,
} from '@aws-amplify/ui-react-storage/browser';
-import '@aws-amplify/ui-react-storage/styles.css';
-import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
import config from './aws-exports';
diff --git a/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/[locations]/[location-detail]/index.page.tsx b/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/[locations]/[location-detail]/index.page.tsx
index be01ddb40ca..32ab12f4431 100644
--- a/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/[locations]/[location-detail]/index.page.tsx
+++ b/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/[locations]/[location-detail]/index.page.tsx
@@ -6,7 +6,6 @@ import { Button, Flex } from '@aws-amplify/ui-react';
import { StorageBrowser } from '../../StorageBrowser';
-import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
import '@aws-amplify/ui-react-storage/styles.css';
export default function Page() {
diff --git a/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/[locations]/index.page.tsx b/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/[locations]/index.page.tsx
index b50fd485c02..8d3093dd95c 100644
--- a/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/[locations]/index.page.tsx
+++ b/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/[locations]/index.page.tsx
@@ -6,7 +6,6 @@ import { Button, Flex } from '@aws-amplify/ui-react';
import { StorageBrowser } from '../StorageBrowser';
-import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
import '@aws-amplify/ui-react-storage/styles.css';
function Locations() {
diff --git a/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/index.page.tsx b/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/index.page.tsx
index 9cfc40de58b..d298cb47bc0 100644
--- a/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/index.page.tsx
+++ b/examples/next/pages/ui/components/storage/storage-browser/default-auth/routed/index.page.tsx
@@ -6,7 +6,6 @@ import useIsSignedIn from './useIsSignedIn';
import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react-storage/styles.css';
-import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
function Example() {
const router = useRouter();
diff --git a/examples/next/pages/ui/components/storage/storage-browser/managed-auth/index.page.tsx b/examples/next/pages/ui/components/storage/storage-browser/managed-auth/index.page.tsx
index 18f2c1f20e9..a718060b9bb 100644
--- a/examples/next/pages/ui/components/storage/storage-browser/managed-auth/index.page.tsx
+++ b/examples/next/pages/ui/components/storage/storage-browser/managed-auth/index.page.tsx
@@ -1,19 +1,104 @@
import React from 'react';
+import { getUrl } from '@aws-amplify/storage/internals';
-import { createStorageBrowser } from '@aws-amplify/ui-react-storage/browser';
+import {
+ ActionViewConfig,
+ ActionHandler,
+ createStorageBrowser,
+} from '@aws-amplify/ui-react-storage/browser';
import { managedAuthAdapter } from '../managedAuthAdapter';
import { SignIn, SignOutButton } from './routed/components';
-
-import { Flex, View } from '@aws-amplify/ui-react';
+import {
+ Button,
+ Flex,
+ Link,
+ StepperField,
+ Text,
+ View,
+} from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react-storage/styles.css';
-import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
-const { StorageBrowser } = createStorageBrowser({
+type GetLink = ActionHandler<{ duration: number; fileKey: string }, string>;
+
+const getLink: GetLink = ({ data, config }) => {
+ const result = getUrl({
+ path: data.key,
+ options: {
+ bucket: { bucketName: config.bucket, region: config.region },
+ locationCredentialsProvider: config.credentials,
+ expiresIn: data.duration * 60,
+ validateObjectExistence: true,
+ },
+ }).then((res) => ({
+ status: 'COMPLETE' as const,
+ value: res.url.toString(),
+ }));
+
+ return { result };
+};
+
+const generateLink: ActionViewConfig = {
+ handler: getLink,
+ viewName: 'LinkActionView',
+ actionListItem: {
+ icon: 'download',
+ label: 'Generate Download Links',
+ disable: (selected) => !selected?.length,
+ },
+};
+
+const { StorageBrowser, useAction, useView } = createStorageBrowser({
+ actions: { custom: { generateLink } },
config: managedAuthAdapter,
});
+const LinkActionView = () => {
+ const [duration, setDuration] = React.useState(60);
+
+ const locationDetailState = useView('LocationDetail');
+ const { onActionExit, fileDataItems } = locationDetailState;
+
+ const items = React.useMemo(
+ () =>
+ !fileDataItems
+ ? []
+ : fileDataItems.map((item) => ({ ...item, duration })),
+ [fileDataItems, duration]
+ );
+
+ const [{ tasks }, handleCreate] = useAction('generateLink', { items });
+
+ return (
+
+
+ {
+ setDuration(value);
+ }}
+ />
+
+ {!tasks
+ ? null
+ : tasks.map(({ data, status, value }) => {
+ return (
+
+ {data.fileKey}
+ {value ? link : null}
+ {status}
+
+ );
+ })}
+
+ );
+};
+
function Example() {
const [showSignIn, setShowSignIn] = React.useState(false);
@@ -29,9 +114,8 @@ function Example() {
>
setShowSignIn(false)} />
-
+
+
);
diff --git a/examples/next/pages/ui/components/storage/storage-browser/managed-auth/routed/[locations]/[location-detail]/index.page.tsx b/examples/next/pages/ui/components/storage/storage-browser/managed-auth/routed/[locations]/[location-detail]/index.page.tsx
index f97c16a4e6c..4ddefd7cadc 100644
--- a/examples/next/pages/ui/components/storage/storage-browser/managed-auth/routed/[locations]/[location-detail]/index.page.tsx
+++ b/examples/next/pages/ui/components/storage/storage-browser/managed-auth/routed/[locations]/[location-detail]/index.page.tsx
@@ -6,7 +6,6 @@ import { SignOutButton } from '../../components';
import { StorageBrowser } from '../../StorageBrowser';
import '@aws-amplify/ui-react-storage/styles.css';
-import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
export default function Page() {
const { back, query, pathname, replace } = useRouter();
@@ -50,7 +49,10 @@ export default function Page() {
}}
/>
{typeof query.actionType === 'string' ? (
-