{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "banner",
  "title": "Banner",
  "description": "A page-wide announcement bar with a tone icon, title, description, optional action and an optional dismiss button.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/tealmac/banner.tsx",
      "content": "// Adapted from Ballmac UI (https://github.com/vamsiy78/ballmac-ui), MIT License, Copyright (c) 2026 Ballmac.\n\"use client\"\n\nimport * as React from \"react\"\nimport { CheckCircle2, Info, TriangleAlert, X } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype BannerProps = Omit<React.ComponentProps<\"section\">, \"title\"> & {\n  /** Short headline that names the announcement. */\n  title: string\n  /** Supporting detail, kept concise for a page-wide banner. */\n  description?: React.ReactNode\n  /** Semantic tone of the announcement. */\n  tone?: \"info\" | \"success\" | \"warning\"\n  /** Optional link or button placed after the message. */\n  action?: React.ReactNode\n  /** Show a dismiss button. */\n  dismissible?: boolean\n  /** Controlled visibility. */\n  visible?: boolean\n  /** Initial visibility when uncontrolled. */\n  defaultVisible?: boolean\n  /** Called when visibility changes. */\n  onVisibleChange?: (visible: boolean) => void\n}\n\nfunction Banner({\n  className,\n  title,\n  description,\n  tone = \"info\",\n  action,\n  dismissible = false,\n  visible,\n  defaultVisible = true,\n  onVisibleChange,\n  ...props\n}: BannerProps) {\n  const [internalVisible, setInternalVisible] = React.useState(defaultVisible)\n  const shown = visible ?? internalVisible\n  if (!shown) return null\n  const Icon =\n    tone === \"success\"\n      ? CheckCircle2\n      : tone === \"warning\"\n        ? TriangleAlert\n        : Info\n  function dismiss() {\n    if (visible === undefined) setInternalVisible(false)\n    onVisibleChange?.(false)\n  }\n  return (\n    <section\n      data-slot=\"banner\"\n      aria-label={title}\n      className={cn(\n        \"grid w-full min-w-0 grid-cols-[auto_minmax(0,1fr)_auto] items-start gap-x-3 gap-y-2 rounded-xl border px-4 py-3 text-sm shadow-sm sm:flex sm:flex-wrap sm:items-center\",\n        tone === \"info\" && \"border-primary/25 bg-primary/5\",\n        tone === \"success\" && \"border-chart-3/30 bg-chart-3/10\",\n        tone === \"warning\" && \"border-chart-4/30 bg-chart-4/10\",\n        className\n      )}\n      {...props}\n    >\n      <Icon\n        aria-hidden=\"true\"\n        className=\"text-foreground col-start-1 row-start-1 mt-0.5 size-4 shrink-0 sm:mt-0\"\n      />\n      <div className=\"col-start-2 row-start-1 min-w-0 flex-1 leading-5\">\n        <strong className=\"font-semibold\">{title}</strong>\n        {description && (\n          <span className=\"text-muted-foreground block sm:ms-1.5 sm:inline\">\n            {description}\n          </span>\n        )}\n      </div>\n      {action && (\n        <div\n          data-slot=\"banner-action\"\n          className=\"col-start-2 row-start-2 shrink-0\"\n        >\n          {action}\n        </div>\n      )}\n      {dismissible && (\n        <button\n          type=\"button\"\n          aria-label={`Dismiss ${title}`}\n          onClick={dismiss}\n          className=\"text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring/50 col-start-3 row-start-1 flex size-8 shrink-0 items-center justify-center rounded-md outline-none focus-visible:ring-[3px]\"\n        >\n          <X aria-hidden=\"true\" className=\"size-4\" />\n        </button>\n      )}\n    </section>\n  )\n}\n\nexport { Banner, type BannerProps }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}