Skip to main content

Toast

Toast is a status message that briefly appears over the page, such as confirming an export or offering to undo an action.

Import

import { ToastProvider } from '@vortexlabs/vortex';
import type { ToastProviderProps } from '@vortexlabs/vortex';

Allied components

Other links

"use client";

import { Button, useToast } from "@vortexlabs/vortex";

export const ToastExample = () => {
  const toast = useToast();

  return (
    <Button
      onClick={() =>
        toast.show({
          title: "Changes saved",
          closeAriaLabel: "Dismiss notification",
          description: "Your project is up to date.",
          tone: "success",
        })
      }
    >
      Save changes
    </Button>
  );
};

Features

  • Shows and hides notifications with useToast.
  • Supports seven tones and two layouts.
  • Supports icons, descriptions, and actions.
  • Supports six positions with separate queues.
  • Pauses auto-dismiss on hover and focus.

VortexProvider includes ToastProvider. Use useToast().show to send a notification. Toasts show a close button that needs closeAriaLabel; pass closable: false to hide it.

Tones and Icons

Set tone to match the message; the default is inverse. Add icon for a visual cue.

"use client";

import { Button, Stack, useToast } from "@vortexlabs/vortex";
import { CircleInformation } from "@vortexlabs/vortex-icons";

export const ToastTonesExample = () => {
  const toast = useToast();

  return (
    <Stack direction="row" gap={3} wrap>
      {(["inverse", "neutral", "primary", "info", "success", "warning", "critical"] as const).map(
        (tone) => (
          <Button
            key={tone}
            variant="secondary"
            onClick={() =>
              toast.show({
                title: `${tone} notification`,
                closeAriaLabel: "Dismiss notification",
                tone,
                icon: CircleInformation,
              })
            }
          >
            {tone}
          </Button>
        ),
      )}
    </Stack>
  );
};

Duration

The default timeout is "brief" (4 seconds). Use "extended" (8 seconds) or a number of milliseconds.

"use client";

import { Button, Stack, useToast } from "@vortexlabs/vortex";

export const ToastDurationExample = () => {
  const toast = useToast();

  return (
    <Stack direction="row" gap={3} wrap>
      <Button
        variant="secondary"
        onClick={() =>
          toast.show({
            title: "Link copied",
            closeAriaLabel: "Dismiss notification",
            timeout: "brief",
          })
        }
      >
        Show brief notification
      </Button>
      <Button
        variant="secondary"
        onClick={() =>
          toast.show({
            title: "Draft saved",
            closeAriaLabel: "Dismiss notification",
            description: "You can keep editing or publish it later.",
            timeout: "extended",
          })
        }
      >
        Show extended notification
      </Button>
    </Stack>
  );
};

Actions

Pass one button or an array to actionsSlot. By default, the last button is primary in inline layout, the first in stacked.

Pass the ID from show to hide to close it from an action. timeout: 0 keeps it open until then.

Project: Active
"use client";

import { Button, Stack, Text, useToast } from "@vortexlabs/vortex";
import React from "react";

export const ToastActionsExample = () => {
  const toast = useToast();
  const [toastId, setToastId] = React.useState<string | null>(null);

  const restore = (id: string) => {
    toast.hide(id);
    setToastId(null);
  };

  const archive = () => {
    const id = toast.show({
      title: "Project archived",
      closable: false,
      description: "You can restore it from the archive at any time.",
      layout: "stacked",
      timeout: 0,
      actionsSlot: [
        <Button key="undo" onClick={() => restore(id)}>
          Undo
        </Button>,
        <Button key="dismiss" onClick={() => toast.hide(id)}>
          Dismiss
        </Button>,
      ],
    });
    setToastId(id);
  };

  return (
    <Stack gap={3} align="start">
      <Text>Project: {toastId ? "Archived" : "Active"}</Text>
      <Button
        variant="secondary"
        onClick={() => (toastId ? restore(toastId) : archive())}
      >
        {toastId ? "Restore project" : "Archive project"}
      </Button>
    </Stack>
  );
};

Position

The default position is bottom-end. start and end follow the text direction.

"use client";

import { Button, Stack, useToast } from "@vortexlabs/vortex";

export const ToastPositionExample = () => {
  const toast = useToast();

  return (
    <Stack direction="row" gap={3} wrap>
      {(
        [
          "top-start",
          "top-center",
          "top-end",
          "bottom-start",
          "bottom-center",
          "bottom-end",
        ] as const
      ).map((position) => (
        <Button
          key={position}
          variant="secondary"
          onClick={() =>
            toast.show({
              title: `Notification at ${position}`,
              closeAriaLabel: "Dismiss notification",
              position,
            })
          }
        >
          {position}
        </Button>
      ))}
    </Stack>
  );
};

Separate Queues

A nested ToastProvider has its own queue and shows notifications inside its nearest positioned ancestor. useToast uses the closest provider.

options sets each position's width or keeps it expanded. Expanded stacks don't auto-dismiss, so add a dismiss action. For the app's provider, use toastOptions on VortexProvider.

"use client";

import { Button, Stack, ToastProvider, useToast } from "@vortexlabs/vortex";

const QueueButton = () => {
  const toast = useToast();

  const notify = () => {
    const id = toast.show({
      title: "Workspace updated",
      closable: false,
      description: "Notification from the local queue.",
      position: "bottom-center",
      actionsSlot: <Button onClick={() => toast.hide(id)}>Dismiss</Button>,
    });
  };

  return (
    <Button variant="secondary" onClick={notify}>
      Add local notification
    </Button>
  );
};

export const ToastQueueExample = () => {
  return (
    <Stack
      width="100%"
      height="18rem"
      align="start"
      attributes={{ style: { position: "relative" } }}
    >
      <ToastProvider
        options={{ "bottom-center": { width: "min(22rem, 100%)", expanded: true } }}
      >
        <QueueButton />
      </ToastProvider>
    </Stack>
  );
};

Accessibility

Key
Description
Tab
Moves from the trigger into the notification's actions. Focus returns to the trigger on close.
EnterSpace
Expands or collapses the stack. Expanded stacks pause auto-dismiss.
warning and critical notifications use role="alert"; other tones use role="status".
Keep essential information outside temporary notifications.