Toast
Notification stack from sonner, unstyled, with the tokens left to you
import { Toaster, toast, useSonner } from "@nyte-ai/ui/sonner";Transient notifications. @nyte-ai/ui/sonner re-exports sonner,
so sonner owns the lifecycle and the API below is sonner's.
No Nyte styling here. Pass toastOptions={{ unstyled: true }} to
Toaster and supply your own classes.
Usage
- Mount
Toasternear the root of the app. One unnamed toaster renders every toast. Give it anidand route toasts to it withtoasterIdwhen you need more than one. - Call
toastfrom anywhere, including outside React. It is a plain function, not a hook. - Give a repeated notification a stable
idso a second call updates the open toast instead of stacking another one. - Every call that opens a toast returns its id. Pass it to
toast.dismissto close that one, or calltoast.dismiss()with no argument to close all of them.
Exports
| Export | Kind | Description |
|---|---|---|
Toaster | component | The list that renders the open toasts. |
toast | function | Opens a toast. Also carries the variant and control methods. |
useSonner | hook | Returns { toasts }, the currently open toasts. |
ExternalToast | type | The options object every toast.* call takes. |
ToasterProps | type | The props of Toaster. |
Examples
Mounting the toaster
<Toaster
position="bottom-right"
offset={16}
gap={8}
expand
closeButton
containerAriaLabel="Notifications"
icons={{ success: <CheckIcon />, error: <WarningIcon />, close: <XIcon /> }}
toastOptions={{
unstyled: true,
closeButtonAriaLabel: "Dismiss notification",
classNames: {
toast: styles.toast,
title: styles.title,
description: styles.description,
actionButton: styles.action,
closeButton: styles.close,
},
}}
/>Opening a toast
toast("Workspace saved");
toast.success("3 chats archived");
toast.error("Could not reach the server", { description: error.message });
toast.warning("This model is deprecated");An action, and undo
toast.success("3 chats archived", {
id: "archive",
action: { label: "Undo", onClick: () => restore() },
onAutoClose: () => commit(),
});action and cancel take { label, onClick } or a React node when you want to render the button
yourself.
Replacing an open toast
The same id updates the open toast in place.
toast.success(`${count} chats archived`, { id: "archive" });A pending operation
toast.promise(save(), {
loading: "Saving",
success: "Saved",
error: (err) => err.message,
});Reading the open toasts
const { toasts } = useSonner();Props
The API below is sonner's.
toast
| Call | Returns | Description |
|---|---|---|
toast(message, data?) | string | number | A default toast. |
toast.message(message, data?) | string | number | Same as calling toast directly. |
toast.success(message, data?) | string | number | Success variant. |
toast.info(message, data?) | string | number | Info variant. |
toast.warning(message, data?) | string | number | Warning variant. |
toast.error(message, data?) | string | number | Error variant. |
toast.loading(message, data?) | string | number | Loading variant. Never auto-closes. |
toast.custom(jsx, data?) | string | number | Renders your own element. jsx receives the toast id. |
toast.promise(promise, data) | id with unwrap() | Swaps through loading, success, and error. |
toast.dismiss(id?) | string | number | Closes one toast, or all of them with no argument. |
toast.getToasts() | (ToastT | ToastToDismiss)[] | The toasts that are open now. |
toast.getHistory() | (ToastT | ToastToDismiss)[] | Open and dismissed toasts. Dismissed ones drop past 100. |
message is a React node or a function returning one. data is ExternalToast.
ExternalToast
| Prop | Type | Description |
|---|---|---|
id | number | string | Stable identity. A second call with the same id updates in place. |
description | React.ReactNode | (() => React.ReactNode) | Second line under the title. |
duration | number | Milliseconds before it closes on its own. |
icon | React.ReactNode | Overrides the variant icon for this toast. |
action | { label, onClick, actionButtonStyle? } | React.ReactNode | Trailing button. |
cancel | { label, onClick, actionButtonStyle? } | React.ReactNode | Dismiss button beside the action. |
dismissible | boolean | Whether the user can swipe it away. Defaults to true. |
closeButton | boolean | Shows the close button for this toast. |
onDismiss | (toast: ToastT) => void | Fires when the user closes it. |
onAutoClose | (toast: ToastT) => void | Fires when the duration runs out. |
position | Position | Overrides the toaster position for this toast. |
richColors | boolean | Variant-tinted background. |
invert | boolean | Inverts the theme for this toast. |
unstyled | boolean | Drops sonner's own toast CSS. |
className | string | Class on the toast element. |
classNames | ToastClassnames | Per-part classes. |
descriptionClassName | string | Class on the description. |
style | React.CSSProperties | Inline style on the toast. |
actionButtonStyle | React.CSSProperties | Inline style on the action button. |
cancelButtonStyle | React.CSSProperties | Inline style on the cancel button. |
toasterId | string | Routes the toast to a specific Toaster. |
testId | string | Sets data-testid on the toast element. |
ToasterProps
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | Names this toaster, for toasterId on a toast. | |
position | Position | "bottom-right" | Corner the stack grows from. |
theme | "light" | "dark" | "system" | "light" | Color scheme sonner applies. |
offset | Offset | Distance from the viewport edge. | |
mobileOffset | Offset | Same, at small viewports. | |
gap | number | 14 | Space between stacked toasts. |
expand | boolean | Shows the stack expanded instead of collapsed. | |
visibleToasts | number | 3 | How many toasts render at once. |
duration | number | 4000 | Default milliseconds for every toast. |
closeButton | boolean | Shows a close button on every toast. | |
richColors | boolean | Variant-tinted backgrounds. | |
invert | boolean | Inverts the theme. | |
icons | ToastIcons | Your icons for success, info, warning, error, loading, and close. | |
toastOptions | ToastOptions | Defaults applied to every toast, including unstyled and classNames. | |
hotkey | string[] | ["altKey", "KeyT"] | Keys that expand the stack and move focus to it. |
swipeDirections | ("top" | "right" | "bottom" | "left")[] | Directions a toast can be swiped away. | |
dir | "rtl" | "ltr" | "auto" | document direction | Text direction. |
containerAriaLabel | string | "Notifications" | Names the list. Sonner appends the hotkey. |
customAriaLabel | string | Replaces the whole list name, hotkey included. | |
className | string | Class on the list container. | |
style | React.CSSProperties | Inline style on the list container. |
Shapes
@nyte-ai/ui/sonner exports the types ExternalToast and ToasterProps. The names below appear
in those types and are not exported.
| Name | Shape |
|---|---|
Position | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top-center" | "bottom-center" |
Offset | number | string | { top?, right?, bottom?, left? } |
ToastIcons | success, info, warning, error, loading, close, each a React node |
ToastOptions | className, closeButton, descriptionClassName, style, cancelButtonStyle, actionButtonStyle, duration, unstyled, classNames, closeButtonAriaLabel, toasterId |
ToastClassnames | toast, title, description, content, icon, loader, closeButton, cancelButton, actionButton, success, error, info, warning, loading, default |
ToastT | The open toast, with its id, title, type, and the options it was given |
ToastToDismiss | { id, dismiss } |
Accessibility
- The toaster renders a region with
aria-live="polite". A new toast is announced without moving focus. - The region's accessible name is
containerAriaLabelplus the hotkey, so a screen reader user hears how to reach the stack.customAriaLabelreplaces that whole name. - The hotkey expands the stack and moves focus to the list. Escape collapses it again while focus is still inside.
- A close button needs a name. Set
closeButtonAriaLabelintoastOptions. - A loading toast carries no close button and no timer. Replace it or dismiss it by id.
- A toast is not a dialog. Do not put the only path to an action in one, since it closes on a timer.