Skip to content
BigBang

Popular

    ↑↓Navigate↵OpenEscClose
    TR

    Components

    Toast

    A short message about the result of an action that appears in a corner of the page, stacks and can be swiped away.

    Storybook
    Storybook
    Source
    Source

    The example below loads live from Storybook; open it in Storybook to use the controls.

    Live example, StorybookOpen in Storybook

    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>
    );
    }

    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>
    );
    }

    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>
    );
    }

    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>
    );
    }