{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "radio",
  "type": "registry:ui",
  "title": "Radio group",
  "description": "One choice from a short list: round wells beside their labels; pressing darkens the well, releasing latches a pip in on the part spring while the old choice's pip drops out (the preset-button interlock).",
  "dependencies": [
    "@base-ui/react@^1.8.0"
  ],
  "registryDependencies": [
    "https://metalui.dev/r/tokens.json"
  ],
  "files": [
    {
      "path": "packages/metalui/src/components/radio/radio.tsx",
      "type": "registry:ui",
      "target": "components/metalui/radio/radio.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { RadioGroup as BaseRadioGroup } from '@base-ui/react/radio-group';\nimport { Radio as BaseRadio } from '@base-ui/react/radio';\n\n/* ─────────────────────────────────────────────────────────\n * RADIO GROUP, one choice from a short list, on Base UI RadioGroup and Radio\n *\n * Each option is the checkbox's well made round, beside its label; the whole row is the hit area.\n *\n *   rest      a recessed round well\n *   hover     the well darkens a step (unchosen only)\n *   pressed   the well turns to the on look at once (press time): the key is already going down\n *   chosen    releasing latches a white pip in on the part spring; the pip of the one chosen\n *             before drops out on the release spring in the same frame (the preset-button interlock)\n *   cancel    press and drag off: nothing latches and the well fades back\n *   focus     the green ring on the well (keyboard only); arrows move and choose, with no press\n *   invalid   a red hairline ring (inside a Base UI Field marked invalid)\n *   disabled  the whole row at 40 %, no hover, no press\n * Reduce Motion: the pip is there or not at once; the well colour still fades.\n * The well's look is the checkbox recipe; the radio recipe adds the pip, the row and the motion.\n * ───────────────────────────────────────────────────────── */\n\nexport interface RadioGroupProps extends Omit<BaseRadioGroup.Props, 'className'> {\n  /** vertical (the default) stacks the options; horizontal sets them in a line. */\n  orientation?: 'vertical' | 'horizontal';\n  className?: string;\n}\n\nexport interface RadioProps extends Omit<BaseRadio.Root.Props, 'className' | 'children' | 'render'> {\n  /** The option's label, beside the well. */\n  children?: React.ReactNode;\n  className?: string;\n}\n\nconst GROUP = {\n  vertical: 'flex flex-col gap-radio-group-gap',\n  horizontal: 'flex flex-row flex-wrap gap-x-radio-group-gap-across gap-y-radio-group-gap',\n};\nconst ROW = 'mu-radio group/radio inline-flex items-center gap-radio-row-gap min-h-radio-row-height type-ui text-ink cursor-pointer tap-highlight-none select-none has-data-disabled:cursor-default has-data-disabled:opacity-radio-disabled';\nconst WELL = [\n  'mu-radio-well relative box-border inline-flex flex-none items-center justify-center size-radio-size rounded-full p-0 border-0 outline-none',\n  'recipe-checkbox transition-radio focus-visible:focus-ring',\n  'data-checked:recipe-checkbox-on',\n  // Hover and press come from the whole row, and only while the option can still be chosen.\n  'not-data-checked:not-data-disabled:not-data-readonly:group-hover/radio:recipe-checkbox-hover',\n  'not-data-checked:not-data-disabled:not-data-readonly:group-active/radio:recipe-checkbox-on not-data-checked:not-data-disabled:not-data-readonly:group-active/radio:duration-radio-press',\n  'data-invalid:not-data-checked:invalid-ring',\n].join(' ');\nconst PIP = 'mu-radio-pip radio-pip data-checked:radio-pip-on reduced-motion:transition-none';\n\n/** One choice from a short list. Wrap `Radio` options; `value` and `onValueChange` hold the choice. */\nfunction Root({ orientation = 'vertical', className, ...props }: RadioGroupProps) {\n  return <BaseRadioGroup data-orientation={orientation} className={className ? `${GROUP[orientation]} ${className}` : GROUP[orientation]} {...props} />;\n}\n\n/** One option: the round well and its label. The label is part of the hit area. */\nconst Item = React.forwardRef<HTMLSpanElement, RadioProps>(function Radio({ children, className, ...props }, ref) {\n  return (\n    <label className={className ? `${ROW} ${className}` : ROW}>\n      <BaseRadio.Root ref={ref} className={WELL} {...props}>\n        <BaseRadio.Indicator keepMounted className={PIP} />\n      </BaseRadio.Root>\n      {children != null && <span className=\"mu-radio-label\">{children}</span>}\n    </label>\n  );\n});\n\nexport const RadioGroup = Object.assign(Root, { Item, Root });\nexport const Radio = Item;\n"
    }
  ],
  "docs": "Agent guide: https://metalui.dev/r/radio.md. SwiftUI: MetalRadioGroup in the MetalUI Swift package."
}
