From 9d65ec4963a5f99794084c4d42ae7db8ecf373d9 Mon Sep 17 00:00:00 2001 From: Robb Niznik Date: Wed, 13 Nov 2024 10:05:06 -0500 Subject: [PATCH] feat(components): support clearing `Toast` queues --- .changeset/mean-ducks-rest.md | 5 ++ packages/components/src/Toast.tsx | 12 ++++ packages/components/stories/Toast.stories.tsx | 60 +++++++++++++------ 3 files changed, 60 insertions(+), 17 deletions(-) create mode 100644 .changeset/mean-ducks-rest.md 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')); },