From c01943f88c7ba5b9d52bef9bdecc42e74177e2f5 Mon Sep 17 00:00:00 2001 From: Hee Suh <53266682+hee-suh@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:05:37 +0900 Subject: [PATCH] feat: add toast component (#38) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add toast component * refactor: update toast css * fix: fix merge conflict * fix: fix toast exit animation https://github.com/timolins/react-hot-toast/issues/165#issuecomment-1113853475 * fix: update toast position * fix: fix translateY causing scrollbar - width를 유연하게 조절하기 위해서 toast container의 position을 'sticky'로 설정하니까, translateY 애니메이션으로 인해 스크롤바가 잠시 표시되는 이슈 발생 - toast의 maxWidth를 최대 viewport width - 2 * marginX로 설정해서 임시 해결 --- package-lock.json | 25 +++++++++- package.json | 1 + src/app/layout.tsx | 2 + src/components/common/custom-toast.tsx | 68 ++++++++++++++++++++++++++ tailwind.config.ts | 23 +++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/components/common/custom-toast.tsx diff --git a/package-lock.json b/package-lock.json index 9bcd35e8..8d6a6b2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "next": "14.2.3", "react": "^18", "react-dom": "^18", + "react-hot-toast": "^2.4.1", "react-qrcode-logo": "^3.0.0", "tailwind-merge": "^2.3.0" }, @@ -10177,7 +10178,6 @@ }, "node_modules/csstype": { "version": "3.1.3", - "dev": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -12820,6 +12820,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz", + "integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.0.1", "dev": true, @@ -16344,6 +16352,21 @@ "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", "dev": true }, + "node_modules/react-hot-toast": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", + "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", + "dependencies": { + "goober": "^2.1.10" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-is": { "version": "16.13.1", "license": "MIT" diff --git a/package.json b/package.json index a46f3df9..84d3b80b 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "next": "14.2.3", "react": "^18", "react-dom": "^18", + "react-hot-toast": "^2.4.1", "react-qrcode-logo": "^3.0.0", "tailwind-merge": "^2.3.0" }, diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ee31058c..6f5a68d6 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,6 +4,7 @@ import type { Metadata } from 'next' import Script from 'next/script' import './globals.css' +import { CustomToaster } from '@/components/common/custom-toast' import { pretendard } from '@/styles/fonts' export const metadata: Metadata = { @@ -29,6 +30,7 @@ export default function RootLayout({ />
{children} +
diff --git a/src/components/common/custom-toast.tsx b/src/components/common/custom-toast.tsx new file mode 100644 index 00000000..99ed8d12 --- /dev/null +++ b/src/components/common/custom-toast.tsx @@ -0,0 +1,68 @@ +import toast, { Toaster, type ToastOptions } from 'react-hot-toast' +import Icon from './icon' +import Typography from './typography' + +type ToastType = 'success' | 'error' + +const toastCustom = ({ + type, + message, + options, +}: { + type: ToastType + message: string + options?: ToastOptions +}) => { + toast.custom( + (t) => ( +
+ {type === 'success' ? ( + + ) : ( + + )} + + {message} + +
+ ), + options, + ) +} + +const notify = { + success: (message: string, options?: ToastOptions) => + toastCustom({ + type: 'success', + message, + options: { id: 'toast-success', ...options }, + }), + error: (message: string, options?: ToastOptions) => + toastCustom({ + type: 'error', + message, + options: { id: 'toast-error', ...options }, + }), +} + +const CustomToaster = () => { + return ( + + ) +} + +export { CustomToaster, notify } diff --git a/tailwind.config.ts b/tailwind.config.ts index 507bcb0e..192d6a15 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -174,6 +174,29 @@ const config: Config = { borderRadius: { '3xl': '20px', }, + keyframes: { + enter: { + '0%': { + transform: 'translateY(20px)', + }, + '100%': { + transform: 'translateY(0)', + }, + }, + leave: { + '0%': { + transform: 'translateY(0)', + }, + '100%': { + transform: 'translateY(20px)', + opacity: '0', + }, + }, + }, + animation: { + enter: 'enter 300ms ease-out', + leave: 'leave 300ms ease-in forwards', + }, }, }, plugins: [],