{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "checkbox",
  "title": "Checkbox",
  "description": "An animated checkbox: the box springs on hover and press, fills with the lead colour, and the tick draws itself in.",
  "dependencies": [
    "radix-ui",
    "motion",
    "class-variance-authority"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/items/checkbox/checkbox.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\";\nimport {\n  motion,\n  useReducedMotionConfig,\n  type HTMLMotionProps,\n} from \"motion/react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * A checkbox whose tick draws itself in. Radix underneath (keyboard, form\n * value, `indeterminate`), a motion button on top: it grows a touch on hover,\n * dips on press, and the check stroke traces from nothing once the fill has\n * landed. Checked is the theme's `lead`, never a brand green.\n *\n * It renders a `<button>`, so pair it with `<label htmlFor>` pointing at its\n * `id`; wrapping it in a label is not enough for every screen reader.\n */\n\nconst checkboxVariants = cva(\n  [\n    \"peer flex shrink-0 items-center justify-center border border-rule bg-card text-on-solid outline-none\",\n    \"transition-colors duration-500\",\n    \"focus-visible:ring-2 focus-visible:ring-lead/30 focus-visible:ring-offset-2 focus-visible:ring-offset-card\",\n    \"aria-invalid:border-stop aria-invalid:ring-2 aria-invalid:ring-stop/20\",\n    \"disabled:cursor-not-allowed disabled:opacity-50\",\n    \"data-[state=checked]:border-lead data-[state=checked]:bg-lead\",\n    \"data-[state=indeterminate]:border-lead data-[state=indeterminate]:bg-lead\",\n    // A 44px hit area on a touch screen; the box itself stays small.\n    \"pointer-coarse:relative pointer-coarse:after:absolute pointer-coarse:after:top-1/2 pointer-coarse:after:left-1/2 pointer-coarse:after:size-[max(100%,44px)] pointer-coarse:after:-translate-x-1/2 pointer-coarse:after:-translate-y-1/2 pointer-coarse:after:content-['']\",\n  ],\n  {\n    variants: {\n      size: {\n        sm: \"size-4.5 rounded-[calc(var(--inset-radius)-1px)]\",\n        default: \"size-5 rounded-[calc(var(--inset-radius)-1px)]\",\n        lg: \"size-6 rounded-inset\",\n      },\n    },\n    defaultVariants: { size: \"sm\" },\n  },\n);\n\nconst indicatorSizes = {\n  sm: \"size-3\",\n  default: \"size-3.5\",\n  lg: \"size-4\",\n} as const;\n\ntype CheckedState = boolean | \"indeterminate\";\n\nexport type CheckboxProps = Omit<\n  HTMLMotionProps<\"button\">,\n  \"value\" | \"checked\" | \"defaultChecked\"\n> &\n  Omit<\n    React.ComponentProps<typeof CheckboxPrimitive.Root>,\n    \"asChild\" | keyof HTMLMotionProps<\"button\">\n  > &\n  VariantProps<typeof checkboxVariants> & {\n    checked?: CheckedState;\n    defaultChecked?: CheckedState;\n    onCheckedChange?: (checked: CheckedState) => void;\n    value?: string;\n  };\n\nexport function Checkbox({\n  className,\n  size,\n  checked,\n  defaultChecked,\n  onCheckedChange,\n  disabled,\n  required,\n  name,\n  value,\n  ...props\n}: CheckboxProps) {\n  const reduceMotion = useReducedMotionConfig();\n  const [inner, setInner] = React.useState<CheckedState>(defaultChecked ?? false);\n  const isChecked = checked !== undefined ? checked : inner;\n\n  function handleChange(next: CheckedState) {\n    setInner(next);\n    onCheckedChange?.(next);\n  }\n\n  return (\n    <CheckboxPrimitive.Root\n      checked={isChecked}\n      onCheckedChange={handleChange}\n      disabled={disabled}\n      required={required}\n      name={name}\n      value={value}\n      {...{ asChild: true }}\n    >\n      <motion.button\n        data-slot=\"checkbox\"\n        whileTap={reduceMotion ? undefined : { scale: 0.95 }}\n        whileHover={reduceMotion ? undefined : { scale: 1.05 }}\n        className={cn(checkboxVariants({ size }), className)}\n        {...props}\n      >\n        <CheckboxPrimitive.Indicator forceMount {...{ asChild: true }}>\n          <motion.svg\n            data-slot=\"checkbox-indicator\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            fill=\"none\"\n            viewBox=\"0 0 24 24\"\n            strokeWidth=\"3.5\"\n            stroke=\"currentColor\"\n            aria-hidden=\"true\"\n            className={indicatorSizes[size ?? \"sm\"]}\n            initial=\"unchecked\"\n            animate={isChecked ? \"checked\" : \"unchecked\"}\n          >\n            {isChecked === \"indeterminate\" ? (\n              <motion.line\n                x1=\"5\"\n                y1=\"12\"\n                x2=\"19\"\n                y2=\"12\"\n                strokeLinecap=\"round\"\n                initial={{ pathLength: 0, opacity: 0 }}\n                animate={{\n                  pathLength: 1,\n                  opacity: 1,\n                  transition: { duration: reduceMotion ? 0 : 0.2 },\n                }}\n              />\n            ) : (\n              <motion.path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                d=\"M4.5 12.75l6 6 9-13.5\"\n                variants={{\n                  checked: {\n                    pathLength: 1,\n                    opacity: 1,\n                    transition: reduceMotion\n                      ? { duration: 0 }\n                      : { duration: 0.2, delay: 0.2 },\n                  },\n                  unchecked: {\n                    pathLength: 0,\n                    opacity: 0,\n                    transition: { duration: reduceMotion ? 0 : 0.2 },\n                  },\n                }}\n              />\n            )}\n          </motion.svg>\n        </CheckboxPrimitive.Indicator>\n      </motion.button>\n    </CheckboxPrimitive.Root>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "meta": {
    "kind": "primitive",
    "whenToUse": "Use for any yes/no or multi-select choice instead of a native checkbox, which ignores theme tokens. Pair it with a <label htmlFor>; for a single on/off setting that takes effect immediately, a switch reads better.",
    "origin": {
      "project": "180Connect",
      "path": "src/components/ui/filed-checkbox.tsx"
    },
    "credits": [
      {
        "name": "Animate UI (Radix Checkbox)",
        "url": "https://animate-ui.com",
        "license": "MIT"
      }
    ]
  },
  "type": "registry:ui"
}
