Toast

*** Toast는 라이브러리가 아닌 코드를 복사하여 프로젝트에서 직접 사용

Props

Props
Type
Default
Description

id

string

-

토스트 고유 아이디

title

string

-

타이틀

type

-

토스트 타입

Usage

  1. sonner 라이브러리 설치

# pnpm add sonner
  1. /src/app/layout.tsx에 <main> 하단에 Toaster 컴포넌트 추가

/src/app/layout.tsx
import { Toaster } from 'sonner'

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <html lang="en">
      <body>
        ...
        <main>
        
        </main>
        <Toaster position="top-right" />
      </body>
    </html>
}
  1. /src/components/ui에 toast 컴포넌트 파일 추가

import Image from 'next/image'
import { X } from 'lucide-react'
import { toast as sonnerToast } from 'sonner'

interface ToastProps {
  id: string | number
  title: string
  type?: 'normal' | 'success' | 'error'
}

/** I recommend abstracting the toast function
 *  so that you can call it without having to use toast.custom everytime. */
export function toast(toast: Omit<ToastProps, 'id'>) {
  return sonnerToast.custom((id) => (
    <Toast id={id} title={toast.title} type={toast.type} />
  ))
}

/** A fully custom toast that still maintains the animations and interactions. */
function Toast(props: ToastProps) {
  const { title, id, type = 'normal' } = props

  return (
    <div className="flex min-h-16 w-full items-center rounded-lg bg-[#191F28] p-4 shadow-lg ring-1 ring-black/5 md:max-w-[364px]">
      <div className="flex flex-1 items-center gap-3">
        <div className="flex w-full min-w-[244px] gap-2">
          {type === 'error' && (
            <Image
              alt={'icon-error'}
              src={'/images/icon-error.png'}
              width={20}
              height={20}
            />
          )}
          {type === 'success' && (
            <Image
              alt={'icon-success'}
              src={'/images/icon-success.png'}
              width={20}
              height={20}
            />
          )}
          <p className="text-sm font-medium text-white">{title}</p>
        </div>
        <button
          className="rounded text-sm font-semibold"
          onClick={() => {
            sonnerToast.dismiss(id)
          }}
        >
          <X color="#FFFFFF" width={16} height={16} />
        </button>
      </div>
    </div>
  )
}
  1. 실제 토스트를 사용할 컴포넌트에서 toast import하여 사용

import { toast } from '@/src/components/ui'

export function ToastDemo() {
  const sendErrorToast = () => {
    toast({
      title: '필수값을 입력해주세요.',
      type: 'error',
    })
  }
  
  const sendSuccessToast = () => {
    toast({
      title: '등록되었습니다.',
      type: 'success',
    })
  }
  
  return <></>
}

Last updated