Banner
WhereUIแถบประกาศเต็มความกว้าง มีไอคอนอัตโนมัติตามสถานะ ปิดได้ด้วยปุ่มกากบาทเมื่อส่ง onClose
ติดตั้ง
Terminal
pnpm dlx shadcn@latest add @whereui/bannerต้องผูก registry และติดตั้ง @whereui/theme นำหน้าเสมอเมื่อติดตั้งครั้งแรก
การใช้งาน
import { Banner } from "@/components/ui/banner"<Banner variant="info" onClose={() => {}}> ระบบประเมินผลประจำปีเปิดใช้งานแล้ว</Banner>ตัวอย่างเพิ่มเติม
ทุกสถานะ แบบปิดไม่ได้
Props
| prop | type | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
| variant | "neutral" | "info" | "success" | "warning" | "destructive" | "info" | สถานะประกาศ กำหนดสีคู่ -soft และไอคอนนำหน้า — destructive ใช้ role="alert" |
| onClose | () => void | — | ถ้าส่งมาจะมีปุ่มปิด — component ซ่อนตัวเองแล้วเรียกฟังก์ชันนี้ (ถ้าต้องการแสดงใหม่ ใช้ key บังคับ remount) |
ข้อควรรู้
- วางไว้บนสุดของหน้า ใต้ header หรือเหนือเนื้อหา เต็มความกว้างเสมอ (ไม่มีมุมโค้ง)
- variant อื่นนอกจาก destructive ใช้ role="status" ให้โปรแกรมอ่านหน้าจอประกาศแบบสุภาพ
ซอร์สโค้ด
components/ui/banner.tsx
"use client"import * as React from "react"import { cva, type VariantProps } from "class-variance-authority"import { CircleAlertIcon, CircleCheckIcon, InfoIcon, MegaphoneIcon, TriangleAlertIcon, XIcon,} from "lucide-react"import { cn } from "cn"const bannerVariants = cva( "flex w-full items-start gap-2.5 px-4 py-3 text-sm has-data-[slot=banner-close]:pr-2", { variants: { variant: { neutral: "bg-muted text-foreground", info: "bg-info-soft text-info", success: "bg-success-soft text-success", warning: "bg-warning-soft text-warning", destructive: "bg-destructive-soft text-destructive", }, }, defaultVariants: { variant: "info", }, })const bannerIcons = { neutral: MegaphoneIcon, info: InfoIcon, success: CircleCheckIcon, warning: TriangleAlertIcon, destructive: CircleAlertIcon,} as const// แถบประกาศเต็มความกว้าง — ส่ง onClose เพื่อให้ปิดได้ (ปิดเองภายใน แล้วเรียกกลับ)function Banner({ className, variant = "info", onClose, children, ...props}: React.ComponentProps<"div"> & VariantProps<typeof bannerVariants> & { onClose?: () => void }) { const [open, setOpen] = React.useState(true) const Icon = bannerIcons[variant ?? "info"] if (!open) return null return ( <div data-slot="banner" data-variant={variant} role={variant === "destructive" ? "alert" : "status"} className={cn(bannerVariants({ variant }), className)} {...props} > <Icon aria-hidden="true" className="mt-0.5 size-4 shrink-0" /> <div className="min-w-0 flex-1 py-0.5 [&_a]:underline [&_a]:underline-offset-3"> {children} </div> {onClose ? ( <button type="button" data-slot="banner-close" aria-label="ปิดประกาศ" onClick={() => { setOpen(false) onClose() }} className="-my-1 grid size-8 shrink-0 place-items-center rounded-lg transition-colors hover:bg-foreground/10" > <XIcon className="size-4" /> </button> ) : null} </div> )}export { Banner, bannerVariants }