Toast

Displays temporary notification messages using Base UI Toast primitives.

Anatomy

Import and set up the toast system:

1import { Toast, toastManager } from '@raystack/apsara'
2
3// Wrap your app with Toast.Provider (once, at root)
4<Toast.Provider position="bottom-right">
5 <App />
6</Toast.Provider>
7
8// Trigger toasts from anywhere
9toastManager.add({ title: 'Hello!', type: 'success' })

API Reference

Toast.Provider

Renders the toast viewport and manages the toast lifecycle. Place once at the root of your app.

Prop

Type

toastManager.add(options)

Creates a new toast and returns its unique ID. The toastManager can be imported and used anywhere — including outside React components (e.g., API interceptors, utility functions).

Prop

Type

createToastManager()

Factory that returns a fresh toast manager. The exported singleton toastManager is one such instance created at module load. Pass a custom manager to <Toast.Provider toastManager={...}> to scope toasts to that provider.

1import { Toast, createToastManager } from '@raystack/apsara'
2
3const manager = createToastManager()
4
5<Toast.Provider toastManager={manager}>
6 <App />
7</Toast.Provider>

The returned object exposes the four manager methods:

Prop

Type

Update options

The update(id, options) method accepts a partial of the toast — every field optional, used to patch an existing toast in place.

Prop

Type

Promise options

The promise(promise, options) method drives a toast through the resolve/reject lifecycle of a Promise.

Prop

Type

useToastManager()

Hook for dispatching toasts from inside a component tree wrapped by <Toast.Provider>. Returns the same methods as createToastManager() — including first-class leadingIcon support — plus a reactive toasts array reflecting the currently-displayed toasts.

1import { useToastManager } from '@raystack/apsara'

The hook is exported as a top-level named export (not as Toast.useToastManager) so React's rules-of-hooks linting recognizes it correctly.

Prop

Type

Toast object

Each entry in toasts is a snapshot of a currently-mounted toast.

Prop

Type

Prefer the singleton toastManager when triggering toasts from non-React code (interceptors, utility functions, event handlers outside the provider). Use useToastManager() inside components when you need access to the live toasts array, or want the dispatch call colocated with the rest of the component's logic.

Examples

Basic Toast

1<Button onClick={() => toastManager.add({ title: "Hello from Apsara!" })}>
2 Show toast
3</Button>

Type Variants

Use the type prop to drive the leading icon color (e.g. green for success, red for error). The toast container itself stays visually neutral regardless of type.

1<Button onClick={() => toastManager.add({ title: "Default toast" })}>
2 Default
3</Button>

With Title and Description

1<Flex gap="medium" wrap="wrap">
2 <Button
3 onClick={() =>
4 toastManager.add({
5 title: "File uploaded",
6 description: "Your document has been uploaded successfully.",
7 type: "success",
8 })
9 }
10 >
11 With description
12 </Button>
13 <Button
14 onClick={() =>
15 toastManager.add({

With Leading Icon

Each toast type ships with a sensible default icon. Pass leadingIcon to override it with any React node, or pass leadingIcon: null to render no icon at all.

1<Flex gap="medium" wrap="wrap">
2 <Button
3 onClick={() =>
4 toastManager.add({
5 title: "Saved successfully",
6 type: "success",
7 leadingIcon: <CheckCircledIcon />,
8 })
9 }
10 >
11 Success with icon
12 </Button>
13 <Button
14 onClick={() =>
15 toastManager.add({

With Action Button

Use actionProps to render an action button inside the toast.

1<Button
2 onClick={() =>
3 toastManager.add({
4 title: "Item deleted",
5 description: "1 item was moved to trash.",
6 actionProps: {
7 children: "Undo",
8 onClick: () =>
9 toastManager.add({ title: "Item restored", type: "success" }),
10 },
11 })
12 }
13>
14 Action toast
15</Button>

Promise Toast

Track an async operation with automatic loading, success, and error states.

1<Button
2 onClick={() => {
3 const promise = new Promise((resolve) => setTimeout(resolve, 2000));
4 toastManager.promise(promise, {
5 loading: "Loading data...",
6 success: "Data loaded successfully!",
7 error: "Failed to load data.",
8 });
9 }}
10>
11 Promise toast
12</Button>

Positioning

Control where toasts appear on screen with the position prop on Toast.Provider.

1(function ToastPreview() {
2 const manager = Toast.createToastManager();
3 return (
4 <Toast.Provider position="top-left" toastManager={manager}>
5 <Flex gap="medium" wrap="wrap">
6 <Button
7 onClick={() =>
8 manager.add({ title: "Top left toast", type: "success" })
9 }
10 >
11 Trigger toast
12 </Button>
13 </Flex>
14 </Toast.Provider>
15 );

Close and Update

Create a toast, then update or close it programmatically using the returned ID.

1(function UpdateToast() {
2 const idRef = React.useRef(null);
3 return (
4 <Flex gap="medium" wrap="wrap">
5 <Button
6 onClick={() => {
7 idRef.current = toastManager.add({
8 title: "Processing...",
9 type: "loading",
10 timeout: 0,
11 });
12 }}
13 >
14 Start processing
15 </Button>

Dispatching from a Component (Hook)

Use useToastManager() inside a component to dispatch toasts and/or read the reactive list of active toasts. The component must be a descendant of <Toast.Provider>.

1(function HookDemo() {
2 // Hook usage lives in an inner component so it runs inside the Provider.
3 function Inner() {
4 const { add, toasts } = useToastManager();
5 return (
6 <Flex direction="column" gap="medium">
7 <Button
8 onClick={() =>
9 add({
10 title: "Triggered via hook",
11 description:
12 "Same leadingIcon-aware API as the singleton manager.",
13 type: "success",
14 })
15 }

Accessibility

  • Uses aria-live regions for screen reader announcements
  • priority: 'high' uses role="alert" (assertive) for urgent notifications
  • priority: 'low' (default) uses role="status" (polite) for non-urgent notifications
  • Close button has aria-label="Close toast"
  • Supports keyboard navigation and Escape to dismiss
  • Swipe-to-dismiss gesture support
  • Respects motion preferences: toast enter/exit motion is enabled only when prefers-reduced-motion: no-preference