From 56b29983fe6d6d797d28519b9e22e0f99111e111 Mon Sep 17 00:00:00 2001 From: Andrew Holloway Date: Thu, 15 Aug 2024 10:40:43 -0400 Subject: [PATCH] docs(ToastNotification): add interactive implementation example - demo autodismiss behavior with stack of notifications - use state to track --- .../ToastNotification.stories.ts | 63 -------- .../ToastNotification.stories.tsx | 142 ++++++++++++++++++ 2 files changed, 142 insertions(+), 63 deletions(-) delete mode 100644 src/components/ToastNotification/ToastNotification.stories.ts create mode 100644 src/components/ToastNotification/ToastNotification.stories.tsx diff --git a/src/components/ToastNotification/ToastNotification.stories.ts b/src/components/ToastNotification/ToastNotification.stories.ts deleted file mode 100644 index ebda7629c..000000000 --- a/src/components/ToastNotification/ToastNotification.stories.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { StoryObj, Meta } from '@storybook/react'; -import type { ComponentProps } from 'react'; - -import { ToastNotification } from './ToastNotification'; - -export default { - title: 'Components/ToastNotification', - component: ToastNotification, - parameters: { - layout: 'centered', - badges: ['intro-1.0', 'current-2.0'], - }, - argTypes: { - onDismiss: { action: 'trigger dismiss' }, - timeout: { table: { disable: true } }, - }, - args: { - title: "You've got a temporary notification!", - className: 'w-96', - }, -} as Meta; - -type Args = ComponentProps; - -export const Default: StoryObj = {}; - -export const Favorable: StoryObj = { - args: { - status: 'favorable', - }, -}; - -/** - * Notifications can have different status, to indicate errors or destructive actions have completed. - */ -export const Critical: StoryObj = { - args: { - status: 'critical', - }, -}; - -/** - * We can restrict the ability to dismiss the notification by not specifying the `onDismiss` method. - */ -export const NotDismissable: StoryObj = { - args: { - ...Default.args, - onDismiss: undefined, - }, -}; - -/** - * Tooltips can be instructed to auto-close after a certain period. After the timeout, the component will call the defined - * `onDismiss` method. The behavior of the dissmisal is left up to the user, which allows for complete control. - */ -export const AutoDismiss: StoryObj = { - args: { - ...Default.args, - dissmissType: 'auto', - timeout: 500, - onDismiss: () => console.log('trigger onDismiss'), - }, -}; diff --git a/src/components/ToastNotification/ToastNotification.stories.tsx b/src/components/ToastNotification/ToastNotification.stories.tsx new file mode 100644 index 000000000..14b3419eb --- /dev/null +++ b/src/components/ToastNotification/ToastNotification.stories.tsx @@ -0,0 +1,142 @@ +import { Transition } from '@headlessui/react'; +import type { StoryObj, Meta } from '@storybook/react'; +import React from 'react'; + +import type { ComponentProps } from 'react'; + +import { ToastNotification } from './ToastNotification'; + +import Button from '../Button'; + +export default { + title: 'Components/ToastNotification', + component: ToastNotification, + parameters: { + layout: 'centered', + badges: ['intro-1.0', 'current-2.0'], + }, + argTypes: { + onDismiss: { action: 'trigger dismiss' }, + timeout: { table: { disable: true } }, + }, + args: { + title: "You've got a temporary notification!", + className: 'w-96', + }, +} as Meta; + +type Args = ComponentProps; +type Story = StoryObj; + +export const Default: Story = {}; + +export const Favorable: Story = { + args: { + status: 'favorable', + }, +}; + +/** + * Notifications can have different status, to indicate errors or destructive actions have completed. + */ +export const Critical: Story = { + args: { + status: 'critical', + }, +}; + +/** + * We can restrict the ability to dismiss the notification by not specifying the `onDismiss` method. + */ +export const NotDismissable: Story = { + args: { + ...Default.args, + onDismiss: undefined, + }, +}; + +/** + * Tooltips can be instructed to auto-close after a certain period. After the timeout, the component will call the defined + * `onDismiss` method. The behavior of the dissmisal is left up to the user, which allows for complete control. + */ +export const AutoDismiss: Story = { + args: { + ...Default.args, + dissmissType: 'auto', + timeout: 500, + onDismiss: () => console.log('trigger onDismiss'), + }, +}; + +let toastId = 0; +const ToastNotificationManager = (args: Args) => { + const [toasts, setToasts] = React.useState< + { id: number | string; text: string; show?: boolean }[] + >([]); + + // TODO: clean up `toasts` after .show is set to false (using useEffect?) + + return ( +
+ +
+ {toasts.map((toast) => ( + + { + setToasts( + toasts.map((thisToast) => { + return thisToast.id === toast.id + ? { ...thisToast, show: false } + : thisToast; + }), + ); + }} + title={'You got a new toast: ' + toast.text + toast.id} + /> + + ))} +
+
+ ); +}; + +/** + * This implementation example shows how you can use toasts with state to ghandle multiple, stacking notifications + */ +export const IEDismissingToasts: Story = { + render: (args) => , + parameters: { + // For interactive use, low value in snap testing again since already covered in other stories. + chromatic: { disableSnapshot: true }, + snapshot: { skip: true }, + }, +};