Toast

A toast notification component with stacking, hover pause, and progress indicators

Installation

Terminal
pnpm add @choice-ui/toast

Import

Component.tsx
import { Toaster, type ToasterProps, toast, type ToastOptions, type ToastData, type ToastType, type ToastVariant, type ToastPosition } from "@choice-ui/toast"

Types

Toast notifications provide non-blocking feedback to users about actions, events, or system status. They appear temporarily and can be dismissed automatically or manually.
## Key Features
- **No Provider Required**: Toast works without wrapping your app in a context provider - **Multiple Instances**: Support multiple Toaster components with unique IDs - **Rich Content**: Support for titles, descriptions, icons, and action buttons - **Flexible Positioning**: Six position options (top/bottom × left/center/right) - **Auto-dismiss**: Configurable duration with pause-on-hover support - **Stacking**: Multiple toasts stack elegantly with expand-on-hover
## Basic Usage
```tsx import { Toaster, toast } from '@choice-ui/react' // 1. Place a Toaster component with a unique ID <Toaster id="my-app" /> // 2. Trigger toasts from anywhere using toast.use(id) toast.use('my-app').success('Changes saved!') toast.use('my-app').error('Something went wrong') ```
## Toast Types
Toast provides six semantic types, each with a distinct icon and purpose:
- **default**: General notifications without a specific semantic meaning - **info**: Informational messages that provide helpful context - **success**: Confirmation that an action completed successfully - **warning**: Alerts about potential issues that need attention - **error**: Critical errors that require user awareness - **loading**: Indicates an ongoing process (does not auto-dismiss)
Each type automatically displays an appropriate icon. The `loading` type shows an animated spinner and will not auto-dismiss until manually closed or updated via the promise API.

Click each button to see the corresponding toast type. Each type has a unique icon and semantic meaning.

Title Only

Toasts can display just a title without a description for brief, simple messages. This is ideal for quick confirmations like "Saved!", "Copied!", or "Deleted!".
Use title-only toasts when:
- The message is self-explanatory - You want minimal visual disruption - The action result is obvious from context

Simple toasts with just a title are perfect for quick, self-explanatory notifications.

With Description

Add a `description` to provide additional context or details about the notification. Descriptions appear below the title in a smaller, muted style.
Best practices:
- Keep descriptions concise (1-2 sentences) - Provide actionable information when possible - Use for context that isn't obvious from the title alone

Descriptions provide additional context below the title. Use them for details that help users understand what happened or what to do next.

With Action

Toasts can include action and cancel buttons for user interaction.
- **action**: Primary action button (e.g., "Undo", "View", "Retry") - **cancel**: Secondary dismiss button (e.g., "Dismiss", "Cancel")
Action buttons are useful for:
- Undo operations (delete, archive, etc.) - Navigation to related content - Retry failed operations - Confirming or dismissing notifications
Both buttons automatically close the toast after being clicked.

Add interactive buttons to toasts for undo actions, navigation, or explicit dismissal.

Promise Toast

The `toast.promise()` API automatically manages loading, success, and error states for asynchronous operations. It shows a loading toast while the promise is pending, then updates to success or error based on the result.
```tsx toast.use('my-app').promise( fetchData(), { loading: 'Fetching data...', success: 'Data loaded!', error: (err) => `Failed: ${err.message}`, } ) ```
Features:
- Loading state with spinner (no auto-dismiss) - Automatic transition to success/error - Dynamic messages based on promise result

Promise toasts automatically handle loading, success, and error states. The toast updates when the promise resolves or rejects.

Dismiss Toast

Toasts can be dismissed programmatically using:
- `toast.use(id).dismiss(toastId)` - Dismiss a specific toast by its ID - `toast.use(id).dismissAll()` - Dismiss all toasts in a Toaster
Each `toast.use(id)()` call returns the toast's unique ID, which you can store and use later to dismiss that specific toast.
Use cases:
- Dismiss related toasts when navigating away - Clear all notifications on logout - Remove outdated notifications when new data arrives

Store toast IDs to dismiss them programmatically. Use dismissAll() to clear all toasts at once.

Active toasts: 0

Duration

Control how long toasts remain visible with the `duration` option (in milliseconds).
- **Default**: 5000ms (5 seconds) - **Custom**: Any positive number - **Persistent**: Set `duration: 0` or `duration: Infinity` to disable auto-dismiss
Guidelines:
- Short messages: 2-3 seconds - Standard notifications: 4-5 seconds - Important information: 7-10 seconds - Critical alerts: `duration: 0` or `Infinity` (manual dismiss only)
Note: `loading` type toasts never auto-dismiss regardless of duration setting.

Set custom durations for different notification types. Use duration: 0 for persistent toasts that require manual dismissal.

Infinite Duration

Set `duration: Infinity` for toasts that should never auto-dismiss. This is useful for critical notifications that require explicit user acknowledgment.
Use cases:
- Important security alerts (password changes, session expiry) - Critical errors that need user action - Confirmations that shouldn't disappear automatically
Note: Always provide a way to dismiss (action button or cancel) for infinite duration toasts.

Use duration: Infinity for toasts that require explicit user dismissal. Always provide a close action.

With Progress Bar

Enable `showProgress` on the Toaster to display a countdown indicator on each toast. The progress bar shows the remaining time before auto-dismiss and pauses when hovering.
Features:
- Visual countdown indicator - Pauses on hover (timer also pauses) - Not shown for `loading` type, `duration: 0`, or `duration: Infinity` toasts - Styled differently for default and compact layouts - Per-toast override via `progress` option
The progress bar helps users understand how long a notification will remain visible and gives them time to read or interact with it.

