Skip to content

Commit

Permalink
feat(ToastNotification): add dismissType with automated dismissing (#…
Browse files Browse the repository at this point in the history
…1980)

- add in new feature with default
- add tests and snapshots
  • Loading branch information
booc0mtaco authored Jun 7, 2024
1 parent e754588 commit 8545f14
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 10 deletions.
14 changes: 13 additions & 1 deletion src/components/ToastNotification/ToastNotification.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ export default {
layout: 'centered',
badges: ['intro-1.0', 'current-2.0'],
},
argTypes: { onDismiss: { action: 'dismissed' } },
argTypes: {
onDismiss: { action: 'dismissed' },
timeout: { table: { disable: true } },
},
args: {
title: "You've got a temporary notification!",
className: 'w-96',
Expand Down Expand Up @@ -39,3 +42,12 @@ export const NotDismissable: StoryObj<Args> = {
onDismiss: undefined,
},
};

export const AutoDismiss: StoryObj<Args> = {
args: {
...Default.args,
dissmissType: 'auto',
timeout: 500,
onDismiss: () => console.log('trigger onDismiss'),
},
};
8 changes: 0 additions & 8 deletions src/components/ToastNotification/ToastNotification.test.ts

This file was deleted.

26 changes: 26 additions & 0 deletions src/components/ToastNotification/ToastNotification.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { generateSnapshots } from '@chanzuckerberg/story-utils';
import { composeStories, type StoryFile } from '@storybook/testing-react';
import { render, waitFor } from '@testing-library/react';

import React from 'react';
import * as stories from './ToastNotification.stories';

const { AutoDismiss } = composeStories(stories);

const { AutoDismiss: skip, ...staticStories } = stories;

describe('<ToastNotification /> (v2)', () => {
afterEach(() => {
jest.resetAllMocks();
});

generateSnapshots(staticStories as StoryFile);

it('triggers the onDissmiss after a delay', async () => {
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();

render(<AutoDismiss />);

await waitFor(() => expect(consoleSpy).toHaveBeenCalledTimes(1));
});
});
27 changes: 26 additions & 1 deletion src/components/ToastNotification/ToastNotification.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import clsx from 'clsx';
import React from 'react';
import React, { useEffect } from 'react';

import getIconNameFromStatus from '../../util/getIconNameFromStatus-v2';
import type { Status } from '../../util/variant-types';
Expand All @@ -19,7 +19,18 @@ export type ToastNotificationProps = {
* Callback when notification is dismissed. When passed in, renders banner with a close icon in the top right.
*/
onDismiss?: () => void;
/**
* Length of time to wait until `onDismiss` is called
*/
timeout?: number;
// Design API
/**
* Determines whether the toast notification will dismiss on its own, or due to user action. When set to `"auto"`,
* it will dismiss after 8 seconds.
*
* **Default is `"manual"`**.
*/
dissmissType?: 'manual' | 'auto';
/**
* Keyword to characterize the state of the notification
*/
Expand All @@ -37,8 +48,10 @@ export type ToastNotificationProps = {
*/
export const ToastNotification = ({
className,
dissmissType = 'manual',
onDismiss,
status = 'favorable',
timeout = 8000,
title,
...other
}: ToastNotificationProps) => {
Expand All @@ -47,6 +60,18 @@ export const ToastNotification = ({
status && styles[`toast--status-${status}`],
className,
);

useEffect(() => {
const expireId =
dissmissType === 'auto'
? setTimeout(() => {
onDismiss && onDismiss();
}, timeout)
: undefined;

return () => clearTimeout(expireId);
}, [onDismiss, dissmissType, timeout]);

return (
<div className={componentClassName} {...other}>
<Icon
Expand Down

0 comments on commit 8545f14

Please sign in to comment.