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>
)
}