Features
- Shows and hides notifications with
useToast. - Supports six tones and two layouts.
- Supports icons, descriptions, and actions.
- Supports six positions with separate queues.
- Pauses auto-dismiss on hover and focus.
Showing Toasts
VortexProvider already includes ToastProvider, so no setup is needed. Get show from useToast and pass it the notification's title and description.
"use client";
import { Button, useToast } from "@vortexlabs/vortex";
export const ToastExample = () => {
const toast = useToast();
return (
<Button
onClick={() =>
toast.show({
title: "Changes saved",
description: "Your project is up to date.",
tone: "success",
})
}
>
Save changes
</Button>
);
};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", "info", "success", "warning", "error"] as const).map(
(tone) => (
<Button
key={tone}
variant="secondary"
onClick={() =>
toast.show({
title: `${tone} 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", timeout: "brief" })}
>
Show brief notification
</Button>
<Button
variant="secondary"
onClick={() =>
toast.show({
title: "Draft saved",
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. The last 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.
"use client";
import { Button, Stack, Text, useToast } from "@vortexlabs/vortex";
import { useState } from "react";
export const ToastActionsExample = () => {
const toast = useToast();
const [toastId, setToastId] = useState<string | null>(null);
const restore = (id: string) => {
toast.hide(id);
setToastId(null);
};
const archive = () => {
const id = toast.show({
title: "Project archived",
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}`, 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",
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
warning and error notifications use role="alert"; other tones use role="status".timeout: 0 notifications an action that calls hide.