Toast
Temporary notification messages with action support. Install Toast from the VLLNT UI registry with the shadcn CLI.
Temporary notification messages with action support. Part of the overlay family in VLLNT UI, it ships as a machine-readable registry entry — copy the source directly into your app with the shadcn CLI and own it, no runtime dependency on a component library.
Preview
Switch between light and dark to inspect the embedded Storybook preview.
Installation
Add Toast to your project with the shadcn CLI. The source lands in your codebase, ready to adapt:
pnpm dlx shadcn@latest add https://ui.vllnt.ai/r/toast.jsonSource
"use client";
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "../../lib/utils";
export type ToastProps = {
variant?: "default" | "destructive";
} & React.HTMLAttributes<HTMLDivElement>;
export type ToastActionElement = {} & React.ReactElement;
const toastVariants = cva(
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
{
defaultVariants: {
variant: "default",
},
variants: {
variant: {
default: "border bg-background text-foreground",
destructive:
"destructive border-destructive bg-destructive text-destructive-foreground",
},
},
},
);
const Toast = ({
className,
ref: reference,
variant,
...props
}: ToastProps &
VariantProps<typeof toastVariants> & {
ref?: React.Ref<HTMLDivElement>;
}) => (
<div
className={cn(toastVariants({ variant }), className)}
ref={reference}
{...props}
/>
);
Toast.displayName = "Toast";
const ToastAction = ({
altText,
className,
ref: reference,
...props
}: React.ComponentPropsWithoutRef<"button"> & {
altText?: string;
ref?: React.Ref<HTMLButtonElement>;
}) => (
<button
className={cn(
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
className,
)}
ref={reference}
type="button"
{...props}
/>
);
ToastAction.displayName = "ToastAction";
const ToastClose = ({
className,
ref: reference,
...props
}: React.ComponentPropsWithoutRef<"button"> & {
ref?: React.Ref<HTMLButtonElement>;
}) => (
<button
className={cn(
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
className,
)}
data-toast-close="true"
ref={reference}
type="button"
{...props}
>
<span className="sr-only">Close</span>✕
</button>
);
ToastClose.displayName = "ToastClose";
const ToastTitle = ({
className,
ref: reference,
...props
}: React.HTMLAttributes<HTMLDivElement> & {
ref?: React.Ref<HTMLDivElement>;
}) => (
<div
className={cn("text-sm font-semibold", className)}
ref={reference}
{...props}
/>
);
ToastTitle.displayName = "ToastTitle";
const ToastDescription = ({
className,
ref: reference,
...props
}: React.HTMLAttributes<HTMLDivElement> & {
ref?: React.Ref<HTMLDivElement>;
}) => (
<div
className={cn("text-sm opacity-90", className)}
ref={reference}
{...props}
/>
);
ToastDescription.displayName = "ToastDescription";
export { Toast, ToastAction, ToastClose, ToastDescription, ToastTitle };
Stories
Explore every variant and state in the interactive Storybook:
Preview
Switch between light and dark to inspect the embedded Storybook preview.