{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ink/banner",
  "title": "Banner",
  "description": "Full-width announcement banner",
  "dependencies": [
    "ink"
  ],
  "registryDependencies": [
    "https://termcn.dev/r/ink/interaction.json",
    "https://termcn.dev/r/ink/terminal-symbols.json",
    "https://termcn.dev/r/ink/use-theme.json",
    "https://termcn.dev/r/ink/use-unicode.json"
  ],
  "files": [
    {
      "path": "registry/ui/banner.tsx",
      "content": "import { useIsScreenReaderEnabled, Box, Text } from \"ink\";\nimport React, { useState } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { useInteraction } from \"@/hooks/use-interaction\";\nimport type { InteractionProps } from \"@/hooks/use-interaction\";\nimport { useTheme } from \"@/hooks/use-theme\";\nimport { useUnicode } from \"@/hooks/use-unicode\";\nimport {\n  resolveStatusSymbol,\n  resolveTerminalSymbol,\n} from \"@/lib/terminal-symbols\";\n\nexport type BannerVariant =\n  | \"info\"\n  | \"warning\"\n  | \"error\"\n  | \"success\"\n  | \"neutral\";\n\nexport interface BannerProps extends InteractionProps {\n  children: ReactNode;\n  variant?: BannerVariant;\n  icon?: string;\n  title?: string;\n  dismissible?: boolean;\n  onDismiss?: () => void;\n  color?: string;\n  accentChar?: string;\n  gap?: number;\n  \"aria-label\"?: string;\n}\n\nexport const Banner = ({\n  children,\n  variant = \"info\",\n  icon,\n  title,\n  dismissible = false,\n  onDismiss,\n  color,\n  accentChar,\n  gap = 1,\n  id,\n  autoFocus,\n  isActive = true,\n  disabled,\n  \"aria-label\": ariaLabel,\n}: BannerProps) => {\n  const theme = useTheme();\n  const unicode = useUnicode();\n  const isScreenReaderEnabled = useIsScreenReaderEnabled();\n  const [dismissed, setDismissed] = useState(false);\n\n  const variantColor =\n    color ??\n    (() => {\n      switch (variant) {\n        case \"success\": {\n          return theme.colors.success;\n        }\n        case \"error\": {\n          return theme.colors.error;\n        }\n        case \"warning\": {\n          return theme.colors.warning;\n        }\n        case \"neutral\": {\n          return theme.colors.muted;\n        }\n        default: {\n          return theme.colors.info;\n        }\n      }\n    })();\n\n  const { isFocused } = useInteraction(\n    (_, key) => {\n      if (dismissible && key.escape) {\n        setDismissed(true);\n        onDismiss?.();\n      }\n    },\n    { autoFocus, disabled, id, isActive: isActive && dismissible }\n  );\n\n  if (dismissed) {\n    return null;\n  }\n\n  const resolvedIcon = icon ?? resolveStatusSymbol(unicode, variant);\n  const resolvedAccentChar =\n    accentChar ?? resolveTerminalSymbol(unicode, \"┃\", \"|\");\n\n  return (\n    <Box\n      flexDirection=\"column\"\n      aria-role={dismissible ? \"button\" : \"listitem\"}\n      aria-state={{ disabled: disabled || undefined }}\n    >\n      <Text\n        aria-label={\n          ariaLabel ??\n          `${variant} banner${title ? `: ${title}` : \"\"}${dismissible ? \". Press Escape to dismiss.\" : \"\"}`\n        }\n      >\n        {\"\"}\n      </Text>\n      <Box flexDirection=\"row\" gap={gap}>\n        {!isScreenReaderEnabled && (\n          <Text aria-hidden color={variantColor}>\n            {resolvedAccentChar}\n          </Text>\n        )}\n        <Box flexDirection=\"column\">\n          <Box flexDirection=\"row\" gap={1}>\n            <Text aria-hidden color={variantColor}>\n              {resolvedIcon}\n            </Text>\n            {isFocused && dismissible && <Text aria-hidden>[focused]</Text>}\n            {title && (\n              <Text bold color={variantColor}>\n                {title}:\n              </Text>\n            )}\n            <Text>{children}</Text>\n          </Box>\n          {dismissible && (\n            <Text aria-hidden color={theme.colors.muted} dimColor>\n              press Esc to dismiss\n            </Text>\n          )}\n        </Box>\n      </Box>\n    </Box>\n  );\n};\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "feedback"
  ],
  "type": "registry:ui"
}