Toast

Lightweight context-based toast system. No external library. 4 types, auto-dismiss, slide-up animation, accessible.

Setup

ToastProvider wraps the app in app/layout.tsx. ToastContainer renders the toasts. Both are already set up in the scaffold:

app/layout.tsx
import { ToastProvider } from '@/hooks/useToast'
import { ToastContainer } from '@/components/ui/Toast'

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <ToastProvider>
          {children}
          <ToastContainer />
        </ToastProvider>
      </body>
    </html>
  )
}

Using useToast

'use client'
import { useToast } from '@/hooks/useToast'

export function SomeComponent() {
  const { toast, dismiss } = useToast()

  function handleAction() {
    toast('success', 'Changes saved successfully.')
    toast('error', 'Something went wrong.')
    toast('info', 'Your session expires in 5 minutes.')
    toast('warning', 'This action cannot be undone.', 6000)
    //                                                  ^^^^ custom duration ms
  }
}

Toast types

TypeIconUse case
successCheckCircleSuccessful operations - saved, verified, updated
errorXCircleFailures - server errors, validation failures
infoInfoNeutral information - session warnings, tips
warningAlertTriangleCaution - irreversible actions, expiry notices

ToastContainer

ToastContainer renders a fixed stack of toasts:

  • Position: bottom-right on desktop, bottom-center on mobile
  • Max 5 toasts visible - oldest removed when limit exceeded
  • Each toast: slide-up + fade-in on appear, reverse on remove
  • Close button on each toast
  • role=alert aria-live=polite for screen readers
  • Default duration: 4000ms. Pass a 4th arg to toast() to override.

Customising

To change default duration, update the DEFAULT_DURATION constant in hooks/useToast.tsx. To change position, update ToastContainer's positioning classes in components/ui/Toast.tsx.