Feedbackui
Banner
Full-width announcement or incident bar, optionally dismissible.
Branching for object storage is now generally available.Read the changelog
Elevated build times in eu-central-1.
Scheduled maintenance on Sunday, 02:00–03:00 UTC.
Installation
npx shadcn@latest add @particular/bannernpm dependencies
- class-variance-authority@^0.7.1
- cn@^0.4.0
- lucide-react@^1.51.0
Installs these registry items
Source
"use client"
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { XIcon } from "lucide-react"
import { cn } from "cn"
import { Button } from "@/components/ui/button"
const bannerVariants = cva(
"relative flex w-full items-center justify-center gap-3 px-10 py-2 text-center text-sm [&>svg]:size-4 [&>svg]:shrink-0",
{
variants: {
tone: {
neutral: "bg-muted text-foreground",
brand: "bg-brand text-brand-foreground",
info: "bg-info-subtle text-info",
success: "bg-success-subtle text-success",
warning: "bg-warning-subtle text-warning",
destructive: "bg-destructive text-destructive-foreground",
},
},
defaultVariants: { tone: "neutral" },
}
)
function Banner({
tone,
dismissible = false,
onDismiss,
action,
className,
children,
...props
}: React.ComponentProps<"div"> &
VariantProps<typeof bannerVariants> & {
dismissible?: boolean
onDismiss?: () => void
action?: React.ReactNode
}) {
const [dismissed, setDismissed] = React.useState(false)
if (dismissed) return null
return (
<div data-slot="banner" role="region" aria-label="Announcement" className={cn(bannerVariants({ tone }), className)} {...props}>
{children}
{action}
{dismissible && (
<Button
variant="ghost"
size="icon-xs"
aria-label="Dismiss"
className="absolute right-2 text-current hover:bg-current/10 hover:text-current"
onClick={() => {
setDismissed(true)
onDismiss?.()
}}
>
<XIcon />
</Button>
)}
</div>
)
}
export { Banner, bannerVariants }