{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "banner",
  "title": "Banner",
  "description": "The nx-ui Banner component.",
  "dependencies": [
    "@untitledui/icons@^0.0.22",
    "class-variance-authority@^0.7.1"
  ],
  "registryDependencies": [
    "@nx-ui/utils"
  ],
  "files": [
    {
      "path": "components/ui/banner.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { X } from \"@untitledui/icons\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\n/**\n * Banner — a full-width announcement bar for the top of an app or marketing\n * page: message + optional leading icon + trailing action links + a dismiss X.\n * Distinct from `alert` (a bordered card) — a banner is edge-to-edge.\n *\n * Three tones: `brand` (solid navy section fill), `neutral` (surface + hairline\n * ring), and `floating` (a rounded, shadowed card variant). All token-driven so\n * they flip in dark mode. Dismissal is uncontrolled by default — pass\n * `onDismiss` to hook in, or manage `open` yourself.\n *\n * @example\n * <Banner tone=\"brand\" onDismiss={() => …}>\n *   <BannerContent>\n *     <BannerTitle>New feedstock dashboard is live.</BannerTitle>\n *   </BannerContent>\n *   <BannerActions><Button size=\"sm\" variant=\"link\">See what's new</Button></BannerActions>\n * </Banner>\n */\n\nconst bannerVariants = cva(\n  \"relative flex w-full items-center gap-3 px-4 py-3 text-sm sm:gap-4\",\n  {\n    variants: {\n      tone: {\n        // text-text-on-brand-solid, NOT text-text-white: the brand fill flips\n        // navy → accent yellow in dark mode, and the on-brand text token flips\n        // with it (white → navy). Fixed white text fails contrast on yellow.\n        brand: \"bg-bg-brand-solid text-text-on-brand-solid [--banner-muted:var(--color-utility-brand-200)]\",\n        neutral:\n          \"bg-bg-primary text-text-secondary ring-1 ring-border-secondary ring-inset [--banner-muted:var(--color-text-tertiary)]\",\n        floating:\n          \"rounded-xl bg-bg-primary text-text-secondary shadow-lg ring-1 ring-border-secondary [--banner-muted:var(--color-text-tertiary)]\",\n      },\n    },\n    defaultVariants: {\n      tone: \"neutral\",\n    },\n  }\n)\n\nfunction Banner({\n  className,\n  tone = \"neutral\",\n  open: openProp,\n  defaultOpen = true,\n  onDismiss,\n  children,\n  ...props\n}: React.ComponentProps<\"div\"> &\n  VariantProps<typeof bannerVariants> & {\n    open?: boolean\n    defaultOpen?: boolean\n    onDismiss?: () => void\n  }) {\n  const [internalOpen, setInternalOpen] = React.useState(defaultOpen)\n  const open = openProp ?? internalOpen\n\n  if (!open) return null\n\n  return (\n    <div\n      data-slot=\"banner\"\n      data-tone={tone}\n      role=\"region\"\n      aria-label=\"Announcement\"\n      className={cn(bannerVariants({ tone }), className)}\n      {...props}\n    >\n      {children}\n      <BannerDismiss\n        onClick={() => {\n          setInternalOpen(false)\n          onDismiss?.()\n        }}\n      />\n    </div>\n  )\n}\n\nfunction BannerContent({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"banner-content\"\n      className={cn(\n        \"flex min-w-0 flex-1 flex-col gap-0.5 sm:flex-row sm:items-center sm:gap-1.5\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction BannerTitle({ className, ...props }: React.ComponentProps<\"p\">) {\n  return (\n    <p\n      data-slot=\"banner-title\"\n      className={cn(\"font-semibold\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction BannerDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n  return (\n    <p\n      data-slot=\"banner-description\"\n      className={cn(\"text-[color:var(--banner-muted)]\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction BannerActions({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"banner-actions\"\n      className={cn(\"flex shrink-0 items-center gap-2\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction BannerDismiss({\n  className,\n  ...props\n}: React.ComponentProps<\"button\">) {\n  return (\n    <button\n      type=\"button\"\n      data-slot=\"banner-dismiss\"\n      aria-label=\"Dismiss announcement\"\n      className={cn(\n        \"-mr-1 inline-flex size-8 shrink-0 items-center justify-center rounded-lg text-current opacity-70 transition hover:bg-black/10 hover:opacity-100 focus-visible:ring-4 focus-visible:ring-ring/25 focus-visible:outline-none dark:hover:bg-white/10 [&_svg]:size-4\",\n        className\n      )}\n      {...props}\n    >\n      <X />\n    </button>\n  )\n}\n\nexport {\n  Banner,\n  BannerContent,\n  BannerTitle,\n  BannerDescription,\n  BannerActions,\n  BannerDismiss,\n  bannerVariants,\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}