Enable showProgress on Toaster, or use progress option per toast. Hover over the toast to pause the timer.

Stacking

Multiple toasts stack elegantly with a subtle offset and fade effect. By default, only the most recent 3 toasts are visible.
Interaction:
- **Collapsed**: Toasts stack with visual offset indicating depth - **Expanded**: Hover over the stack to expand and view all toasts - **Dismiss**: Swipe or click to dismiss individual toasts
Configure with `visibleToasts` prop (default: 3) to control how many toasts are visible at once.

Multiple toasts stack with a subtle offset. Hover over the stack to expand and view all notifications. The default limit is 3 visible toasts.

Variant

The `variant` option controls the background color scheme of individual toasts. This is separate from `type` which controls the icon.
Available variants:
- **default**: Dark neutral background (gray) - **accent**: Blue/brand color background - **success**: Green background - **warning**: Yellow/amber background (dark text) - **error**: Red background - **assistive**: Pink/magenta background
Use variants to:
- Match your application's color scheme - Emphasize certain notifications - Create visual hierarchy among notifications

Use the variant option to customize the background color scheme of each toast independently from its type.

Compact Layout

Set `layout="compact"` on the Toaster for a minimal, single-line toast style. Compact toasts are smaller (40px height) and don't show descriptions.
Best for:
- Brief confirmations ("Saved", "Copied", "Sent") - High-frequency notifications - Mobile or space-constrained UIs - Non-critical status updates
Features:
- Smaller, pill-shaped appearance - Dynamic width based on content - Title only (descriptions are hidden) - Progress bar fills the background

Use layout="compact" for minimal, single-line toasts. Ideal for brief confirmations and high-frequency notifications.

Position

Control where toasts appear on screen with the `position` prop on Toaster.
Available positions:
- `top-left`, `top-center`, `top-right` - `bottom-left`, `bottom-center`, `bottom-right` (default)
The `offset` prop controls the distance from viewport edges (default: 16px).
Swipe direction adapts to position:
- Corner positions: Swipe left/right to dismiss - Center positions: Swipe up/down to dismiss

Click each button to see a toast in that position. The swipe direction to dismiss adapts based on position (horizontal for corners, vertical for center).

Multiple Toasters

You can have multiple Toaster components with different IDs and configurations. Use `toast.use(id)` to target a specific Toaster.
Use cases:
- Different positions for different notification types - Separate system notifications from user actions - Different styling or behavior per area
Each Toaster maintains its own toast queue and state independently.

Multiple Toaster instances with different IDs operate independently. Use toast.use("id") to target specific instances.

System Notifications (Top-Left)

For system-level alerts and background processes

User Actions (Bottom-Right)

For user-triggered action confirmations

Html Content

Both `title` and `description` automatically detect and render HTML content. When a string contains HTML tags (like `<b>`, `<strong>`, `<span>`), it will be rendered as HTML. Plain strings and React nodes are rendered normally.
Supported HTML:
- `<strong>`, `<b>` for bold text - `<code>` for inline code - `<span>` with classes for colored text - Any inline HTML elements with Tailwind classes
**Security Note**: Only use HTML strings with trusted content. User-generated content should be sanitized before rendering.

Both title and description automatically detect HTML tags and render them appropriately. Plain strings are rendered as text, while strings with HTML tags are rendered as HTML.

Custom Slots

Use compound components to fully customize toast appearance:
- `Toaster.Item` - Wrapper with custom className/style - `Toaster.Icon` - Custom icon renderer `(type, defaultIcon) => ReactNode` - `Toaster.Title` - Custom title styling - `Toaster.Description` - Custom description styling - `Toaster.Actions` - Custom action buttons `(action, cancel, close) => ReactNode`
This enables complete control over toast appearance while maintaining the toast's behavior and state management.

Use compound components to customize each part of the toast. This example uses emoji icons and custom button styling.

Use Effect

This example demonstrates using toast within React effects for:
- Triggering toasts based on state changes - Proper cleanup when components unmount - Managing toast state alongside component state
Key patterns:
- Store toast IDs for later dismissal - Clean up toasts on unmount - Handle action callbacks that update component state

This example shows proper toast integration with React effects, including state management and cleanup.

Status: Monitoring inactive

Toast: Hidden

Action count: 0

Playground

Interactive playground to test all Toast features and configurations. Experiment with different combinations of:
- **Position**: Where toasts appear on screen - **Variant**: Background color scheme - **Type**: Semantic type with corresponding icon - **Layout**: Default (full) or compact style - **Progress**: Show/hide countdown indicator - **Actions**: Add action and cancel buttons - **Content**: Adjust title and description length - **Offset**: Distance from viewport edges

Position

Variant

Type

Layout

Title Length

Use arrow keys to navigate between options

Description Length

Use arrow keys to navigate between options
Offset: 16px

API reference

ToasterPropsTypeDefault
id
string
|
undefined
"default"
position
undefined
|
"top-left"
|
"top-center"
|
"top-right"
|
"bottom-left"
|
"bottom-center"
|
"bottom-right"
"bottom-right"
container
HTMLElement
|
null
|
undefined
-
label
string
|
undefined
"Notifications"
portal
boolean
|
undefined
true
offset
number
|
undefined
16
duration
number
|
undefined
5000
visibleToasts
number
|
undefined
3
className
string
|
undefined
-
children
ReactNode -
showProgress
boolean
|
undefined
false
layout
undefined
|
"default"
|
"compact"
"default"
ref
((instance: HTMLDivElement
|
null) => void)
|
RefObject<HTMLDivElement>
|
null
|
undefined
-