Banner
ProA full-width announcement or system message with an icon, one line of text, an action link and an optional dismiss button.
npx prodular-ui add bannerPart of Prodular UI Pro. Preview and read the docs freely, install with a license. See pricing
App bar
Edge to edge above the app header, centered, dismissible and controlled.
The bar sits above the app header and spans the full width.
"use client"
import * as React from "react"import { MegaphoneIcon } from "lucide-react"
import { Banner, BannerAction, BannerClose, BannerContent, BannerDescription, BannerIcon, BannerTitle,} from "@/components/ui/banner"import { Button } from "@/components/ui/button"
export default function BannerAppBar() { const [open, setOpen] = React.useState(true) return ( <div className="w-full overflow-hidden rounded-xl border bg-background shadow-xs"> <Banner variant="brand" align="center" open={open} onOpenChange={setOpen}> <BannerIcon> <MegaphoneIcon /> </BannerIcon> <BannerContent> <BannerTitle>Ledgerline 4.0 is here</BannerTitle> <BannerDescription>Revenue recognition, now automatic.</BannerDescription> </BannerContent> <BannerAction>See what is new</BannerAction> <BannerClose /> </Banner> <div className="flex h-40 flex-col items-center justify-center gap-3 p-6 text-center"> <p className="text-sm text-muted-foreground"> {open ? "The bar sits above the app header and spans the full width." : "Dismissed. Persist this per user so it stays gone."} </p> {!open && ( <Button variant="outline" size="sm" onClick={() => setOpen(true)}> Show banner again </Button> )} </div> </div> )}Variants
layout="inset" places the banner inside page content with a radius.
"use client"
import { CircleAlertIcon, InfoIcon, RocketIcon, SparklesIcon, TriangleAlertIcon } from "lucide-react"
import { Banner, BannerAction, BannerClose, BannerContent, BannerDescription, BannerIcon, BannerTitle,} from "@/components/ui/banner"
export default function BannerVariants() { return ( <div className="flex w-full flex-col gap-3"> <Banner variant="info" layout="inset"> <BannerIcon> <InfoIcon /> </BannerIcon> <BannerContent> <BannerTitle>Scheduled maintenance</BannerTitle> <BannerDescription>Billing exports pause on Oct 26 from 02:00 to 03:00 UTC.</BannerDescription> </BannerContent> <BannerAction render={<a href="#maintenance" />}>Details</BannerAction> <BannerClose /> </Banner> <Banner variant="warning" layout="inset"> <BannerIcon> <TriangleAlertIcon /> </BannerIcon> <BannerContent> <BannerTitle>Your card expires in 6 days</BannerTitle> <BannerDescription>Update it to keep the Growth plan active.</BannerDescription> </BannerContent> <BannerAction>Update payment method</BannerAction> </Banner> <Banner variant="destructive" layout="inset"> <BannerIcon> <CircleAlertIcon /> </BannerIcon> <BannerContent> <BannerTitle>Webhook deliveries are failing</BannerTitle> <BannerDescription>148 events to hooks.ledgerline.io returned 503 in the last hour.</BannerDescription> </BannerContent> <BannerAction>View logs</BannerAction> </Banner> <Banner variant="brand" layout="inset"> <BannerIcon> <RocketIcon /> </BannerIcon> <BannerContent> <BannerTitle>Usage-based pricing is live</BannerTitle> <BannerDescription>Meter API calls, seats or storage on any plan.</BannerDescription> </BannerContent> <BannerAction>Set up a meter</BannerAction> <BannerClose /> </Banner> <Banner variant="ai" layout="inset"> <BannerIcon> <SparklesIcon /> </BannerIcon> <BannerContent> <BannerTitle>Atlas drafted 12 dunning emails</BannerTitle> <BannerDescription>Review them before they go out on Monday.</BannerDescription> </BannerContent> <BannerAction>Review drafts</BannerAction> <BannerClose /> </Banner> </div> )}Anatomy
<Banner variant="info"> <BannerIcon><InfoIcon /></BannerIcon> <BannerContent> <BannerTitle>Scheduled maintenance</BannerTitle> <BannerDescription>Exports pause on Oct 26.</BannerDescription> </BannerContent> <BannerAction render={<a href="/status" />}>Details</BannerAction> <BannerClose /></Banner>Guidance
Use it when
- Messages about the whole account or app: maintenance windows, billing problems, outages, launches.
- brand for product announcements, ai for things a model did that people should review.
- warning and destructive for problems that block work until someone acts.
Avoid
- Feedback on a single action. Use a toast.
- Problems with one form or record. Use an Alert next to it.
- Stacking several banners. Show the most urgent one.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Keep it to one line: BannerTitle plus a short BannerDescription. Put the details behind BannerAction.
- Label BannerAction with a verb: Update payment method, View logs. Pass render={<a href=... />} for navigation.
- Add BannerClose only for messages that are safe to ignore. Do not make destructive banners dismissible while the problem lasts.
- Control open with onOpenChange and persist the dismissal so it does not come back on reload.
- Use layout="bar" at the very top of the app shell and layout="inset" inside page content.
- Use variant="ai" only when a model produced the thing the banner talks about.
API
Banner
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "neutral" | "info" | "warning" | "destructive" | "brand" | "ai" | "neutral" | Color and role. warning and destructive set role="alert". |
| layout | "bar" | "inset" | "bar" | bar spans the full width with a bottom border. inset is rounded with a full border. |
| align | "start" | "center" | "start" | center centers the content on wide screens; the close button moves to the edge. |
| open / defaultOpen / onOpenChange | boolean / boolean / (open) => void | Visibility. BannerClose calls onOpenChange(false). |
BannerAction
| Prop | Type | Default | Description |
|---|---|---|---|
| render | ReactElement | Renders the action as a link or router Link. |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add banner# or, with the registry in components.jsonnpx shadcn@latest add @prodular/banner