Light

Sonner (Toast)

An opinionated toast component for React.

Spec · from metadata

When to use

  • Success/error/info notifications after user actions
  • Non-blocking feedback messages (saved, deleted, etc.)
  • Loading state notifications with async updates

When not to use

  • Blocking confirmation — use AlertDialog instead
  • Inline form errors — use FieldError instead
  • Persistent alerts — use Alert component instead

Anti-patterns

Avoid// On every page:
<Toaster />
Prefer// Once in root layout:
<Toaster />

Toaster should be rendered once at the root. Multiple instances cause duplicate toasts.

Avoidimport { Toaster } from "@timelycare/helix-ui"
Toaster.success("Done")
Preferimport { toast } from "sonner"
toast.success("Done")

Toaster is the render component. Use the toast() function from sonner to trigger notifications.

Accessibility

  • Screen readersonner uses aria-live regions for toast announcements. Each toast type has a distinct icon for visual differentiation.
  • ContrastUses --normal-bg (card), --normal-text (card-foreground), --normal-border (border) tokens.

Token bindings

TokenCategoryUsage
cardcolorToast background (--normal-bg)
card-foregroundcolorToast text (--normal-text)
bordercolorToast border (--normal-border)
radiusradiusToast border radius (--border-radius)

Import

import { toast } from "sonner"
import { Toaster } from "@timelycare/helix-ui"

Setup

// In layout or root component
<Toaster />

Structure

PartTailwind
Containerbg-popover border border-border rounded-md p-4 shadow-lg gap-2 flex items-center
Titletext-sm font-semibold leading-normal text-popover-foreground
Descriptiontext-sm font-normal leading-normal text-muted-foreground
Text wrapperflex flex-col gap-0.5 (2px gap)
Iconsize-5 text-foreground (20px)

States

StateImplementation
DefaultStandard toast appearance
Focusring-2 ring-ring ring-offset-2

Toast Types

TypeIconMethod
DefaultNonetoast("Message")
SuccessCheckmark (✓)toast.success("Message")
InfoInfo circle (i)toast.info("Message")
WarningTriangle (⚠)toast.warning("Message")
ErrorError circle (!)toast.error("Message")
LoadingSpinnertoast.loading("Message")

Action Buttons

TypeTailwindUse For
Defaulth-6 px-2 rounded bg-primary text-xs font-semibold text-primary-foreground shadow-xsPrimary action (Undo)
Secondaryh-6 px-2 rounded bg-secondary text-xs font-semibold text-secondary-foregroundCancel, dismiss

Common Patterns

Simple Toast

toast("Event has been created")

With Description

toast("Event has been created", {
  description: "Monday, January 3rd at 6:00pm",
})

Success with Action

toast.success("Event has been created", {
  description: "Sunday, December 03, 2023 at 9:00 AM",
  action: {
    label: "Undo",
    onClick: () => console.log("Undo"),
  },
})

With Cancel

toast("Event has been created", {
  cancel: {
    label: "Cancel",
    onClick: () => console.log("Cancel"),
  },
})

Error Toast

toast.error("Event has not been created")

Warning Toast

toast.warning("Event start time cannot be earlier than 8am")

Info Toast

toast.info("Be at the area 10 minutes before the event time")

Loading → Success

const toastId = toast.loading("Loading...")

// On completion
toast.success("Done!", { id: toastId })

Positioning

<Toaster position="bottom-right" />
PositionValue
Bottom Rightbottom-right (default)
Bottom Centerbottom-center
Bottom Leftbottom-left
Top Righttop-right
Top Centertop-center
Top Lefttop-left

Accessibility

  • Built on sonner library — manages toast announcements
  • Screen reader: toasts announced via aria-live region automatically
  • Keyboard: Tab to focus toast actions, Escape to dismiss
  • Auto-dismiss with configurable timeout
  • Ensure action buttons within toasts are keyboard accessible

Gotchas

ProblemSolution
Toast not showingEnsure <Toaster /> is in layout
Wrong positionSet position prop on <Toaster />
Action not clickablePass onClick in action object
Update existing toastPass same id to new toast call
Dismiss programmaticallytoast.dismiss(toastId) or toast.dismiss() for all

See Also


Last updated: February 9, 2026