Agents (llms.txt)

Radio

A radio button input component.

import { Radio } from '@/components/radio';

const labelClass = 'font-medium text-base text-foreground';

export default function RadioPreview() {
  return (
    <div className="flex flex-col gap-4">
      <div className="space-y-2">
        <div className="flex items-center gap-2">
          <Radio id="option1" name="options" />
          <label className={labelClass} htmlFor="option1">
            Option 1
          </label>
        </div>
        <div className="flex items-center gap-2">
          <Radio id="option2" name="options" />
          <label className={labelClass} htmlFor="option2">
            Option 2
          </label>
        </div>
        <div className="flex items-center gap-2">
          <Radio id="option3" name="options" />
          <label className={labelClass} htmlFor="option3">
            Option 3
          </label>
        </div>
      </div>

      <div className="space-y-2">
        <div className="flex items-center gap-2">
          <Radio id="disabled" disabled />
          <label className={labelClass} htmlFor="disabled">
            Disabled
          </label>
        </div>
        <div className="flex items-center gap-2">
          <Radio id="checked-disabled" disabled defaultChecked />
          <label className={labelClass} htmlFor="checked-disabled">
            Checked & Disabled
          </label>
        </div>
      </div>
    </div>
  );
}

Source Code

import { cva } from '@/lib/utils/classnames';

type RadioVariant = 'default' | 'brand';

interface RadioProps
  extends Omit<React.ComponentPropsWithRef<'input'>, 'type'> {
  variant?: RadioVariant;
}

const radioStyle = cva({
  base: [
    'focus-visible:ring-(length:--ring-width) relative flex size-5 shrink-0 appearance-none items-center justify-center rounded-full border border-border bg-background shadow-xs outline-none ring-ring transition enabled:cursor-pointer enabled:not-checked:hover:border-mix-border/8',
    // checked circle
    'checked:before:absolute checked:before:h-1.5 checked:before:w-1.5 checked:before:rounded-full',
    // disabled
    'disabled:cursor-not-allowed disabled:border-foreground/5 disabled:bg-foreground/10 disabled:checked:before:bg-foreground/50',
  ],
  variants: {
    variant: {
      default: [
        'checked:enabled:hover:mix-with-accent-foreground checked:enabled:border-accent checked:enabled:bg-accent checked:enabled:hover:border-mix-accent/8',
        'checked:before:bg-accent-foreground',
      ],
      brand: [
        'checked:enabled:border-(--color-border-hover) checked:enabled:bg-(--color-border-hover)',
        'checked:before:bg-white',
      ],
    },
  },
  defaultVariants: { variant: 'default' },
});

const Radio = ({ className, variant, ...props }: RadioProps) => {
  return (
    <input
      type="radio"
      className={radioStyle({ variant, className })}
      {...props}
    />
  );
};

export type { RadioProps };
export { Radio };

Server component. No 'use client' — native <input type="radio"> with cva styling; forwards props only.

API Reference

Extends the input element with type="radio".

Examples

Simple

Basic usage of radio buttons.

import { Radio } from '@/components/radio';

const labelClass = 'font-medium text-base text-foreground';

export default function RadioPreview() {
  return (
    <div className="flex flex-col gap-4">
      <div className="space-y-2">
        <div className="flex items-center gap-2">
          <Radio id="option1" name="options" />
          <label className={labelClass} htmlFor="option1">
            Option 1
          </label>
        </div>
        <div className="flex items-center gap-2">
          <Radio id="option2" name="options" />
          <label className={labelClass} htmlFor="option2">
            Option 2
          </label>
        </div>
        <div className="flex items-center gap-2">
          <Radio id="option3" name="options" />
          <label className={labelClass} htmlFor="option3">
            Option 3
          </label>
        </div>
      </div>

      <div className="space-y-2">
        <div className="flex items-center gap-2">
          <Radio id="disabled" disabled />
          <label className={labelClass} htmlFor="disabled">
            Disabled
          </label>
        </div>
        <div className="flex items-center gap-2">
          <Radio id="checked-disabled" disabled defaultChecked />
          <label className={labelClass} htmlFor="checked-disabled">
            Checked & Disabled
          </label>
        </div>
      </div>
    </div>
  );
}

Best Practices

  1. Labels:

    • Use clear, concise labels
    • Make labels clickable
    • Consider label position
  2. Accessibility:

    • Ensure keyboard navigation
    • Use fieldset and legend for groups
    • Maintain sufficient spacing between options

Previous

Progress

Next

Scrubber