# Radio
> Radio is an input control that lets users select a single value from several options.

## Import

```js
import { Radio, RadioGroup } from '@gemini-suite/vera-react';
```

## Examples

### Basic

<Callout variant="tip">

Prefer placing radios underneath one another (vertically stacked) to aid in a user’s ability to scan the form.

</Callout>

```jsx
<Flex flow="column" gap="spacingS">
  <Radio.Root defaultChecked={false}>
    <Radio.Indicator />
    <Radio.Label>{'Unchecked'}</Radio.Label>
  </Radio.Root>
  <Radio.Root defaultChecked={true}>
    <Radio.Indicator />
    <Radio.Label>{'Checked'}</Radio.Label>
  </Radio.Root>
  <Radio.Root isDisabled>
    <Radio.Indicator />
    <Radio.Label>{'Disabled'}</Radio.Label>
  </Radio.Root>
  <Radio.Root defaultChecked={true} isDisabled>
    <Radio.Indicator />
    <Radio.Label>{'Checked + disabled'}</Radio.Label>
  </Radio.Root>
</Flex>
```

### Controlled

It is most common to set up `Radio` as a [controlled component](https://reactjs.org/docs/forms.html#controlled-components), meaning that React state drives its value. To achieve this you must provide `isChecked` and `onChange` properties.

<Callout variant="tip">

The `defaultChecked` prop will have no effect in a controlled radio.

</Callout>

```jsx
() => {
  const [value, setValue] = React.useState('b');
  const handleChange = event => setValue(event.target.value);

  return (
    <Flex flow="column" gap="spacingXs">
      <Radio.Root value="a" isChecked={value === 'a'} onChange={handleChange}>
        <Radio.Indicator />
        <Radio.Label>{'Choice A'}</Radio.Label>
      </Radio.Root>
      <Radio.Root value="b" isChecked={value === 'b'} onChange={handleChange}>
        <Radio.Indicator />
        <Radio.Label>{'Choice B'}</Radio.Label>
      </Radio.Root>
    </Flex>
  );
};
```

### RadioGroup

`Radio` should always appear in groups of 2 or more. Use `RadioGroup` component to wrap multiple, related options.

`RadioGroup` helps managing the checked state of its children `Radio` components and conveniently passes some shared props to each.

<Callout variant="tip">

Make sure to pass `value` prop to each `Radio` within a group.

</Callout>

<Callout variant="important">

Include at most 6 options in a group. Radios can facilitate the comparison of choice, but if there's a chance the group might later expand to include more than 6 options, use [Select
component](/components/forms/select) instead, which allows the user to choose between a larger set of options.

</Callout>

<Callout variant="tip">

Use the same `name` attribute on all radios in the group. It's recommended to pass the `name` prop to the `RadioGroup`, instead of passing it to each `Radio` component. This ensures that the same `name` is given for all `<RadioGroup>` inputs.

</Callout>

```jsx
<RadioGroup
  defaultValue={'dragon_fruit'}
  onChange={value => console.log(value)}
>
  <Flex flow="column" gap="spacingXs">
    <Radio.Root value="gooseberries">
      <Radio.Indicator />
      <Radio.Label>{'Gooseberries'}</Radio.Label>
    </Radio.Root>
    <Radio.Root value="dragon_fruit">
      <Radio.Indicator />
      <Radio.Label>{'Dragon Fruit'}</Radio.Label>
    </Radio.Root>
    <Radio.Root value="watermelon">
      <Radio.Indicator />
      <Radio.Label>{'Watermelon'}</Radio.Label>
    </Radio.Root>
  </Flex>
</RadioGroup>
```

Mark the radio group as disabled by passing `true` to the `isDisabled` prop. All descendant inputs will be disabled.

```jsx
<RadioGroup isDisabled defaultValue={'dragon_fruit'}>
  <Flex flow="column" gap="spacingXs">
    <Radio.Root value="gooseberries">
      <Radio.Indicator />
      <Radio.Label>{'Gooseberries'}</Radio.Label>
    </Radio.Root>
    <Radio.Root value="dragon_fruit">
      <Radio.Indicator />
      <Radio.Label>{'Dragon Fruit'}</Radio.Label>
    </Radio.Root>
    <Radio.Root value="watermelon">
      <Radio.Indicator />
      <Radio.Label>{'Watermelon'}</Radio.Label>
    </Radio.Root>
  </Flex>
</RadioGroup>
```

