# Field: Radio Group (category: selection)

URL: https://docs.forms.saastro.io/docs/radio

<FieldPreview name="radio" description="Interactive demo of radio group field" />

## Overview

The radio group field allows users to select exactly one option from a list. Use it when users need to see all options at once and make a single selection.

## Usage

### Basic Radio Group

```tsx

const config = FormBuilder.create('survey')
  .addField('satisfaction', (f) =>
    f
      .type('radio')
      .label('How satisfied are you?')
      .options([
        { label: 'Very satisfied', value: 'very-satisfied' },
        { label: 'Satisfied', value: 'satisfied' },
        { label: 'Neutral', value: 'neutral' },
        { label: 'Dissatisfied', value: 'dissatisfied' },
      ])
      .required('Please select an option'),
  )
  .addStep('main', ['satisfaction'])
  .build();
```

### With Default Value

```tsx
.addField('plan', (f) =>
  f.type('radio')
    .label('Select a plan')
    .options([
      { label: 'Free', value: 'free' },
      { label: 'Pro', value: 'pro' },
      { label: 'Enterprise', value: 'enterprise' },
    ])
    .value('pro')
    .required()
)
```

### With Descriptions

```tsx
.addField('shipping', (f) =>
  f.type('radio')
    .label('Shipping method')
    .options([
      { label: 'Standard', value: 'standard', description: '5-7 business days' },
      { label: 'Express', value: 'express', description: '2-3 business days' },
      { label: 'Overnight', value: 'overnight', description: 'Next business day' },
    ])
    .required()
)
```

### JSON Configuration

```json
{
  "type": "radio",
  "label": "Select a plan",
  "options": [
    { "label": "Free", "value": "free" },
    { "label": "Pro", "value": "pro" },
    { "label": "Enterprise", "value": "enterprise" }
  ],
  "value": "pro",
  "schema": { "required": true }
}
```

## Props

| Prop               | Type                                                  | Default | Description                       |
| ------------------ | ----------------------------------------------------- | ------- | --------------------------------- |
| `type`             | `'radio'`                                             | -       | Field type (required)             |
| `label`            | `string`                                              | -       | Group label                       |
| `options`          | `Option[]`                                            | -       | Array of options                  |
| `value`            | `string`                                              | -       | Default selected value            |
| `optionsClassName` | `string`                                              | -       | CSS classes for options container |
| `columns`          | `Partial<Record<Breakpoint, number>>`                 | -       | Grid columns by breakpoint        |
| `disabled`         | `boolean \| function \| ConditionGroup`               | `false` | Disable all options               |
| `hidden`           | `boolean \| function \| ConditionGroup \| Responsive` | `false` | Hide the field                    |

### Option Object

| Property      | Type      | Description          |
| ------------- | --------- | -------------------- |
| `label`       | `string`  | Display text         |
| `value`       | `string`  | Value when selected  |
| `description` | `string`  | Optional description |
| `disabled`    | `boolean` | Disable this option  |

## Validation

### Required Selection

```tsx
.addField('gender', (f) =>
  f.type('radio')
    .label('Gender')
    .options([
      { label: 'Male', value: 'male' },
      { label: 'Female', value: 'female' },
      { label: 'Other', value: 'other' },
      { label: 'Prefer not to say', value: 'none' },
    ])
    .required('Please select an option')
)
```

## Conditional Logic

### Show options based on another field

```tsx
.addField('paymentMethod', (f) =>
  f.type('radio')
    .label('Payment method')
    .options([
      { label: 'Credit Card', value: 'card' },
      { label: 'PayPal', value: 'paypal' },
      { label: 'Bank Transfer', value: 'bank' },
    ])
    .hidden((values) => values.total === 0)
)
```

## Styling

### Custom Classes

```tsx
.addField('plan', (f) =>
  f.type('radio')
    .label('Select a plan')
    .options([...])
    .required()
    .classNames({
      wrapper: 'bg-muted/30 p-4 rounded-lg',
      label: 'text-lg font-semibold',
      error: 'text-destructive',
    })
)
```

### Options Layout

Control how options are arranged using `optionsClassName`:

```json
{
  "type": "radio",
  "label": "Plan",
  "optionsClassName": "grid grid-cols-1 md:grid-cols-3 gap-4",
  "options": [...]
}
```

### Responsive Layout

```tsx
.addField('plan', (f) =>
  f.type('radio')
    .label('Select a plan')
    .options([...])
    .columns({ default: 12, md: 6 })
)
```

### JSON Styling

```json
{
  "type": "radio",
  "label": "Plan",
  "wrapper_className": "bg-muted/30 p-4 rounded-lg",
  "label_className": "text-lg font-semibold",
  "optionsClassName": "space-y-3",
  "columns": { "default": 12, "md": 6 }
}
```

## Related Fields

- [Select](/docs/select) - Dropdown for many options
- [Button Radio](/docs/button-radio) - Radio styled as buttons
- [Checkbox Group](/docs/checkbox-group) - Multiple selection

## Radio vs Select

| Use Radio                 | Use Select       |
| ------------------------- | ---------------- |
| 2-5 options               | 6+ options       |
| Options need visibility   | Space is limited |
| Options have descriptions | Simple list      |
| Important decision        | Quick selection  |

## Accessibility

- Uses Radix UI RadioGroup for accessibility
- Supports keyboard navigation (Arrow keys)
- Proper ARIA roles and labels
- Focus visible states
- Screen reader announcements
