toast
Shows a short notification (success, error, warning, info, loading, or a promise's progress) that closes on its own.
import { toast, ToastFn, ToastOptions, ToastPromiseOptions, ToastUpdateOptions, ToastType } from '@salla.sa/twilight-theme-engine/components/toast';In plain words
A toast is the small message that slides in at the edge of the screen, like "Added to your wishlist", and goes away after a few seconds. Call toast.success('Added to your wishlist') from a click handler and it appears.
There is one method per kind of message: success, error, warning, info and loading, plus toast('text') for a plain one. Each call returns an id. Pass it back to replace that toast (toast.success('Saved', { id })) or to close it (toast.dismiss(id)).
You never put the toast area on the page yourself: TwilightProvider, the component every theme wraps its pages in, already renders it.
Signature
const toast: ToastFn
interface ToastFn {
(title: string, options?: ToastOptions): string | number;
success / error / warning / info / loading:
(title: string, options?: ToastOptions) => string | number;
promise: <T>(promise: Promise<T>, options: ToastPromiseOptions<T>) => Promise<T>;
dismiss: (id?: string | number) => void;
update: (id: string | number, options: ToastUpdateOptions) => void; // broken: see gotchas
}
// sonner's per-toast options, with description narrowed to a string
interface ToastOptions extends ExternalToast {
description?: string;
// id, duration, position, closeButton, dismissible, action, cancel,
// icon, onDismiss, onAutoClose, className, style…
}
interface ToastPromiseOptions<T = unknown> {
loading: string;
success: string | ((data: T) => string);
error: string | ((error: Error) => string);
}
interface ToastUpdateOptions extends ToastOptions {
title?: string;
type?: ToastType;
}
type ToastType = 'success' | 'error' | 'warning' | 'info' | 'loading';Try it live
import { toast } from '@salla.sa/twilight-theme-engine/components/toast';
export function SaveButton() {
return (
<button type="button" className="btn btn--primary" onClick={() => toast.success('Added to your wishlist')}>
Save
</button>
);
}
Example
import { toast } from '@salla.sa/twilight-theme-engine/components/toast';
export function SaveAddressButton({ save }: { save: () => Promise<void> }) {
const onClick = async () => {
const id = toast.loading('Saving your address…');
try {
await save();
toast.success('Address saved', { id }); // same id: replaces the loading toast
} catch {
toast.error('Could not save the address', { id, description: 'Please try again.' });
}
};
return (
<button type="button" className="btn btn--primary" onClick={onClick}>
Save
</button>
);
}
How it behaves
Every method forwards to the method of the same name in sonner 2, the toast library the engine depends on, and returns the toast id: a number, unless you pass your own
id.Passing the
idof a toast that is still on screen replaces it in place (type, title and options) instead of adding a new one. That is how aloadingtoast becomes a result.A toast stays 4 seconds unless you pass
duration(sonner's default; the engine's Toaster sets none). Aloadingtoast never closes on its own. At most 3 are visible at once; the rest stack behind and spread out on hover.promise(p, { loading, success, error })showsloadinguntilpsettles, thensuccess(a string, or a function of the value) orerror. It returns your promise, not sonner's, soawaitit for the value and handle its rejection as usual. Only those three options are forwarded.dismiss()with no id closes every toast.actionandcanceltake{ label, onClick }and render buttons inside the toast. Titles and descriptions are strings: the engine does not expose sonner's JSX toasts.It is a plain object, not tied to React rendering: call it from any event handler, effect or function that runs in the browser. Toasts appear only where a Toaster is mounted, which
TwilightProviderdoes unless you passtoast={false}(see Toaster).
Gotchas
toast.update(id, { type: 'success', title: 'Saved' })does not update the toast. It callssonner.success(id, { description: title }), which creates a second toast whose title is the id ("1") with your title under it, and the first toast stays (a loading one, forever). Addingidto the options only renames the old toast to its id (packages/theme-engine/src/components/toast/useToast.ts,update). Replace a toast with the variant and the id instead:toast.success('Saved', { id }).Calling
toast.success(…)in the body of a component shows a new toast every time that component renders. Call it from an event handler or an effect.
Related
The area where toasts appear, which also turns Salla SDK messages into toasts; TwilightProvider already renders one for you.
useToastAnother name for toast: the same object, not a React hook, so there is nothing to call at the top of a component.
ModalA dialog box over a dimmed page, opened and closed by your own state, with Header, Body and Footer parts.