Toast
Low-level toast markup kept for compatibility.
<%= render(Shadcn::ToastComponent.new) do |toast| %>
<% toast.with_title { "Scheduled: Catch up" } %>
<% toast.with_description { "Friday, February 10, 2023 at 5:57 PM" } %>
<% end %>
Installation
For new toast work, install Sonner. Install Toast only when you need the lower-level compatibility component.
Add the component to your project:
rails generate shadcn:add toast
Usage
Toast renders individual notification markup and is kept for apps that already depend on it.
New code should use Sonner,
which provides the recommended toast() API,
stacking, positions, swipe dismissal, and Turbo Stream support.
<%= render(Shadcn::ToastComponent.new) do |toast| %>
<% toast.with_title { "Scheduled: Catch up" } %>
<% toast.with_description { "Friday, February 10, 2023 at 5:57 PM" } %>
<% end %>
Examples
Simple
A minimal toast with just a description.
With Title
Include both a title and description for more context.
With Action
Add an action button to allow users to respond to the notification.
The alt_text parameter
is required for accessibility.
Destructive
Use the destructive variant for error messages or critical notifications.
Custom Duration
Control how long the toast is displayed before auto-dismissing. Duration is specified in milliseconds.
No Auto-dismiss
Set duration: 0
to prevent automatic dismissal. The user must manually close the toast.
All Variants
<div class="space-y-3">
<%= render Shadcn::Toast.new do |toast| %>
<% toast.with_title { "Success" } %>
<% toast.with_description { "Your changes have been saved." } %>
<% end %>
<%= render Shadcn::Toast.new(variant: :destructive) do |toast| %>
<% toast.with_title { "Error" } %>
<% toast.with_description { "Something went wrong." } %>
<% end %>
</div>
With Description
<%= render(Shadcn::ToastComponent.new) do |toast| %>
<% toast.with_title { "Scheduled: Catch up" } %>
<% toast.with_description { "Friday, February 10, 2023 at 5:57 PM" } %>
<% end %>
Destructive with Action
<%= render(Shadcn::ToastComponent.new) do |toast| %>
<% toast.with_title { "Scheduled: Catch up" } %>
<% toast.with_description { "Friday, February 10, 2023 at 5:57 PM" } %>
<% end %>
Success
<%= render(Shadcn::ToastComponent.new) do |toast| %>
<% toast.with_title { "Success!" } %>
<% toast.with_description { "Your changes have been saved successfully." } %>
<% end %>
Warning
<%= render Shadcn::Toast.new do |toast| %>
<% toast.with_title { "Warning" } %>
<% toast.with_description { "Your session will expire soon." } %>
<% toast.with_action(alt_text: "Extend session") do %>
<%= render Shadcn::Button.new(variant: :outline, class_name: "h-8 px-3 text-xs") { "Extend" } %>
<% end %>
<% end %>
Long Duration
<%= render(Shadcn::ToastComponent.new) do |toast| %>
<% toast.with_title { "Scheduled: Catch up" } %>
<% toast.with_description { "Friday, February 10, 2023 at 5:57 PM" } %>
<% end %>
No Auto Dismiss
<%= render(Shadcn::ToastComponent.new(duration: 0)) do |toast| %>
<% toast.with_title { "Manual dismiss required" } %>
<% toast.with_description { "This toast will not auto-dismiss. Click the X to close." } %>
<% end %>
Multiple Toasts
<%= render(Shadcn::ToastComponent.new) do |toast| %>
<% toast.with_title { "Scheduled: Catch up" } %>
<% toast.with_description { "Friday, February 10, 2023 at 5:57 PM" } %>
<% end %>
API Reference
ToastComponent
| Prop | Type | Default | Description |
|---|---|---|---|
| variant |
Symbol
|
:default
|
Toast style variant (:default, :destructive) |
| duration |
Integer
|
5000
|
Auto-dismiss duration in milliseconds (0 for no auto-dismiss) |
| open |
Boolean
|
true
|
Whether the toast is visible |
| class_name |
String
|
nil
|
Additional CSS classes to apply |
ToastComponent Slots
| Slot | Props | Description |
|---|---|---|
| with_title | - | Toast title (bold heading) |
| with_description | - | Toast description text |
| with_action | alt_text: (required) |
Action button (requires alt_text for accessibility) |
| with_close | - | Custom close button (default provided) |
ToastViewportComponent
Container component for toasts, positioned at bottom-right on desktop and top on mobile.
| Prop | Type | Default | Description |
|---|---|---|---|
| class_name |
String
|
nil
|
Additional CSS classes to apply |
Stimulus Controller
The Toast component uses a Stimulus controller (shadcn--toast)
for auto-dismiss functionality and close button interaction.
Values
| Value | Type | Default | Description |
|---|---|---|---|
| duration | Number | 5000 | Auto-dismiss time in milliseconds |
| open | Boolean | true | Whether toast is visible |
Actions
| Action | Description |
|---|---|
| close | Manually close the toast |
| pause | Pause auto-dismiss timer (useful on hover) |
| resume | Resume auto-dismiss timer |
Events
| Event | Description |
|---|---|
| shadcn--toast:closed | Dispatched when toast is closed and removed from DOM |
Integration Example
Here's an example of dynamically adding toasts using Turbo Streams or JavaScript:
// Add a toast dynamically
function addToast(title, description, variant = 'default') {
const viewport = document.querySelector('[data-shadcn--toaster-target="viewport"]');
const toast = document.createElement('li');
toast.setAttribute('data-controller', 'shadcn--toast');
toast.setAttribute('data-shadcn--toast-duration-value', '5000');
toast.setAttribute('data-shadcn--toast-open-value', 'true');
toast.setAttribute('data-state', 'open');
toast.setAttribute('role', 'status');
toast.setAttribute('aria-live', 'polite');
const variantClasses = variant === 'destructive'
? 'destructive group border-destructive bg-destructive text-destructive-foreground'
: 'border bg-background text-foreground';
toast.className = `group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all ${variantClasses}`;
toast.innerHTML = `
<div class="grid gap-1">
${title ? `<div class="text-sm font-semibold [&+div]:text-xs">${title}</div>` : ''}
<div class="text-sm opacity-90">${description}</div>
</div>
<button type="button" class="absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100" data-action="click->shadcn--toast#close" aria-label="Close">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" class="h-4 w-4">
<path d="M18 6 6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
`;
viewport.appendChild(toast);
}
Accessibility
- Uses
role="status"for proper screen reader announcement - Has
aria-live="polite"to announce changes without interrupting - Close button has
aria-label="Close"for screen readers - Action buttons require
alt_textparameter foraria-label - Auto-dismiss timer can be paused on hover for users who need more time to read
- All interactive elements are keyboard accessible
- Color is not the only indicator - text content provides meaning
On This Page