Saltar al contenido
VEXA
Formularios

RadioGroup

Hoja cliente

A set of mutually exclusive options.

Vista previa en vivo

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

Escritorio
Plan

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/radio-group.json

Se instala en components/vexa/radio-group.tsx

Dependencias npm

  • @radix-ui/react-radio-group

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/radio-group.tsx
"use client";

import type * as React from "react";
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";

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

/**
 * RadioGroup — a set of mutually exclusive options.
 *
 * Client leaf. Radix provides the `radiogroup`/`radio` roles and the APG roving
 * focus model: Arrow keys move between and select options, Tab moves in and out
 * of the group. Give the group an accessible name with `aria-label` or
 * `aria-labelledby`, and associate each item with a `<Label htmlFor>`.
 */
export function RadioGroup({
  className,
  ...props
}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
  return (
    <RadioGroupPrimitive.Root
      data-slot="radio-group"
      className={cn("grid gap-2.5", className)}
      {...props}
    />
  );
}

export function RadioGroupItem({
  className,
  ...props
}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
  return (
    <RadioGroupPrimitive.Item
      data-slot="radio-group-item"
      className={cn(
        "aspect-square size-5 shrink-0 rounded-full border border-vexa-input bg-vexa-surface-raised shadow-vexa-sm",
        "transition-[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",
        "aria-[invalid=true]:border-vexa-danger",
        className,
      )}
      {...props}
    >
      <RadioGroupPrimitive.Indicator
        data-slot="radio-group-indicator"
        className="flex items-center justify-center"
      >
        <span className="size-2.5 rounded-full bg-vexa-primary" />
      </RadioGroupPrimitive.Indicator>
    </RadioGroupPrimitive.Item>
  );
}
JSON del registryr/radio-group.json
r/radio-group.json
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "radio-group",
  "type": "registry:ui",
  "title": "RadioGroup",
  "description": "A set of mutually exclusive options.",
  "dependencies": [
    "@radix-ui/react-radio-group"
  ],
  "registryDependencies": [
    "@vexa/utils"
  ],
  "files": [
    {
      "path": "registry/default/ui/radio-group.tsx",
      "type": "registry:ui",
      "target": "components/vexa/radio-group.tsx",
      "content": "\"use client\";\n\nimport type * as React from \"react\";\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * RadioGroup — a set of mutually exclusive options.\n *\n * Client leaf. Radix provides the `radiogroup`/`radio` roles and the APG roving\n * focus model: Arrow keys move between and select options, Tab moves in and out\n * of the group. Give the group an accessible name with `aria-label` or\n * `aria-labelledby`, and associate each item with a `<Label htmlFor>`.\n */\nexport function RadioGroup({\n  className,\n  ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n  return (\n    <RadioGroupPrimitive.Root\n      data-slot=\"radio-group\"\n      className={cn(\"grid gap-2.5\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function RadioGroupItem({\n  className,\n  ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n  return (\n    <RadioGroupPrimitive.Item\n      data-slot=\"radio-group-item\"\n      className={cn(\n        \"aspect-square size-5 shrink-0 rounded-full border border-vexa-input bg-vexa-surface-raised shadow-vexa-sm\",\n        \"transition-[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\",\n        \"aria-[invalid=true]:border-vexa-danger\",\n        className,\n      )}\n      {...props}\n    >\n      <RadioGroupPrimitive.Indicator\n        data-slot=\"radio-group-indicator\"\n        className=\"flex items-center justify-center\"\n      >\n        <span className=\"size-2.5 rounded-full bg-vexa-primary\" />\n      </RadioGroupPrimitive.Indicator>\n    </RadioGroupPrimitive.Item>\n  );\n}\n"
    }
  ],
  "meta": {
    "frameworks": [
      "react",
      "next"
    ],
    "rsc": "client",
    "exports": [
      "RadioGroup",
      "RadioGroupItem"
    ],
    "cssVars": [
      "--vexa-input",
      "--vexa-surface-raised",
      "--vexa-primary",
      "--vexa-ring",
      "--vexa-danger",
      "--vexa-background"
    ],
    "a11y": "APG radiogroup model: Arrow keys move and select, Tab enters/exits the group. Give the group a name via aria-label/aria-labelledby and label each item.",
    "example": "<RadioGroup defaultValue=\"a\" aria-label=\"Plan\"><div className=\"flex items-center gap-2\"><RadioGroupItem value=\"a\" id=\"a\" /><Label htmlFor=\"a\">Starter</Label></div></RadioGroup>",
    "tests": "planned — see docs/README.md#roadmap"
  }
}

Detalles

Accesibilidad

APG radiogroup model: Arrow keys move and select, Tab enters/exits the group. Give the group a name via aria-label/aria-labelledby and label each item.