Sonner

Usage

'use client'
 
import { Button } from '@jamie/ui/button'
import { toast } from 'sonner'
 
export function SonnerDemo() {
  return (
    <Button variant="outline" onClick={() => toast('Meeting has been recorded')}>
      Show toast
    </Button>
  )
}

Types

Use toast.success(), toast.error(), toast.info(), and toast.warning() for semantic variants.

'use client'
 
import { Button } from '@jamie/ui/button'
import { toast } from 'sonner'
 
export function SonnerTypesDemo() {
  return (
    <div className="flex flex-wrap gap-2">
      <Button variant="outline" onClick={() => toast('Meeting has been recorded')}>
        Default
      </Button>
      <Button variant="outline" onClick={() => toast.success('Meeting summary generated')}>
        Success
      </Button>
      <Button variant="outline" onClick={() => toast.error('Transcript processing failed')}>
        Error
      </Button>
      <Button variant="outline" onClick={() => toast.info('Your transcript will be ready shortly')}>
        Info
      </Button>
      <Button variant="outline" onClick={() => toast.warning('Storage limit approaching')}>
        Warning
      </Button>
    </div>
  )
}

Description

Pass a description option to add secondary text below the title.

'use client'
 
import { Button } from '@jamie/ui/button'
import { toast } from 'sonner'
 
export function SonnerDescriptionDemo() {
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast.success('Meeting summary generated', {
          description: 'Q3 Earnings Review — 12 action items extracted.'
        })
      }
    >
      With description
    </Button>
  )
}

Action

Add an action with a label and onClick callback to provide an undo or follow-up.

'use client'
 
import { Button } from '@jamie/ui/button'
import { toast } from 'sonner'
 
export function SonnerActionDemo() {
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast('Meeting recap sent to team', {
          action: {
            label: 'Undo',
            onClick: () => toast('Recap sending cancelled')
          }
        })
      }
    >
      With action
    </Button>
  )
}

Promise

Use toast.promise() to show loading, success, and error states for async operations.

'use client'
 
import { Button } from '@jamie/ui/button'
import { toast } from 'sonner'
 
export function SonnerPromiseDemo() {
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast.promise(
          new Promise<{ summary: string }>((resolve) =>
            setTimeout(() => resolve({ summary: 'Q3 Earnings Review' }), 2000)
          ),
          {
            loading: 'Generating meeting summary...',
            success: (data) => `Summary ready: ${data.summary}`,
            error: 'Failed to generate summary'
          }
        )
      }
    >
      With promise
    </Button>
  )
}

Custom

Use toast.custom() to render fully custom toast content.

'use client'
 
import { Button } from '@jamie/ui/button'
import { toast } from 'sonner'
 
export function SonnerCustomDemo() {
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast.custom(() => (
          <div className="w-[356px] rounded-lg border bg-background p-4 shadow-lg">
            <p className="text-sm font-medium">New meeting recorded</p>
            <p className="mt-1 text-xs text-muted-foreground">
              Budget Planning Sync — 30 min · 5 action items
            </p>
            <div className="mt-3 flex gap-2">
              <Button size="sm" variant="outline" onClick={() => toast.dismiss()}>
                Dismiss
              </Button>
              <Button size="sm">View summary</Button>
            </div>
          </div>
        ))
      }
    >
      Custom toast
    </Button>
  )
}