### Radio with help text

In cases where the radio requires additional context, you can display this information as help text. This helps keep radio labels concise.

<Callout variant="tip">

Avoid lengthy text labels. Be clear and brief with radio labels so they are easily scanned.

</Callout>

```jsx
<Radio.Root defaultChecked>
  <Radio.Indicator />
  <Flex flow="column" gap="none">
    <Radio.Label>Label</Radio.Label>
    <Radio.HelperText>Details about the option.</Radio.HelperText>
  </Flex>
</Radio.Root>
```

### With Form Field

[Form Field component](/components/forms/form-field) should be used to label groups of related options. The same goes for connecting helper text and/or validation feedback message.

<Callout variant="tip">

When providing a top-level label for a group of radio inputs that are already labelled, it doesn't make sense for the `FormField.Label` to render an HTML `<label>` element. The `as` prop should be provided with another element type, such as `span`.

</Callout>

```jsx
<FormField.Root as={Flex} flow="column">
  <FormField.Label as="span">
    Which time slot works best for you?
  </FormField.Label>
  <FormField.HelperText>
    Select all the options that apply.
  </FormField.HelperText>
  <RadioGroup defaultValue="monday">
    <Flex flow="column" gap="spacingXs">
      <Radio.Root value="monday">
        <Radio.Indicator />
        <Flex flow="column" gap="none">
          <Radio.Label>Monday</Radio.Label>
          <Radio.HelperText>Morning and afternoon</Radio.HelperText>
        </Flex>
      </Radio.Root>
      <Radio.Root value="tuesday">
        <Radio.Indicator />
        <Flex flow="column" gap="none">
          <Radio.Label>Tuesday</Radio.Label>
          <Radio.HelperText>Morning, afternoon, and evening</Radio.HelperText>
        </Flex>
      </Radio.Root>
      <Radio.Root value="wednesday">
        <Radio.Indicator />
        <Flex flow="column" gap="none">
          <Radio.Label>Wednesday</Radio.Label>
          <Radio.HelperText>Evening only</Radio.HelperText>
        </Flex>
      </Radio.Root>
    </Flex>
  </RadioGroup>
</FormField.Root>
```

<Callout variant="important">

Don't validate each option in a group, always treat validation on the group as a whole.

</Callout>

```jsx
() => {
  const [groupValue, setGroupValue] = React.useState();

  return (
    <FormField.Root
      as={Flex}
      flow="column"
      isRequired
      validationStatus={!groupValue ? 'error' : undefined}
    >
      <FormField.Label as="span">What is your favorite food?</FormField.Label>
      <RadioGroup value={groupValue} onChange={setGroupValue}>
        <Flex flow="column" gap="spacingXs">
          <Radio.Root value="pizza">
            <Radio.Indicator />
            <Radio.Label>Pizza</Radio.Label>
          </Radio.Root>
          <Radio.Root value="curry">
            <Radio.Indicator />
            <Radio.Label>Curry</Radio.Label>
          </Radio.Root>
          <Radio.Root value="sushi">
            <Radio.Indicator />
            <Radio.Label>Sushi</Radio.Label>
          </Radio.Root>
        </Flex>
      </RadioGroup>
      <FormField.FeedbackMessage>
        <FormField.FeedbackIcon />
        {'You must choose at least one food type.'}
      </FormField.FeedbackMessage>
    </FormField.Root>
  );
};
```

### Sizes

`Radio` component comes in two different sizes: `medium` and `small`. By default, it uses `medium` size.

```jsx
<Flex>
  <Radio.Root>
    <Radio.Indicator />
    <Flex flow="column" gap="none">
      <Radio.Label>Default</Radio.Label>
      <Radio.HelperText>Additional details.</Radio.HelperText>
    </Flex>
  </Radio.Root>
  <Radio.Root size="small">
    <Radio.Indicator />
    <Flex flow="column" gap="none">
      <Radio.Label>Small</Radio.Label>
      <Radio.HelperText>Additional details.</Radio.HelperText>
    </Flex>
  </Radio.Root>
</Flex>
```

