{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"checkbox","type":"registry:ui","title":"Checkbox","description":"Native checkbox restyled with a hand-drawn tick animation, indeterminate dash, label and description.","dependencies":[],"registryDependencies":["utils"],"files":[{"path":"registry/ui/checkbox.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { useEffect, useId, useImperativeHandle, useRef, type InputHTMLAttributes, type ReactNode, type Ref } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n// The native input *is* the box (appearance:none), so forms, labels, :checked and\n// :indeterminate all work natively. CSS draws the tick by animating the stroke.\nconst css = `\n.ui-cbx-mark path{stroke-dasharray:1;stroke-dashoffset:1;transition:stroke-dashoffset .22s cubic-bezier(.6,0,.4,1)}\n.ui-cbx:checked:not(:indeterminate)+.ui-cbx-mark .ui-cbx-tick,.ui-cbx:indeterminate+.ui-cbx-mark .ui-cbx-dash{stroke-dashoffset:0;transition-delay:.06s}\n@media (prefers-reduced-motion:reduce){.ui-cbx-mark path{transition:none}}\n`;\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"size\"> {\n  label?: ReactNode;\n  description?: ReactNode;\n  /** Mixed state (e.g. \"select all\" with some children checked). Shows a dash. */\n  indeterminate?: boolean;\n  ref?: Ref<HTMLInputElement>;\n}\n\nexport function Checkbox({ label, description, indeterminate = false, className, id, ref, ...props }: CheckboxProps) {\n  const inner = useRef<HTMLInputElement>(null);\n  const auto = useId();\n  const inputId = id ?? auto;\n  useImperativeHandle(ref, () => inner.current!, []);\n\n  // `indeterminate` has no HTML attribute; set the property. Re-applied every render\n  // because a click natively clears it.\n  useEffect(() => {\n    if (inner.current) inner.current.indeterminate = indeterminate;\n  });\n\n  const box = (\n    <span className=\"relative grid size-5 shrink-0 place-items-center transition-[scale] duration-150 has-[input:active:enabled]:scale-90 motion-reduce:transition-none\">\n      <style href=\"ui-checkbox\" precedence=\"default\">\n        {css}\n      </style>\n      <input\n        {...props}\n        ref={inner}\n        id={inputId}\n        type=\"checkbox\"\n        aria-describedby={description ? `${inputId}-d` : undefined}\n        className={cn(\n          \"ui-cbx peer absolute inset-0 m-0 cursor-pointer appearance-none rounded-[6px] border border-input bg-background shadow-xs outline-none\",\n          \"transition-[background-color,border-color,box-shadow] duration-200 hover:border-primary/60\",\n          \"checked:border-primary checked:bg-primary indeterminate:border-primary indeterminate:bg-primary\",\n          \"focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50\",\n          \"aria-invalid:border-destructive aria-invalid:ring-destructive/30\",\n          className,\n        )}\n      />\n      <svg\n        aria-hidden\n        viewBox=\"0 0 24 24\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth={3.2}\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        className=\"ui-cbx-mark pointer-events-none relative size-3.5 text-primary-foreground peer-disabled:opacity-50\"\n      >\n        <path className=\"ui-cbx-tick\" pathLength={1} d=\"M4.5 12.5l5 5L19.5 7\" />\n        <path className=\"ui-cbx-dash\" pathLength={1} d=\"M6 12h12\" />\n      </svg>\n    </span>\n  );\n\n  if (!label && !description) return box;\n\n  return (\n    <div className=\"flex items-start gap-3\">\n      {box}\n      <div className=\"grid gap-0.5 text-sm leading-5\">\n        <label\n          htmlFor={inputId}\n          className={cn(\"cursor-pointer font-medium text-foreground select-none\", props.disabled && \"cursor-not-allowed opacity-50\")}\n        >\n          {label}\n        </label>\n        {description && (\n          <p id={`${inputId}-d`} className={cn(\"text-muted-foreground\", props.disabled && \"opacity-50\")}>\n            {description}\n          </p>\n        )}\n      </div>\n    </div>\n  );\n}\n"}]}