Saltar al contenido
VEXA
Formularios

Checkbox

Hoja cliente

A control that toggles a boolean or shows an indeterminate state.

Vista previa en vivo

Renderizado desde el código fuente instalado de VEXA — los mismos archivos que recibes.

Escritorio

Playground

Ajusta las props y copia el JSX equivalente.

Playground

checkbox.tsx
<Checkbox defaultChecked />

Instalación

Añade el código del componente a tu proyecto. Las dependencias del registry se resuelven automáticamente.

npx shadcn@latest add https://vexa.valfiguer.com/r/checkbox.json

Se instala en components/vexa/checkbox.tsx

Dependencias npm

  • @radix-ui/react-checkbox

Dependencias del registry

  • @vexa/utils

Otros items de VEXA que necesita este componente. Instálalos primero — la CLI los resuelve automáticamente.

Código

Cópialo a su ruta destino, o instálalo con el comando de arriba.

components/vexa/checkbox.tsx
"use client";

import type * as React from "react";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";

import { cn } from "@/lib/utils";

function CheckIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M4 12.5 9 17.5 20 6.5"
        stroke="currentColor"
        strokeWidth="2.5"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

function MinusIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
      className={className}
    >
      <path
        d="M6 12h12"
        stroke="currentColor"
        strokeWidth="2.5"
        strokeLinecap="round"
      />
    </svg>
  );
}

/**
 * Checkbox — a control that toggles a boolean, or represents an indeterminate
 * (mixed) state. Built on Radix so the role, `aria-checked` (including
 * `"mixed"`), keyboard model (Space toggles), and label association are handled.
 *
 * Client leaf: the `"use client"` boundary lives here. Pair with `<Label>` via
 * a shared `id`, or wrap the label text so a click on it toggles the control.
 * The checked/indeterminate state is conveyed by an icon, not color alone.
 */
export function Checkbox({
  className,
  ...props
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
  return (
    <CheckboxPrimitive.Root
      data-slot="checkbox"
      className={cn(
        "group peer size-5 shrink-0 rounded-vexa-sm border border-vexa-input bg-vexa-surface-raised shadow-vexa-sm",
        "transition-[color,background-color,border-color,box-shadow] duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)]",
        "outline-none focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-2 focus-visible:ring-offset-vexa-background",
        "disabled:cursor-not-allowed disabled:opacity-50",
        "data-[state=checked]:border-vexa-primary data-[state=checked]:bg-vexa-primary data-[state=checked]:text-vexa-primary-foreground",
        "data-[state=indeterminate]:border-vexa-primary data-[state=indeterminate]:bg-vexa-primary data-[state=indeterminate]:text-vexa-primary-foreground",
        "aria-[invalid=true]:border-vexa-danger",
        className,
      )}
      {...props}
    >
      <CheckboxPrimitive.Indicator
        data-slot="checkbox-indicator"
        className="flex items-center justify-center text-current"
      >
        <CheckIcon className="size-3.5 group-data-[state=indeterminate]:hidden" />
        <MinusIcon className="hidden size-3.5 group-data-[state=indeterminate]:block" />
      </CheckboxPrimitive.Indicator>
    </CheckboxPrimitive.Root>
  );
}
JSON del registryr/checkbox.json
r/checkbox.json
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "checkbox",
  "type": "registry:ui",
  "title": "Checkbox",
  "description": "A control that toggles a boolean or shows an indeterminate state.",
  "dependencies": [
    "@radix-ui/react-checkbox"
  ],
  "registryDependencies": [
    "@vexa/utils"
  ],
  "files": [
    {
      "path": "registry/default/ui/checkbox.tsx",
      "type": "registry:ui",
      "target": "components/vexa/checkbox.tsx",
      "content": "\"use client\";\n\nimport type * as React from \"react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction CheckIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      aria-hidden=\"true\"\n      className={className}\n    >\n      <path\n        d=\"M4 12.5 9 17.5 20 6.5\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2.5\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n    </svg>\n  );\n}\n\nfunction MinusIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      aria-hidden=\"true\"\n      className={className}\n    >\n      <path\n        d=\"M6 12h12\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2.5\"\n        strokeLinecap=\"round\"\n      />\n    </svg>\n  );\n}\n\n/**\n * Checkbox — a control that toggles a boolean, or represents an indeterminate\n * (mixed) state. Built on Radix so the role, `aria-checked` (including\n * `\"mixed\"`), keyboard model (Space toggles), and label association are handled.\n *\n * Client leaf: the `\"use client\"` boundary lives here. Pair with `<Label>` via\n * a shared `id`, or wrap the label text so a click on it toggles the control.\n * The checked/indeterminate state is conveyed by an icon, not color alone.\n */\nexport function Checkbox({\n  className,\n  ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n  return (\n    <CheckboxPrimitive.Root\n      data-slot=\"checkbox\"\n      className={cn(\n        \"group peer size-5 shrink-0 rounded-vexa-sm border border-vexa-input bg-vexa-surface-raised shadow-vexa-sm\",\n        \"transition-[color,background-color,border-color,box-shadow] duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)]\",\n        \"outline-none focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-2 focus-visible:ring-offset-vexa-background\",\n        \"disabled:cursor-not-allowed disabled:opacity-50\",\n        \"data-[state=checked]:border-vexa-primary data-[state=checked]:bg-vexa-primary data-[state=checked]:text-vexa-primary-foreground\",\n        \"data-[state=indeterminate]:border-vexa-primary data-[state=indeterminate]:bg-vexa-primary data-[state=indeterminate]:text-vexa-primary-foreground\",\n        \"aria-[invalid=true]:border-vexa-danger\",\n        className,\n      )}\n      {...props}\n    >\n      <CheckboxPrimitive.Indicator\n        data-slot=\"checkbox-indicator\"\n        className=\"flex items-center justify-center text-current\"\n      >\n        <CheckIcon className=\"size-3.5 group-data-[state=indeterminate]:hidden\" />\n        <MinusIcon className=\"hidden size-3.5 group-data-[state=indeterminate]:block\" />\n      </CheckboxPrimitive.Indicator>\n    </CheckboxPrimitive.Root>\n  );\n}\n"
    }
  ],
  "meta": {
    "frameworks": [
      "react",
      "next"
    ],
    "rsc": "client",
    "cssVars": [
      "--vexa-input",
      "--vexa-surface-raised",
      "--vexa-primary",
      "--vexa-primary-foreground",
      "--vexa-ring",
      "--vexa-danger",
      "--vexa-background"
    ],
    "a11y": "Radix supplies role=checkbox, aria-checked (including \"mixed\"), and Space to toggle. Checked/indeterminate shown by an icon, not color alone. Associate a <Label>.",
    "example": "<div className=\"flex items-center gap-2\"><Checkbox id=\"terms\" /><Label htmlFor=\"terms\">Accept terms</Label></div>",
    "tests": "registry/tests/checkbox.test.tsx"
  }
}

Detalles

Accesibilidad

Radix supplies role=checkbox, aria-checked (including "mixed"), and Space to toggle. Checked/indeterminate shown by an icon, not color alone. Associate a <Label>.