#### Size inheritance

`Radio` automatically inherits size, when placed inside a [FormField component](/components/forms/form-field).

```jsx
() => {
  return (
    <Flex cross="start" gap="spacingXl" wrap="wrap">
      <FormField.Root as={Flex} flow="column">
        <FormField.Label as="span">
          Which time slot works best for you?
        </FormField.Label>
        <FormField.HelperText>
          Select all the options that apply.
        </FormField.HelperText>
        <RadioGroup defaultValue="monday">
          <Flex flow="column" gap="spacingXs">
            <Radio.Root value="monday">
              <Radio.Indicator />
              <Flex flow="column" gap="none">
                <Radio.Label>Monday</Radio.Label>
                <Radio.HelperText>Morning and afternoon</Radio.HelperText>
              </Flex>
            </Radio.Root>
            <Radio.Root value="tuesday">
              <Radio.Indicator />
              <Flex flow="column" gap="none">
                <Radio.Label>Tuesday</Radio.Label>
                <Radio.HelperText>
                  Morning, afternoon, and evening
                </Radio.HelperText>
              </Flex>
            </Radio.Root>
            <Radio.Root value="wednesday">
              <Radio.Indicator />
              <Flex flow="column" gap="none">
                <Radio.Label>Wednesday</Radio.Label>
                <Radio.HelperText>Evening only</Radio.HelperText>
              </Flex>
            </Radio.Root>
          </Flex>
        </RadioGroup>
      </FormField.Root>
      <FormField.Root as={Flex} flow="column" size="small">
        <FormField.Label as="span">
          Which time slot works best for you?
        </FormField.Label>
        <FormField.HelperText>
          Select all the options that apply.
        </FormField.HelperText>
        <RadioGroup defaultValue="monday">
          <Flex flow="column" gap="none">
            <Radio.Root value="monday">
              <Radio.Indicator />
              <Flex flow="column" gap="none">
                <Radio.Label>Monday</Radio.Label>
                <Radio.HelperText>Morning and afternoon</Radio.HelperText>
              </Flex>
            </Radio.Root>
            <Radio.Root value="tuesday">
              <Radio.Indicator />
              <Flex flow="column" gap="none">
                <Radio.Label>Tuesday</Radio.Label>
                <Radio.HelperText>
                  Morning, afternoon, and evening
                </Radio.HelperText>
              </Flex>
            </Radio.Root>
            <Radio.Root value="wednesday">
              <Radio.Indicator />
              <Flex flow="column" gap="none">
                <Radio.Label>Wednesday</Radio.Label>
                <Radio.HelperText>Evening only</Radio.HelperText>
              </Flex>
            </Radio.Root>
          </Flex>
        </RadioGroup>
      </FormField.Root>
    </Flex>
  );
};
```

### Customizing appearance

`Radio` API allows you to easily implement custom behaviours and appearances.

```jsx
() => {
  const [groupValue, setGroupValue] = React.useState();
  const customStyles = {
    borderRadius: '$m',
    padding: '$spacingM',
    border: '1px solid $borderNeutralSubtle'
  };

  return (
    <RadioGroup value={groupValue} onChange={setGroupValue}>
      <AutoGrid min="20ch">
        <Radio.Root
          as="label"
          value="item1"
          gap="spacingM"
          css={{
            ...customStyles,
            backgroundColor:
              groupValue === 'item1'
                ? '$backgroundAccent'
                : '$backgroundNeutralMinimal'
          }}
        >
          <Radio.Indicator />
          <Flex flow="column" gap="spacingXs">
            <Radio.Label as={Flex} gap="spacingS">
              <Box>Choice A</Box>
              <Label size="small" color="success" variant="subtle">
                Label
              </Label>
            </Radio.Label>
            <Radio.HelperText>
              Extra information about the choice A
            </Radio.HelperText>
          </Flex>
        </Radio.Root>
        <Radio.Root
          as="label"
          value="item2"
          gap="spacingM"
          css={{
            ...customStyles,
            backgroundColor:
              groupValue === 'item2'
                ? '$backgroundAccent'
                : '$backgroundNeutralMinimal'
          }}
        >
          <Radio.Indicator />
          <Flex flow="column" gap="spacingXs">
            <Radio.Label as={Flex} gap="spacingS">
              <Box>Choice B</Box>
              <Label size="small" color="success" variant="subtle">
                Label
              </Label>
            </Radio.Label>
            <Radio.HelperText>
              Extra information about the choice B
            </Radio.HelperText>
          </Flex>
        </Radio.Root>
      </AutoGrid>
    </RadioGroup>
  );
};
```

