Minimal Alert
Original · freeA minimal one-line alert with a dot indicator.
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/alert-minimal.json"use client";
import { useState } from "react";
type Tone = "info" | "success" | "warning" | "error";
type MinimalAlert = {
id: string;
tone: Tone;
message: string;
action?: { label: string; href: string };
};
const TONES: Record<
Tone,
{ dot: string; ring: string; label: string; text: string }
> = {
info: {
dot: "bg-sky-500",
ring: "shadow-[0_0_0_4px_rgba(14,165,233,0.15)]",
label: "Information",
text: "text-slate-700 dark:text-slate-200",
},
success: {
dot: "bg-emerald-500",
ring: "shadow-[0_0_0_4px_rgba(16,185,129,0.15)]",
label: "Success",
text: "text-slate-700 dark:text-slate-200",
},
warning: {
dot: "bg-amber-500",
ring: "shadow-[0_0_0_4px_rgba(245,158,11,0.15)]",
label: "Warning",
text: "text-slate-700 dark:text-slate-200",
},
error: {
dot: "bg-rose-500",
ring: "shadow-[0_0_0_4px_rgba(244,63,94,0.15)]",
label: "Error",
text: "text-slate-700 dark:text-slate-200",
},
};
const INITIAL: MinimalAlert[] = [
{
id: "deploy",
tone: "success",
message: "Deploy to production finished in 42s.",
action: { label: "View log", href: "#log" },
},
{
id: "seats",
tone: "info",
message: "3 new teammates joined your workspace this week.",
action: { label: "Manage", href: "#team" },
},
{
id: "quota",
tone: "warning",
message: "You've used 82% of your monthly API quota.",
action: { label: "Upgrade", href: "#billing" },
},
{
id: "webhook",
tone: "error",
message: "Webhook delivery to billing-service failed twice.",
action: { label: "Retry", href: "#retry" },
},
];
export default function AlertMinimal() {
const [alerts, setAlerts] = useState<MinimalAlert[]>(INITIAL);
const dismiss = (id: string) =>
setAlerts((prev) => prev.filter((a) => a.id !== id));
const reset = () => setAlerts(INITIAL);
return (
<section className="relative w-full bg-slate-50 px-6 py-20 dark:bg-slate-950 sm:px-8">
<style>{`
@keyframes alertMinimal_in {
from { opacity: 0; transform: translateY(-6px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes alertMinimal_pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.9); opacity: 0; }
}
.alertMinimal_row { animation: alertMinimal_in 0.35s cubic-bezier(0.22, 1, 0.36, 1) both; }
.alertMinimal_ping { animation: alertMinimal_pulse 2s cubic-bezier(0, 0, 0.2, 1) infinite; }
@media (prefers-reduced-motion: reduce) {
.alertMinimal_row { animation: none; }
.alertMinimal_ping { animation: none; }
}
`}</style>
<div className="mx-auto w-full max-w-2xl">
<div className="mb-8 flex items-end justify-between gap-4">
<div>
<h2 className="text-lg font-semibold tracking-tight text-slate-900 dark:text-white">
Notifications
</h2>
<p className="mt-1 text-sm text-slate-500 dark:text-slate-400">
Minimal one-line alerts with a status dot.
</p>
</div>
{alerts.length < INITIAL.length && (
<button
type="button"
onClick={reset}
className="shrink-0 rounded-lg px-3 py-1.5 text-sm font-medium text-indigo-600 transition-colors hover:bg-indigo-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 focus-visible:ring-offset-slate-50 dark:text-indigo-400 dark:hover:bg-indigo-500/10 dark:focus-visible:ring-offset-slate-950"
>
Restore all
</button>
)}
</div>
<ul className="flex flex-col gap-2.5">
{alerts.map((alert) => {
const t = TONES[alert.tone];
return (
<li
key={alert.id}
role="status"
aria-live="polite"
className="alertMinimal_row group flex items-center gap-3 rounded-xl border border-slate-200 bg-white px-4 py-3 shadow-sm transition-shadow hover:shadow-md dark:border-slate-800 dark:bg-slate-900"
>
<span className="relative flex h-2.5 w-2.5 shrink-0">
<span
aria-hidden="true"
className={`alertMinimal_ping absolute inline-flex h-full w-full rounded-full ${t.dot} opacity-60`}
/>
<span
className={`relative inline-flex h-2.5 w-2.5 rounded-full ${t.dot} ${t.ring}`}
/>
</span>
<p
className={`min-w-0 flex-1 truncate text-sm font-medium ${t.text}`}
>
<span className="sr-only">{t.label}: </span>
{alert.message}
</p>
{alert.action && (
<a
href={alert.action.href}
className="shrink-0 rounded-md px-2 py-1 text-sm font-semibold text-indigo-600 underline-offset-2 transition-colors hover:bg-indigo-50 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:text-indigo-400 dark:hover:bg-indigo-500/10"
>
{alert.action.label}
</a>
)}
<button
type="button"
onClick={() => dismiss(alert.id)}
aria-label={`Dismiss ${t.label.toLowerCase()} alert: ${alert.message}`}
className="shrink-0 rounded-md p-1 text-slate-400 opacity-60 transition-all hover:bg-slate-100 hover:text-slate-700 focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 group-hover:opacity-100 dark:hover:bg-slate-800 dark:hover:text-slate-200"
>
<svg
viewBox="0 0 20 20"
fill="none"
className="h-4 w-4"
aria-hidden="true"
>
<path
d="M6 6l8 8M14 6l-8 8"
stroke="currentColor"
strokeWidth="1.75"
strokeLinecap="round"
/>
</svg>
</button>
</li>
);
})}
</ul>
{alerts.length === 0 && (
<div className="rounded-xl border border-dashed border-slate-300 bg-white px-4 py-10 text-center dark:border-slate-700 dark:bg-slate-900">
<p className="text-sm font-medium text-slate-500 dark:text-slate-400">
You're all caught up. No new notifications.
</p>
</div>
)}
</div>
</section>
);
}Dependencies
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Soft Variants Alert
OriginalSoft-tinted alerts: success, info, warning and error, each with an icon.

Solid Variants Alert
OriginalSolid-colour alerts across the four states.

Outline Variants Alert
OriginalOutlined alerts across the four states.

Left Accent Alert
OriginalAlerts with a coloured left accent bar and icon.

Dismissible Alert
OriginalDismissible alerts with a working close button.

With Action Alert
OriginalAn alert with title, body and action buttons.
Icon Large Alert
OriginalAn alert led by a large circular icon.

Banner Top Alert
OriginalA full-width top announcement banner, dismissible.

Toast Stack Alert
OriginalA stack of dismissible toasts in a corner.

Toast Slide Alert
OriginalA toast that slides in with an icon and auto-dismiss progress.

Progress Alert
OriginalAn alert with a countdown progress bar.

Gradient Alert
OriginalA gradient promo banner alert with a call to action.

