Skip to content

Commit

Permalink
feat: create Notification component
Browse files Browse the repository at this point in the history
  • Loading branch information
fa-901 committed Oct 5, 2023
1 parent 3138682 commit 9ee5a31
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import classNames from 'classnames';
import { withThemeByDataAttribute } from '@storybook/addon-themes';
import { SiteProvider } from '../providers/siteProvider';
import { LocaleProvider } from '../providers/localeProvider';
import { NotificationProvider } from '../providers/notificationProvider';
import * as constants from './constants';
import type { Preview, ReactRenderer } from '@storybook/react';

Expand Down Expand Up @@ -30,9 +31,11 @@ const preview: Preview = {
Story => (
<SiteProvider>
<LocaleProvider>
<NotificationProvider>
<div className={rootClasses}>
<Story />
</div>
</NotificationProvider>
</LocaleProvider>
</SiteProvider>
),
Expand Down
18 changes: 18 additions & 0 deletions components/Common/Notification/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.root {
@apply m-6
rounded
border
border-neutral-200
bg-white
px-4
py-3
shadow-lg
dark:border-neutral-800
dark:bg-neutral-900;
}

.message {
@apply font-medium
text-green-600
dark:text-white;
}
37 changes: 37 additions & 0 deletions components/Common/Notification/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { CodeBracketIcon } from '@heroicons/react/24/solid';
import type { Meta as MetaObj, StoryObj } from '@storybook/react';
import { FormattedMessage } from 'react-intl';

import Notification from './index';

type Story = StoryObj<typeof Notification>;
type Meta = MetaObj<typeof Notification>;

export const Default: Story = {
args: {
open: true,
duration: 5000,
children: 'Copied to clipboard!',
},
};

export const TimedNotification: Story = {
args: {
duration: 5000,
children: 'Copied to clipboard!',
},
};

export const WithJSX: Story = {
args: {
open: true,
children: (
<div className="flex items-center gap-3">
<CodeBracketIcon className="h-4 w-4" />
<FormattedMessage id="components.common.codebox.copied" />
</div>
),
},
};

export default { component: Notification } as Meta;
34 changes: 34 additions & 0 deletions components/Common/Notification/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as ToastPrimitive from '@radix-ui/react-toast';
import classNames from 'classnames';
import type { FC } from 'react';

import styles from './index.module.css';

type NotificationProps = {
open?: boolean;
duration?: number;
onChange?: (value: boolean) => void;
children?: React.ReactNode;
className?: string;
};

const Notification: FC<NotificationProps> = ({
open,
duration = 5000,
onChange,
children,
className,
}: NotificationProps) => (
<ToastPrimitive.Root
open={open}
duration={duration}
onOpenChange={onChange}
className={classNames(styles.root, className)}
>
<ToastPrimitive.Title className={styles.message}>
{children}
</ToastPrimitive.Title>
</ToastPrimitive.Root>
);

export default Notification;
9 changes: 9 additions & 0 deletions hooks/useNotification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useContext } from 'react';

import { NotificationDispatch } from '@/providers/notificationProvider';

export const useNotification = () => {
const dispatch = useContext(NotificationDispatch);

return dispatch;
};
1 change: 1 addition & 0 deletions i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"components.pagination.previous": "Older",
"components.common.crossLink.previous": "Prev",
"components.common.crossLink.next": "Next",
"components.common.codebox.copied": "Copied to clipboard!",
"layouts.blogPost.author.byLine": "{author, select, null {} other {By {author}, }}",
"layouts.blogIndex.currentYear": "News from {year}",
"components.api.jsonLink.title": "View as JSON",
Expand Down
59 changes: 59 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@mdx-js/react": "^2.3.0",
"@nodevu/core": "~0.1.0",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-toast": "^1.1.5",
"@types/node": "18.18.3",
"@vcarl/remark-headings": "~0.1.0",
"@vercel/analytics": "^1.0.2",
Expand Down
55 changes: 55 additions & 0 deletions providers/notificationProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as Toast from '@radix-ui/react-toast';
import type {
CSSProperties,
Dispatch,
FC,
PropsWithChildren,
SetStateAction,
} from 'react';
import { createContext, useEffect, useState } from 'react';

import Notification from '@/components/Common/Notification';

const viewportStyles = {
position: 'absolute',
bottom: 0,
right: 0,
} satisfies CSSProperties;

type NotificationContextType = {
message: string | JSX.Element;
duration: number;
} | null;

const NotificationContext = createContext<NotificationContextType>(null);

export const NotificationDispatch = createContext<
Dispatch<SetStateAction<NotificationContextType>>
>(() => {});

export const NotificationProvider: FC<PropsWithChildren> = ({ children }) => {
const [notification, dispatch] = useState<NotificationContextType>(null);

useEffect(() => {
const timeout = setTimeout(() => dispatch(null), notification?.duration);

return () => clearTimeout(timeout);
}, [notification]);

return (
<NotificationContext.Provider value={notification}>
<NotificationDispatch.Provider value={dispatch}>
<Toast.Provider>
{children}

{notification && (
<Notification duration={notification.duration}>
{notification.message}
</Notification>
)}
<Toast.Viewport style={viewportStyles} />
</Toast.Provider>
</NotificationDispatch.Provider>
</NotificationContext.Provider>
);
};

0 comments on commit 9ee5a31

Please sign in to comment.