tsimport {XDSToast} from '@xds/core/Toast'
| 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. |
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>);}
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>);}
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>);}
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>);}
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>);}
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={() => {}}/>);}