XDSToast@xds/core · Toast
Usage
Toast shows a brief, non-blocking notification to confirm an action or present temporary information. Use it for scenarios where the user needs feedback but not a decision, such as saving, deleting, or changing a status. For production use, prefer the `useXDSToast()` hook — it handles positioning, stacking, auto-dismiss, and deduplication via `XDSToastViewport`. The `XDSToast` component renders the visual toast element inline and is useful for previews, documentation, and static showcases where the viewport lifecycle is not needed.Best practices
| Guidance | Practices |
|---|---|
| Do | Keep messages short - only a few words that tell the user what happened, like "Changes saved" or "Message sent". |
| Do | Add an undo action in the endContent slot for reversible operations like deleting an item, so the user can recover without navigating away. |
| Do | Use uniqueID to deduplicate toasts that fire from repeated actions, like clicking a save button multiple times. |
| Do | Use error type for failures that need attention but not immediate action — it persists until dismissed so the user won't miss it. |
| Don't | Don't use a toast for critical errors that block the user — use Banner for persistent, in-context messaging that requires acknowledgment. |
| Don't | Don't put long or multi-line content in a toast — it disappears after 5 seconds and the user may not finish reading. |
| Don't | Don't show form validation errors as toasts — use inline field validation so the user can see exactly which field needs fixing. |
Anatomy
| Element | Description | |
|---|---|---|
| Body | required | The primary message text describing what happened or what the user should know. |
| End content | A trailing action like an Undo button or a link, placed after the body text. | |
| Dismiss button | required | A close button that lets the user manually dismiss the toast before auto-hide. |
Import
tsimport {XDSToast} from '@xds/core/Toast'
Props
| Prop | Type | Description |
|---|---|---|
bodyrequired | ReactNode | Primary message content. |
type | 'info' | 'error' (default: 'info') | Toast type controlling background color. Error toasts persist until dismissed. |
isAutoHide | boolean | Whether the toast auto-dismisses. Defaults to true for info, false for error. |
autoHideDuration | number (default: 5000) | Duration in ms before auto-dismiss. |
endContent | ReactNode | Content rendered at the trailing end (e.g. Undo button, link). |
uniqueID | string | Unique identifier for deduplication. |
collisionBehavior | 'overwrite' | 'ignore' (default: 'overwrite') | Behavior when a toast with matching uniqueID already exists. |
onHide | (reason: "auto" | "manual") => void | Callback fired when the toast is removed. |
Examples
Common configurations, variations, and states.Toast — ActionPersistent toasts with a trailing button or link so the user can act on the notification, like undoing a delete or viewing a report.
tsx// In production, use useXDSToast() hook for proper positioning, stacking, and lifecycle.'use client';import {XDSToast} from '@xds/core/Toast';import {useXDSToast} from '@xds/core/Toast';import {XDSButton} from '@xds/core/Button';import {XDSLink} from '@xds/core/Link';import {XDSVStack} from '@xds/core/Layout';export default function ToastAction() {const toast = useXDSToast();return (<XDSVStack gap={3}><XDSToasttype="info"body="Item deleted"endContent={<XDSButtonlabel="Undo"variant="secondary"size="sm"onClick={() => toast({body: 'Undo successful', type: 'info'})}/>}isAutoHide={false}autoHideDuration={5000}isExiting={false}onDismiss={() => {}}/><XDSToasttype="info"body="Your report is ready."endContent={<XDSLink href="#" label="View report" hasUnderline>View report</XDSLink>}isAutoHide={false}autoHideDuration={5000}isExiting={false}onDismiss={() => {}}/></XDSVStack>);}
Toast — DeduplicationPrevent duplicate toasts with uniqueID. Use ignore to keep the first toast, or overwrite to replace it with updated content like a progress percentage.
tsx// In production, use useXDSToast() hook for proper positioning, stacking, and lifecycle.'use client';import {XDSToast} from '@xds/core/Toast';import {useXDSToast} from '@xds/core/Toast';import {XDSButton} from '@xds/core/Button';import {XDSVStack, XDSHStack} from '@xds/core/Layout';export default function ToastDeduplication() {const toast = useXDSToast();return (<XDSVStack gap={3}><XDSToasttype="info"body="You are offline"isAutoHide={false}autoHideDuration={5000}isExiting={false}onDismiss={() => {}}/><XDSHStack gap={3} vAlign="center"><XDSButtonlabel="Offline (ignore)"variant="secondary"size="sm"onClick={() =>toast({body: 'You are offline',uniqueID: 'offline',collisionBehavior: 'ignore',isAutoHide: false,})}/><XDSButtonlabel="Progress (overwrite)"variant="secondary"size="sm"onClick={() =>toast({body: `Uploading… ${Math.floor(Math.random() * 100)}%`,uniqueID: 'upload-progress',collisionBehavior: 'overwrite',isAutoHide: false,})}/></XDSHStack></XDSVStack>);}
Toast — DismissShow a persistent toast and dismiss it programmatically using the function returned by useXDSToast. Use for long-running operations that need manual cleanup.
tsx// In production, use useXDSToast() hook for proper positioning, stacking, and lifecycle.'use client';import {useRef} from 'react';import {XDSToast} from '@xds/core/Toast';import {useXDSToast} from '@xds/core/Toast';import {XDSButton} from '@xds/core/Button';import {XDSVStack, XDSHStack} from '@xds/core/Layout';export default function ToastDismiss() {const toast = useXDSToast();const dismissRef = useRef<(() => void) | null>(null);return (<XDSVStack gap={3}><XDSToasttype="info"body="Uploading file…"isAutoHide={false}autoHideDuration={5000}isExiting={false}onDismiss={() => {}}/><XDSHStack gap={3} vAlign="center"><XDSButtonlabel="Show toast"variant="secondary"size="sm"onClick={() => {dismissRef.current = toast({body: 'Uploading file…',isAutoHide: false,});}}/><XDSButtonlabel="Dismiss via code"variant="ghost"size="sm"onClick={() => {dismissRef.current?.();dismissRef.current = null;}}/></XDSHStack></XDSVStack>);}
Toast — StackingMultiple toasts stacking vertically with smooth enter and exit animations. Click repeatedly to see how toasts queue and dismiss.
tsx// In production, use useXDSToast() hook for proper positioning, stacking, and lifecycle.'use client';import {useRef} from 'react';import {XDSToast} from '@xds/core/Toast';import {useXDSToast} from '@xds/core/Toast';import {XDSButton} from '@xds/core/Button';import {XDSVStack} from '@xds/core/Layout';const MESSAGES = [{body: 'Changes saved.', type: 'info' as const},{body: 'Failed to upload file.', type: 'error' as const},{body: 'Message sent to Sarah Chen.', type: 'info' as const},];export default function ToastStacking() {const toast = useXDSToast();const countRef = useRef(0);return (<XDSVStack gap={3}>{MESSAGES.map(msg => (<XDSToastkey={msg.body}type={msg.type}body={msg.body}isAutoHide={false}autoHideDuration={5000}isExiting={false}onDismiss={() => {}}/>))}<XDSButtonlabel="Show toast"variant="secondary"size="sm"onClick={() => {const msg = MESSAGES[countRef.current % MESSAGES.length];countRef.current++;toast(msg);}}/></XDSVStack>);}
Toast — TypesInfo and error toast variants side by side. Info toasts auto-dismiss after 5 seconds, error toasts persist until the user dismisses them.
tsx// In production, use useXDSToast() hook for proper positioning, stacking, and lifecycle.'use client';import {XDSToast} from '@xds/core/Toast';import {useXDSToast} from '@xds/core/Toast';import {XDSButton} from '@xds/core/Button';import {XDSVStack} from '@xds/core/Layout';export default function ToastTypes() {const toast = useXDSToast();return (<XDSVStack gap={3}><XDSToasttype="info"body="Changes saved successfully."endContent={<XDSButtonlabel="Show toast"variant="ghost"size="sm"onClick={() =>toast({body: 'Changes saved successfully.', type: 'info'})}/>}isAutoHide={false}autoHideDuration={5000}isExiting={false}onDismiss={() => {}}/><XDSToasttype="error"body="Failed to save changes."endContent={<XDSButtonlabel="Show toast"variant="ghost"size="sm"onClick={() =>toast({body: 'Failed to save changes.', type: 'error'})}/>}isAutoHide={false}autoHideDuration={5000}isExiting={false}onDismiss={() => {}}/></XDSVStack>);}
Showcase source
tsx// In production, use useXDSToast() hook for proper positioning, stacking, and lifecycle.'use client';import {XDSToast} from '@xds/core/Toast';import {useXDSToast} from '@xds/core/Toast';import {XDSButton} from '@xds/core/Button';export default function ToastShowcase() {const toast = useXDSToast();return (<XDSToasttype="info"body="Document saved successfully"endContent={<XDSButtonlabel="Show toast"variant="ghost"size="sm"onClick={() => toast({body: 'Document saved successfully'})}/>}isAutoHide={false}autoHideDuration={5000}isExiting={false}onDismiss={() => {}}/>);}