## API Reference

### Radio.Root

<Callout variant="tip">

In addition to the props below, you can pass [Flex props](/components/layout/flex#api-reference) to control the layout.

</Callout>

| Name               | Type                                                      | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ------------------ | --------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`               | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `div`   | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`              | `StitchesCss`                                             |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |
| `value`            | `string \| number`                                        |         | The value of the radio input element. It will be returned on form submission.                                                                                                                                                                                                                |          |
| `name`             | `string`                                                  |         | Name attribute of the radio input element. Useful for form submission.                                                                                                                                                                                                                       |          |
| `id`               | `string`                                                  |         | ID assigned to input. Used for `htmlFor` of `Radio.Label`. Defaults to a generated ID.                                                                                                                                                                                                       |          |
| `defaultChecked`   | `boolean`                                                 | `false` | If `true` the radio will be initially checked.                                                                                                                                                                                                                                               |          |
| `isChecked`        | `boolean`                                                 |         | When `true`, the radio will be checked. This makes the radio controlled.                                                                                                                                                                                                                     |          |
| `onChange`         | `(event: React.ChangeEvent<HTMLInputElement>) => void`    |         | Event handler called when the input checked state changes.                                                                                                                                                                                                                                   |          |
| `onFocus`          | `(event: React.FocusEvent<HTMLInputElement>) => void`     |         | Event handler called when the input receives a focus.                                                                                                                                                                                                                                        |          |
| `onBlur`           | `(event: React.FocusEvent<HTMLInputElement>) => void`     |         | Event handler called when focus has left the input.                                                                                                                                                                                                                                          |          |
| `isDisabled`       | `boolean`                                                 |         | When `true`, the radio will be disabled, preventing the user from interacting with it.                                                                                                                                                                                                       |          |
| `isReadOnly`       | `boolean`                                                 |         | When `true`, the radio will be readonly.                                                                                                                                                                                                                                                     |          |
| `isRequired`       | `boolean`                                                 |         | When `true`, the radio input is marked as required.                                                                                                                                                                                                                                          |          |
| `validationStatus` | `"error" \| "success" \| "warning"`                       |         | Styles the radio to match the status.                                                                                                                                                                                                                                                        |          |
| `size`             | `"medium" \| "small"`                                     |         | Size of the radio.                                                                                                                                                                                                                                                                           |          |

### Radio.Indicator

| Name  | Type          | Default | Description                                                                                                                                                                                                                                   | Required |
| ----- | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css` | `StitchesCss` |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |

### Radio.Label

| Name  | Type                                                      | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ----- | --------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`  | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `label` | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css` | `StitchesCss`                                             |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |

### Radio.HelperText

<Callout variant="tip">

In addition to the props below, you can pass [Text props](/components/typography/text#api-reference).

</Callout>

| Name  | Type          | Default | Description                                                                                                                                                                                                                                   | Required |
| ----- | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css` | `StitchesCss` |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |

### RadioGroup

| Name           | Type                                | Default | Description                                                                                                       | Required |
| -------------- | ----------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------- | -------- |
| `defaultValue` | `string \| number`                  |         | Initial value of the radio group. Radio, inside the group, with that value will be checked by default             |          |
| `value`        | `string \| number`                  |         | Value of the radio group. This makes the group controlled, so passing `onChange` is required to update the value. |          |
| `name`         | `string`                            |         | The `name` attribute given for all radio inputs in the group. Useful for form submission.                         |          |
| `onChange`     | `(value: string \| number) => void` |         | Event handler called when any children `Radio` is checked or unchecked.                                           |          |
| `isDisabled`   | `boolean`                           |         | When `true`, all radio inputs within the group will be disabled.                                                  |          |
