React Alert Examples — Variants, Icons, Dismissible
Copy-paste React Alert examples — four variants, custom icons, dismissible pattern with state, and rendering alerts from an array. Drivn component library.
Alerts are how a React interface talks back mid-task — a trial lapses, a save succeeds, an upload fails. They live inline with the content that triggered them, hold their spot until the state changes or the user dismisses them, and carry one clear message per box. An alert that does its job earns attention once and then gets out of the way.
Drivn's Alert is a single component, not a set of sub-parts. It takes a variant (default, info, success, or destructive), a title prop for the bold headline, an icon prop that accepts either a component reference like icon={Info} or a pre-rendered element, and a children slot for the body. There is no AlertTitle or AlertDescription to import and nest — the whole thing reads in one glance, and the styling lives in a const styles object keyed by keyof typeof styles.variants inside the file the CLI drops into your repo.
This page gathers five alert patterns you will actually ship: a default banner with a title, the full four-variant showcase, a custom-icon alert, a dismissible alert backed by React state, and a data-driven version that maps a server response into a list. Every snippet is copy-paste and assumes Drivn is installed via the CLI. For an engineering comparison against shadcn/ui's Alert, see Drivn vs shadcn/ui Alert.
Default alert with title
The canonical Drivn Alert is a single component with a title prop for the bold headline and children for the body copy. No wrapper elements, no sub-components, no AlertTitle or AlertDescription imports to remember. The default variant renders a neutral accent background with a subtle border — appropriate for informational banners that do not warrant the visual weight of info or success.
Drop this pattern at the top of a page, inside a card, or as a persistent banner in a dashboard header. The body text can hold an inline link, a code span, or any markup your copy needs — the alert docs show the full API reference.
1 import { Alert } from '@/components/ui/alert' 2 3 export default function Page() { 4 return ( 5 <Alert title="Heads up!"> 6 You can add components to your app using the CLI. 7 </Alert> 8 ) 9 }
All four variants
Alert ships with four variants — default, info, success, and destructive — and each one is a single entry in the styles.variants object. The design tokens do the coloring: info pulls bg-info/10 with an info border and text, success maps to the green token, and destructive to red, so a blue notice, a green confirmation, and a red error all read correctly without a line of extra Tailwind config. shadcn/ui ships two variants by comparison, so the extra info and success presets save you a round of variant plumbing whenever a dashboard mixes states.
Reach for info on non-critical context like a trial countdown, success on a completed action, and destructive on anything the user has to fix. Keep default for neutral announcement bars where a colored tint would over-signal. See the feedback category for how Alert sits alongside Toast, Progress, and Tooltip across a product's surfaces.
1 import { Info, CheckCircle, XCircle } from 'lucide-react' 2 import { Alert } from '@/components/ui/alert' 3 4 <Alert variant="default" title="Heads up"> 5 Default alert for neutral announcements. 6 </Alert> 7 8 <Alert variant="info" icon={Info} title="Info"> 9 Your trial expires in 3 days. 10 </Alert> 11 12 <Alert variant="success" icon={CheckCircle} title="Success"> 13 Your changes have been saved. 14 </Alert> 15 16 <Alert variant="destructive" icon={XCircle} title="Error"> 17 Something went wrong. Please try again. 18 </Alert>
Custom icon
The icon prop accepts either a component reference (icon={Info}) or a pre-rendered React element (icon={<Info className="size-5 text-primary" />}). The component-reference form is concise and matches the pattern used by the Button (leftIcon={Plus}). Use it for the common case where the default icon size and color are fine.
The element form gives per-alert control — a larger icon on a hero banner, a custom color for a branded variant, or an inline SVG that is not in your Lucide set. Any component matching ComponentType<{ className?: string }> works, so you can pass a third-party icon set or a project-specific SVG component without adapters. See the theming guide for how to tint icons via token colors.
1 import { Info, Shield, Zap } from 'lucide-react' 2 import { Alert } from '@/components/ui/alert' 3 4 // component reference — concise 5 <Alert variant="info" icon={Info} title="Did you know?"> 6 You can customize alerts with any icon. 7 </Alert> 8 9 // pre-rendered element — full control 10 <Alert 11 variant="success" 12 icon={<Shield className="size-5 text-success" />} 13 title="Secure" 14 > 15 Connection is end-to-end encrypted. 16 </Alert> 17 18 // any custom component 19 <Alert icon={Zap} title="Fast"> 20 Response times under 100ms. 21 </Alert>
Dismissible alert
Drivn's Alert does not ship a built-in close button because most alert surfaces do not need one — inline errors resolve when the user fixes the underlying issue; status banners stay until the status changes. For the cases that do need dismissal (announcement bars, first-run tips, paid-feature upsells), wrap the Alert in a component that owns an open state and conditionally renders.
The snippet below adds a close button in the top-right corner using the Button with variant="ghost" and an X icon. Persist the dismissed state with localStorage if the alert should stay gone across page loads. For a stack of alerts that auto-dismiss on a timer, use the Toast component instead — toasts are built for transient notifications with a timeline.
1 'use client' 2 import * as React from 'react' 3 import { X, Info } from 'lucide-react' 4 import { Alert } from '@/components/ui/alert' 5 import { Button } from '@/components/ui/button' 6 7 export function DismissibleAlert() { 8 const [open, setOpen] = React.useState(true) 9 return ( 10 <div className="relative"> 11 {open && ( 12 <Alert variant="info" icon={Info} title="New feature"> 13 You can now schedule posts ahead of time. 14 </Alert> 15 )} 16 <Button 17 variant="ghost" 18 size="sm" 19 className="absolute top-2 right-2" 20 onClick={() => setOpen(false)} 21 aria-label="Dismiss" 22 > 23 <X className="size-4" /> 24 </Button> 25 </div> 26 ) 27 }
Render alerts from an array
Server-returned errors, CMS-driven announcements, and notification lists all arrive as arrays of objects. Map over the array and render one Alert per item. Use the object's stable id as the React key, the variant field as the alert's variant, and the message field as children. Pair with a filter to show only active alerts, or with a sort to put the most severe at the top of the list.
This pattern also works for per-field form errors — render one destructive Alert above the form for server-side failures that touch multiple fields at once. For field-level inline errors, use each input's error prop instead — see the React Hook Form guide for the full form-integration pattern.
1 import { Alert } from '@/components/ui/alert' 2 3 const alerts = [ 4 { 5 id: 1, 6 variant: 'info' as const, 7 title: 'Maintenance', 8 message: 'Scheduled downtime on Sunday at 2am UTC.', 9 }, 10 { 11 id: 2, 12 variant: 'success' as const, 13 title: 'Deployed', 14 message: 'v1.20 is live in production.', 15 }, 16 { 17 id: 3, 18 variant: 'destructive' as const, 19 title: 'Quota', 20 message: 'You are over your monthly API limit.', 21 }, 22 ] 23 24 <div className="flex flex-col gap-3"> 25 {alerts.map((a) => ( 26 <Alert key={a.id} variant={a.variant} title={a.title}> 27 {a.message} 28 </Alert> 29 ))} 30 </div>
Install Drivn in one command
Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.
npx drivn@latest createRequires Node 18+. Works with npm, pnpm, and yarn.
Frequently asked questions
Wrap the Alert in a component that owns an open state with React.useState(true), and conditionally return null when dismissed. Add a close button positioned absolutely in the corner using the Button component with variant="ghost" and an X icon. For persistence across page loads, store the dismissed state in localStorage keyed by the alert's id and read it on mount.
Alerts are persistent and inline — they stay on the page until the underlying condition resolves or the user dismisses them, and they render in normal document flow next to the content that caused them. Toasts are transient and floating — they stack in a corner, auto-dismiss after a timer, and are better for confirming completed actions ("Saved", "Sent"). Use an alert for unresolved conditions, and a toast for completed-action confirmations.
Yes. The children prop is a standard React node, so you can render paragraphs, links, inline code spans, emphasized text, and even buttons inside the alert body. Keep the content to one primary message per alert — if you find yourself adding two actions or three paragraphs, you probably want a Dialog or a Drawer. Inline links inside the alert body work; just style them with a class that matches your link pattern.
Yes. The icon prop accepts any React component that matches the ComponentType<{ className?: string }> signature, which covers every icon in lucide-react. You can also pass a pre-rendered JSX element if you need to override the default size or color per alert, or a custom SVG component from your design system. Non-Lucide icon sets work as long as they accept a className prop.
Render the Alert conditionally based on whether the server returned an error message. Use the destructive variant, set the title to a short noun phrase ("Save failed"), and put the server's message or a friendly rewrite in the children. For field-level errors use each input's error prop instead. For a list of errors at the top of a form, map them over a single destructive Alert rendered above the form.
Drivn Alerts do not include entrance or exit animations by default. Add them in the parent component — a fadeIn keyframe on the container, a slideDown from above, or a tween via framer-motion if you already use it. Because the Alert source lives in your repo after install, you can also add animation classes directly to the styles.base string in src/components/ui/alert.tsx.

