- Accordion
- Avatar
- Badge
- Breadcrumb
- Button
- Calendar
- Checkbox
- Combobox
- Container
- CurrencyInput
- DistributionSlider
- Drawer
- Dropdown
- Grid
- Heading
- Image
- Input
- InputGroup
- Label
- Logo
- MapPin
- Modal
- NativeSelect
- NumberInput
- OtpInput
- PhoneInput
- Popover
- Progress
- PropertyCalendar
- RadioGroup
- RadioGroupCards
- ResponsiveModal
- ScrollArea
- SearchBar
- SearchBarFallback
- SearchInput
- Select
- Separator
- Spinner
- Switch
- Tabs
- Text
- Textarea
- Toast
- Toggle
- ToggleGroup
- Tooltip
Toast
Dictionary-driven notifications built on Sonner
pnpm add @wandercom/design-system-web
Add the Toaster component to your application root layout or provider:
import { Toaster } from '@wandercom/design-system-web/ui/toast';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<>
{children}
<Toaster />
</>
);
}Import the toast object to trigger toasts. The label and description props accept both dictionary keys and direct strings:
import { toast } from '@wandercom/design-system-web/ui/toast';
export function Example() {
return (
<>
<button onClick={() => toast.error({ label: 'ErrorGeneral', description: 'ErrorGeneral' })}>
Show error toast
</button>
<button onClick={() => toast.success({ label: 'Success!', description: 'Your changes have been saved.' })}>
Show success toast
</button>
</>
);
}The label and description props accept both dictionary keys and direct strings. When a key exists in the dictionary, the resolved copy is displayed. Otherwise, the string is used as-is.
// Dictionary keys (resolved from the toast dictionary)
toast.success({
label: 'CopiedToClipboard',
args: { value: 'API key' },
});
// Direct strings
toast.success({
label: 'Copied to clipboard!',
description: 'Your API key has been copied.',
});
// Mixing both
toast.error({
label: 'ErrorGeneral',
description: 'Please try again in a few moments.',
});Add action buttons to toasts for user interaction. When dismissible is true (the default), clicking an action also dismisses the toast.
toast.default({
label: 'ErrorActionFailed',
description: 'ErrorActionFailed',
actions: [
{
label: 'Try again',
onClick: () => {
console.log('Clicked try again');
},
},
{
label: 'Dismiss',
onClick: () => {
console.log('Dismissed');
},
},
],
});Set inline to render the label and description side-by-side instead of stacked:
toast.info({
label: 'Theme',
description: 'System preference',
inline: true,
});Control how long toasts are displayed and whether they can be dismissed:
toast.success({
label: 'CopiedToClipboard',
duration: 3000,
});
toast.info({
label: 'ChangedTheme',
args: { value: 'system' },
dismissible: false,
});Track promise-based operations with automatic loading, success, and error states:
toast.promise<{ name: string }>(
() => fetch('/api/booking').then((r) => r.json()),
{
loading: 'Processing...',
success: (data) => `${data.name} confirmed successfully`,
error: 'Failed to process booking',
},
);Each phase (loading, success, error) accepts a dictionary key, a direct string, or a full props object:
toast.promise<{ name: string }>(
() => fetch('/api/booking').then((r) => r.json()),
{
loading: { label: 'Processing...', description: 'Please wait' },
success: (data) => ({
label: 'Booking confirmed',
description: `${data.name} is all set`,
}),
error: { label: 'ErrorGeneral', description: 'ErrorGeneral' },
},
);The promise method shows a loading toast while the promise is pending, then automatically transitions to a success or error toast based on the result. The success and error options also accept a callback that receives the resolved data or error, respectively. The returned promise can be chained further.
Use createToast to build a toast instance backed by a custom dictionary. This keeps copy centralized and type-safe across your application.
import { createToast } from '@wandercom/design-system-web/ui/toast';
import { createToastDictionary } from '@wandercom/design-system-shared/dictionaries/toasts';
const APP_TOASTS = createToastDictionary({
BookingConfirmed: {
label: 'Booking confirmed',
description: ({ value }) => `Welcome, ${value}!`,
},
} as const);
export const appToast = createToast(APP_TOASTS);
// Usage -- dictionary keys are fully typed
appToast.success({ label: 'BookingConfirmed', args: { value: 'John' } });The shared dictionary keys (ErrorGeneral, CopiedToClipboard, etc.) are automatically included via createToastDictionary.
Notification without a preset icon. Accepts a custom icon prop.
Success notification with a green checkmark icon.
Error notification with a red exclamation icon.
Informational notification with an info icon.
Loading notification with an animated spinner.
Promise-based notification that transitions through loading, success, and error states automatically.
All toast methods accept the following props (except toast.promise(), documented above):
label?:
description?:
args?:
actions?:
icon?:
inline?:
dismissible?:
duration?:
The Toaster component accepts all Sonner ToasterProps. Defaults are applied for position (bottom-right) and toast width styling.
theme?:
position?:
Toast notifications are rendered by Sonner, which manages an aria-live region so screen readers announce new toasts automatically.
- Each toast is rendered inside an accessible container with appropriate
aria-livepoliteness - Dismissible toasts include a close button reachable via keyboard
- Action buttons within toasts are focusable and keyboard-operable
- Toasts do not trap focus, allowing users to continue interacting with the page