{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "validation-message",
  "type": "registry:ui",
  "title": "Validation Message",
  "description": "Validation Message is inline typed feedback paired with a field — error, warning, success, or info — with icon and text.",
  "author": "Skrewww",
  "dependencies": [
    "@phosphor-icons/react"
  ],
  "registryDependencies": [
    "@skrewww/foundation"
  ],
  "docs": "Host requirements (assumed already present, not installed by this command): react, react-dom.",
  "files": [
    {
      "path": "components/ui/ValidationMessage.tsx",
      "content": "/** @skrewww-component validation-message */\nimport {\n  CheckCircle,\n  Info,\n  Warning,\n  WarningCircle,\n} from \"@phosphor-icons/react/dist/ssr\";\nimport { cn } from \"@/lib/cn\";\nimport styles from \"@/components/ui/validation-message.module.css\";\n\nexport type ValidationMessageType = \"error\" | \"warning\" | \"success\" | \"info\";\n\nexport type ValidationAnnounce = \"off\" | \"polite\" | \"assertive\";\n\nconst typeClass: Record<ValidationMessageType, string> = {\n  error: styles.error,\n  warning: styles.warning,\n  success: styles.success,\n  info: styles.info,\n};\n\nconst iconClass: Record<ValidationMessageType, string> = {\n  error: styles.iconError,\n  warning: styles.iconWarning,\n  success: styles.iconSuccess,\n  info: styles.iconInfo,\n};\n\nfunction ValidationIcon({ type }: { type: ValidationMessageType }) {\n  const props = {\n    size: 16,\n    weight: \"fill\" as const,\n    className: cn(styles.icon, iconClass[type]),\n    \"aria-hidden\": true,\n  };\n\n  if (type === \"error\") return <WarningCircle {...props} />;\n  if (type === \"warning\") return <Warning {...props} />;\n  if (type === \"success\") return <CheckCircle {...props} />;\n  return <Info {...props} />;\n}\n\nfunction resolveRole(type: ValidationMessageType, announce: ValidationAnnounce) {\n  if (announce === \"off\") return undefined;\n  if (announce === \"assertive\" && type === \"error\") return \"alert\";\n  return \"status\";\n}\n\nexport function ValidationMessage({\n  id,\n  type = \"error\",\n  announce = \"off\",\n  children,\n  className,\n}: {\n  id?: string;\n  type?: ValidationMessageType;\n  announce?: ValidationAnnounce;\n  children: React.ReactNode;\n  className?: string;\n}) {\n  return (\n    <p\n      id={id}\n      className={cn(styles.message, typeClass[type], className)}\n      role={resolveRole(type, announce)}\n    >\n      <ValidationIcon type={type} />\n      <span>{children}</span>\n    </p>\n  );\n}\n",
      "type": "registry:ui",
      "target": "~/components/ui/ValidationMessage.tsx"
    },
    {
      "path": "components/ui/validation-message.module.css",
      "content": ".message {\n  display: flex;\n  align-items: flex-start;\n  gap: 0.25rem;\n  font-size: 0.8125rem;\n  line-height: 1.4;\n}\n\n.icon {\n  flex-shrink: 0;\n  margin-top: 0.125rem;\n}\n\n.error {\n  color: var(--component-validation-message-error-text);\n}\n\n.warning {\n  color: var(--component-validation-message-warning-text);\n}\n\n.success {\n  color: var(--component-validation-message-success-text);\n}\n\n.info {\n  color: var(--component-validation-message-info-text);\n}\n\n/* Icon rules come after type text and use .icon + type so inherited\n   message color cannot darken the glyph. */\n.icon.iconError {\n  color: var(--component-validation-message-text);\n}\n\n.icon.iconWarning {\n  color: var(--semantic-feedback-warning);\n}\n\n.icon.iconSuccess {\n  color: var(--semantic-feedback-success);\n}\n\n.icon.iconInfo {\n  color: var(--semantic-feedback-info);\n}\n",
      "type": "registry:ui",
      "target": "~/components/ui/validation-message.module.css"
    },
    {
      "path": "lib/cn.ts",
      "content": "export function cn(...classes: Array<string | false | null | undefined>): string {\n  return classes.filter(Boolean).join(\" \");\n}\n",
      "type": "registry:lib",
      "target": "~/lib/cn.ts"
    }
  ]
}
