The example below loads live from Storybook; open it in Storybook to use the controls.
Default
Section titled “Default”Wrap the app in one Toaster and show toasts with useToast. The toast appears in the bottom corner and closes after five seconds; the timer pauses on hover and focus.
import { Button, Toaster, useToast } from '@bigbang/ui';
function ShowButton() { const toast = useToast(); return ( <Button variant="secondary" onClick={() => toast.show({ tone: 'success', title: 'Changes saved', description: 'Your latest edit has been saved.' })} > Show notification </Button> );}
export default function Default() { return ( <Toaster> <ShowButton /> </Toaster> );}tone sets the icon and colour. danger is announced at once and stays until closed.
import { Button, Toaster, useToast, type ToastOptions } from '@bigbang/ui';
const toasts: (ToastOptions & { button: string })[] = [ { button: 'Neutral', tone: 'neutral', title: 'Link copied' }, { button: 'Success', tone: 'success', title: 'Changes saved', description: 'Your latest edit has been saved.' }, { button: 'Info', tone: 'info', title: 'A new version is ready', description: 'It opens when you reload the page.' }, { button: 'Warning', tone: 'warning', title: 'Connection is slow', description: 'Changes may save with a delay.' }, { button: 'Error', tone: 'danger', title: 'Could not save', description: 'Check your connection and try again.' },];
function ToneButtons() { const toast = useToast(); return ( <div className="flex flex-wrap gap-sm"> {toasts.map(({ button, ...options }) => ( <Button key={button} variant="secondary" onClick={() => toast.show(options)}> {button} </Button> ))} </div> );}
export default function Tones() { return ( <Toaster> <ToneButtons /> </Toaster> );}With an action
Section titled “With an action”One action, such as “Undo”. The toast closes when it is pressed. The action must also be possible another way, because the toast closes by itself.
import { Button, Toaster, useToast } from '@bigbang/ui';
function DeleteButton() { const toast = useToast(); return ( <Button variant="secondary" onClick={() => toast.show({ title: 'Item deleted', action: { label: 'Undo', onClick: () => undefined } })} > Show notification </Button> );}
export default function WithAction() { return ( <Toaster> <DeleteButton /> </Toaster> );}Loading, then success or error
Section titled “Loading, then success or error”promise shows a toast with a spinner; the same toast turns into a success when the promise resolves and an error when it rejects.
import { Button, Toaster, useToast } from '@bigbang/ui';
const wait = (fail: boolean) => new Promise((resolve, reject) => setTimeout(fail ? reject : resolve, 2000));
function SaveButtons() { const toast = useToast(); const save = (fail: boolean) => void toast .promise(wait(fail), { loading: { title: 'Saving' }, success: { title: 'Changes saved' }, error: { title: 'Could not save', description: 'Check your connection and try again.' }, }) .catch(() => undefined); return ( <div className="flex gap-sm"> <Button onClick={() => save(false)}>Save</Button> <Button variant="secondary" onClick={() => save(true)}> Save with an error </Button> </div> );}
export default function PromiseExample() { return ( <Toaster> <SaveButtons /> </Toaster> );}Light and dark mode
Section titled “Light and dark mode”The toast uses color-surface-raised and shadow-overlay; icons take the status colours.
import { Button, Toaster, useToast, type ToastOptions } from '@bigbang/ui';
const toasts: (ToastOptions & { button: string })[] = [ { button: 'Neutral', tone: 'neutral', title: 'Link copied' }, { button: 'Success', tone: 'success', title: 'Changes saved', description: 'Your latest edit has been saved.' }, { button: 'Info', tone: 'info', title: 'A new version is ready', description: 'It opens when you reload the page.' }, { button: 'Warning', tone: 'warning', title: 'Connection is slow', description: 'Changes may save with a delay.' }, { button: 'Error', tone: 'danger', title: 'Could not save', description: 'Check your connection and try again.' },];
function ToneButtons() { const toast = useToast(); return ( <div className="flex flex-wrap gap-sm"> {toasts.map(({ button, ...options }) => ( <Button key={button} variant="secondary" onClick={() => toast.show(options)}> {button} </Button> ))} </div> );}
export default function Tones() { return ( <Toaster> <ToneButtons /> </Toaster> );}