{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "banner",
  "title": "Banner",
  "description": "An inline notice about the page it sits on: a deploy is blocked, a quota is near.",
  "registryDependencies": [
    "https://sproutboat.com/ikada/r/theme.json",
    "https://sproutboat.com/ikada/r/cn.json",
    "https://sproutboat.com/ikada/r/icons.json",
    "https://sproutboat.com/ikada/r/status.json",
    "https://sproutboat.com/ikada/r/status-glyph.json"
  ],
  "files": [
    {
      "path": "registry/ikada/ui/banner.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport { cn, coarseTarget, focusRing, pressMotion } from \"@/components/ikada/lib/cn\";\nimport { CloseIcon } from \"@/components/ikada/lib/icons\";\nimport { softSurface } from \"@/components/ikada/status\";\nimport type { Status } from \"@/components/ikada/status\";\nimport { StatusGlyph } from \"@/components/ikada/status-glyph\";\n\nexport interface BannerProps extends Omit<ComponentProps<\"div\">, \"title\"> {\n  /** Status that sets the colour and the glyph. Default info. */\n  tone?: Status;\n  /** Bold first line; the children follow as the body. */\n  title?: ReactNode;\n  /** One action, usually a Button or Link. */\n  action?: ReactNode;\n  /** Shows a close button. The banner hides itself and calls `onDismiss`. */\n  dismissible?: boolean;\n  /** Shows a close button and is called when it is pressed. Without it the banner stays. */\n  onDismiss?: () => void;\n  /** Accessible name of the close button. Default \"Dismiss\". */\n  dismissLabel?: string;\n}\n\n/**\n * An inline notice about the page it sits on: a deploy is blocked, a quota is near.\n * Never promotion. Danger interrupts (`role=\"alert\"`); every other tone is polite.\n */\nexport function Banner({\n  tone = \"info\",\n  title,\n  action,\n  dismissible = false,\n  onDismiss,\n  dismissLabel = \"Dismiss\",\n  className,\n  children,\n  ref,\n  ...props\n}: BannerProps) {\n  const [open, setOpen] = useState(true);\n  if (!open) return null;\n  return (\n    <div\n      data-slot=\"banner\"\n      ref={ref}\n      role={tone === \"danger\" ? \"alert\" : \"status\"}\n      data-tone={tone}\n      className={cn(\"flex items-start gap-3 rounded-lg px-4 py-3 text-sb-base\", softSurface[tone], className)}\n      {...props}\n    >\n      <StatusGlyph tone={tone} className=\"mt-[5px]\" />\n      <div className=\"flex min-w-0 flex-1 flex-col gap-x-4 gap-y-2 sm:flex-row sm:items-center\">\n        <div className=\"min-w-0 flex-1\">\n          {title ? <div className=\"font-semibold\">{title}</div> : null}\n          {children ? <div className={cn(title && \"mt-0.5\")}>{children}</div> : null}\n        </div>\n        {action ? <div className=\"shrink-0 text-fg\">{action}</div> : null}\n      </div>\n      {dismissible ? (\n        <button\n          type=\"button\"\n          aria-label={dismissLabel}\n          onClick={() => {\n            setOpen(false);\n            onDismiss?.();\n          }}\n          className={cn(\n            \"-me-1.5 -mt-1 inline-grid size-8 shrink-0 place-items-center rounded-md hover:bg-fg/10\",\n            pressMotion,\n            coarseTarget,\n            focusRing,\n          )}\n        >\n          <CloseIcon />\n        </button>\n      ) : null}\n    </div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "@components/ikada/banner.tsx"
    }
  ],
  "categories": [
    "feedback"
  ],
  "type": "registry:ui"
}