ComponentsCSS
Alert
Inline message on a surface, tinted by a soft glow in info, success, warning or danger.
A new runtime is available
Node 24 is now the default for new projects.
Domain verified
app.acme.dev is pointing at this project.
Build cache almost full
You have used 4.6 GB of 5 GB.
Deploy failed
Type error in src/app/page.tsx.
Installation
npx shadcn@latest add https://ui-collections.vercel.app/r/tide/alert.jsonAlso installs the theme, cn(). Packages: clsx, tailwind-merge.
Usage
alert-demo.tsx
"use client";
import { useState } from "react";
import { Alert } from "@/registry/kit/ui/alert";
import { Button } from "@/registry/kit/ui/button";
export default function AlertDemo() {
const [logs, setLogs] = useState(false);
return (
<div className="grid w-full max-w-lg gap-3">
<Alert title="A new runtime is available">Node 24 is now the default for new projects.</Alert>
<Alert variant="success" title="Domain verified">app.acme.dev is pointing at this project.</Alert>
<Alert variant="warning" title="Build cache almost full">You have used 4.6 GB of 5 GB.</Alert>
<Alert
variant="danger"
title="Deploy failed"
action={
<Button size="sm" variant="ghost" aria-expanded={logs} onClick={() => setLogs((v) => !v)}>
{logs ? "Hide logs" : "View logs"}
</Button>
}
>
Type error in src/app/page.tsx.
{logs && (
<pre className="mt-2 overflow-x-auto rounded-field bg-bg-deep/60 px-3 py-2 font-mono text-xs text-fg/80">
{"src/app/page.tsx:42:7\nType 'string' is not assignable to type 'number'."}
</pre>
)}
</Alert>
</div>
);
}API
variant= "info"
"info" | "success" | "warning" | "danger"Tone. Danger uses role=alert.
titleReactNodeHeadline.
actionReactNodeTrailing control.
Source
components/ui/alert.tsx
import type { HTMLAttributes } from "react";
import { cn } from "@/registry/kit/lib/utils";
const tones = {
info: { text: "text-info", glow: "var(--color-info)", path: "M12 16v-5M12 8h.01" },
success: { text: "text-success", glow: "var(--color-success)", path: "M8 12.5l2.5 2.5L16 9.5" },
warning: { text: "text-warning", glow: "var(--color-warning)", path: "M12 8v4.5M12 16h.01" },
danger: { text: "text-danger", glow: "var(--color-danger)", path: "M9.5 9.5l5 5M14.5 9.5l-5 5" },
};
export interface AlertProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
variant?: keyof typeof tones;
title: React.ReactNode;
/** Optional trailing control, such as a link or button. */
action?: React.ReactNode;
}
/**
* Inline message on a surface, tinted by a soft glow in its tone colour.
* Danger alerts are announced immediately (role="alert"); the rest politely.
*/
export function Alert({ variant = "info", title, action, className, children, ...props }: AlertProps) {
const tone = tones[variant];
return (
<div
role={variant === "danger" ? "alert" : "status"}
className={cn("surface flex items-start gap-3 overflow-hidden rounded-card p-4", className)}
{...props}
>
{/* Tone glow over whatever fill the theme gives the surface. */}
<span
aria-hidden
className="pointer-events-none absolute inset-0 rounded-[inherit]"
style={{
background: `radial-gradient(120% 140% at 0% 0%, color-mix(in oklab, ${tone.glow} 14%, transparent), transparent 60%)`,
}}
/>
<svg viewBox="0 0 24 24" className={cn("relative mt-px size-5 shrink-0", tone.text)} fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
<circle cx="12" cy="12" r="9" />
<path d={tone.path} />
</svg>
<div className="relative min-w-0 flex-1">
<div className="text-sm font-medium text-fg">{title}</div>
{children && <div className="mt-1 text-sm leading-relaxed text-muted">{children}</div>}
</div>
{action && <div className="relative shrink-0 self-center">{action}</div>}
</div>
);
}