diff --git a/.changeset/mean-ducks-rest.md b/.changeset/mean-ducks-rest.md new file mode 100644 index 000000000..4d54382f1 --- /dev/null +++ b/.changeset/mean-ducks-rest.md @@ -0,0 +1,5 @@ +--- +"@launchpad-ui/components": patch +--- + +Support clearing `Toast` queues diff --git a/packages/components/src/Toast.tsx b/packages/components/src/Toast.tsx index 47ab710b5..9a54472de 100644 --- a/packages/components/src/Toast.tsx +++ b/packages/components/src/Toast.tsx @@ -187,15 +187,26 @@ const snackbarQueue = new AriaToastQueue({ const timeout = 6000; const ToastQueue = { + clear: () => { + for (const toast of toastQueue.visibleToasts) { + toastQueue.close(toast.key); + } + }, error: (children: ToastContent['children'], options?: ToastOptions) => toastQueue.add({ children, status: 'error' }, { ...options, timeout }), info: (children: ToastContent['children'], options?: ToastOptions) => toastQueue.add({ children, status: 'info' }, { ...options, timeout }), success: (children: ToastContent['children'], options?: ToastOptions) => toastQueue.add({ children, status: 'success' }, { ...options, timeout }), + visibleToasts: () => toastQueue.visibleToasts, }; const SnackbarQueue = { + clear: () => { + for (const toast of snackbarQueue.visibleToasts) { + snackbarQueue.close(toast.key); + } + }, error: (content: SnackbarContent, options?: ToastOptions) => { const key = snackbarQueue.add({ ...content, status: 'error' }, { ...options }); return () => snackbarQueue.close(key); @@ -208,6 +219,7 @@ const SnackbarQueue = { const key = snackbarQueue.add({ ...content, status: 'success' }, { ...options }); return () => snackbarQueue.close(key); }, + visibleToasts: () => snackbarQueue.visibleToasts, }; /** diff --git a/packages/components/stories/Toast.stories.tsx b/packages/components/stories/Toast.stories.tsx index 56355ddba..58d97d749 100644 --- a/packages/components/stories/Toast.stories.tsx +++ b/packages/components/stories/Toast.stories.tsx @@ -2,7 +2,15 @@ import type { Meta, StoryFn, StoryObj } from '@storybook/react'; import { expect, userEvent, within } from '@storybook/test'; -import { Button, Link, SnackbarContainer, SnackbarQueue, ToastContainer, ToastQueue } from '../src'; +import { + Button, + ButtonGroup, + Link, + SnackbarContainer, + SnackbarQueue, + ToastContainer, + ToastQueue, +} from '../src'; const meta: Meta = { component: ToastContainer, @@ -39,16 +47,25 @@ export const Example: Story = { return ( <> - + + + + ); }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await userEvent.click(canvas.getByRole('button')); + await userEvent.click(canvas.getAllByRole('button')[0]); const body = canvasElement.ownerDocument.body; await expect(await within(body).findByRole('alert')); }, @@ -59,24 +76,33 @@ export const Snackbar: Story = { return ( <> - + + + + ); }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); - await userEvent.click(canvas.getByRole('button')); + await userEvent.click(canvas.getAllByRole('button')[0]); const body = canvasElement.ownerDocument.body; await expect(await within(body).findByRole('alert')); },