# Radio group

Radio groups let people select a single item from a short list. Use them in layouts that offer enough space to list up to five options or if it's important to view all options at once.

## Best practices

### Do

- Use a radio group for one selection from a short list of up to five options.
- Provide a logical default selection and place it first.
- Prefer vertical alignment for scanability and localization.

### Don't

- Use a radio group when space cannot show the options; use a dropdown.
- Use a radio group for multiple selections; use checkboxes.
- Use a radio group as an immediate on/off control; use a switch.

## Behavior and states

- Present a selected option by default.
- Place the default selection first and use the most logical response.
- When tabbing, focus falls on the selected option first, or the first option when none is selected.
- Radio groups can be aligned vertically or horizontally.
- Vertical alignment is preferred for scannability and localization.
- If there isn't enough space, try a dropdown instead.
- If you need to let people select more than one option, use checkboxes.
- To let them immediately turn a setting on or off, try a switch.

## Default

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-radiogroup--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { RadioGroupProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import * as React from 'react';

export const Default = (props: Partial<RadioGroupProps>): JSXElement => (<Field label="Favorite Fruit">
    <RadioGroup {...props}>
      <Radio value="apple" label="Apple"/>
      <Radio value="pear" label="Pear"/>
      <Radio value="banana" label="Banana"/>
      <Radio value="orange" label="Orange"/>
    </RadioGroup>
  </Field>);

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### RadioGroup API

A RadioGroup component presents a set of options where only one option can be selected.

```ts
interface RadioGroupProps {
  as?: "div";

  children?: any;

  className?: string;

  /**
   * The default selected Radio item in this group.
   *
   * This should be the `value` prop of one of the Radio items inside this group.
   */
  defaultValue?: string | number | readonly string[];

  /**
   * Disable all Radio items in this group.
   */
  disabled?: boolean;

  /**
   * How the radio items are laid out in the group.
   * @default vertical
   */
  layout?: "horizontal" | "vertical" | "horizontal-stacked";

  /**
   * The name of this radio group. This name is applied to all Radio items inside this group.
   *
   * If no name is provided, one will be generated so that all of the Radio items have the same name.
   */
  name?: string;

  /**
   * Callback when the selected Radio item changes.
   */
  onChange?: ((ev: FormEvent<HTMLDivElement>, data: RadioGroupOnChangeData) => void);

  ref?: Ref<HTMLDivElement>;

  /**
   * Require a selection in this group. Adds the `required` prop to all child Radio items.
   */
  required?: boolean;

  style?: CSSProperties;

  /**
   * The selected Radio item in this group.
   *
   * This should be the `value` prop of one of the Radio items inside this group.
   */
  value?: string;
}
```

### Radio API

Radio component is a wrapper for a radio button with a label.

```ts
interface RadioProps {
  as?: "input";

  children?: undefined;

  className?: string;

  /**
   * Disable this Radio item.
   */
  disabled?: boolean;

  /**
   * A circle outline, with a filled circle icon inside when the Radio is checked.
   */
  indicator?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * Hidden input that handles the radio's functionality.
   *
   * This is the PRIMARY slot: all native properties specified directly on `<Radio>` will be applied to this slot,
   * except `className` and `style`, which remain on the root slot.
   */
  input?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;

  /**
   * The Radio's label.
   */
  label?: WithSlotShorthandValue<Omit<ComponentProps<LabelSlots>, "required"> & { disabled?: boolean; required?: boolean | WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null | undefined; }, "children"> & { children?: any; }> | null | undefined; size?: "small" | "medium" | "large" | undefined; weight?: "regular" | "semibold" | undefined; } & RefAttributes<HTMLLabelElement>> | null | undefined;

  /**
   * The position of the label relative to the radio indicator.
   *
   * This defaults to `after` unless the Radio is inside a RadioGroup with `layout="horizontalStacked"`,
   * in which case it defaults to `below`.
   */
  labelPosition?: "below" | "after";

  /**
   * Callback when this Radio is selected in its group.
   *
   * **Note:** `onChange` is NOT called when this Radio is deselected.
   * Use RadioGroup's `onChange` event to determine when the selection in the group changes.
   */
  onChange?: ((ev: ChangeEvent<HTMLInputElement>, data: RadioOnChangeData) => void);

  ref?: Ref<HTMLInputElement>;

  /**
   * The root element of the Radio.
   *
   * The root slot receives the `className` and `style` specified directly on the `<Radio>`.
   * All other native props will be applied to the primary slot: `input`
   */
  root?: NonNullable<WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  style?: CSSProperties;

  /**
   * The value of the RadioGroup when this Radio item is selected.
   */
  value?: string | number | readonly string[];
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

## Controlled Value

Source: Fluent, adapted for CoreAI.

The selected radio item can be controlled using the `value` and `onChange` props.

[Download source](/coreai-design-system/source/examples/components-radiogroup--controlled-value.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";

export const ControlledValue = (): JSXElement => {
    const [value, setValue] = React.useState('banana');
    return (<>
      <Field label="Favorite Fruit">
        <RadioGroup value={value} onChange={(_, data) => setValue(data.value)}>
          <Radio value="apple" label="Apple"/>
          <Radio value="pear" label="Pear"/>
          <Radio value="banana" label="Banana"/>
          <Radio value="orange" label="Orange"/>
        </RadioGroup>
      </Field>
      <Button disabledFocusable={!value} onClick={() => setValue('')}>
        Clear selection
      </Button>
    </>);
};

export default ControlledValue;
```

## Default Value

Source: Fluent, adapted for CoreAI.

The initially selected item can be set by setting the `defaultValue` of RadioGroup. Alternatively, one Radio item can have `defaultChecked` set. Both methods have the same effect, but only one should be used in a given RadioGroup.

[Download source](/coreai-design-system/source/examples/components-radiogroup--default-value.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import * as React from 'react';

export const DefaultValue = (): JSXElement => (<Field label="Favorite Fruit">
    <RadioGroup defaultValue="pear">
      <Radio value="apple" label="Apple"/>
      <Radio value="pear" label="Pear"/>
      <Radio value="banana" label="Banana"/>
      <Radio value="orange" label="Orange"/>
    </RadioGroup>
  </Field>);

export default DefaultValue;
```

## Disabled

Source: Fluent, adapted for CoreAI.

RadioGroup can be disabled, which disables all Radio items inside.

[Download source](/coreai-design-system/source/examples/components-radiogroup--disabled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import * as React from 'react';

export const Disabled = (): JSXElement => (<Field label="Favorite Fruit">
    <RadioGroup defaultValue="apple" disabled>
      <Radio value="apple" label="Apple"/>
      <Radio value="pear" label="Pear"/>
      <Radio value="banana" label="Banana"/>
      <Radio value="orange" label="Orange"/>
    </RadioGroup>
  </Field>);

export default Disabled;
```

## Disabled Item

Source: Fluent, adapted for CoreAI.

Radio items can be disabled individually.

[Download source](/coreai-design-system/source/examples/components-radiogroup--disabled-item.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import * as React from 'react';

export const DisabledItem = (): JSXElement => (<Field label="Favorite Fruit">
    <RadioGroup defaultValue="apple">
      <Radio value="apple" label="Apple"/>
      <Radio value="pear" label="Pear"/>
      <Radio value="banana" label="Banana" disabled/>
      <Radio value="orange" label="Orange"/>
    </RadioGroup>
  </Field>);

export default DisabledItem;
```

## Layout: horizontal

Source: Fluent, adapted for CoreAI.

The `horizontal` layout places each radio item in a row, with labels after the radio indicator.

[Download source](/coreai-design-system/source/examples/components-radiogroup--horizontal.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import * as React from 'react';

export const Horizontal = (): JSXElement => (<Field label="Favorite Fruit">
    <RadioGroup layout="horizontal">
      <Radio value="apple" label="Apple"/>
      <Radio value="pear" label="Pear"/>
      <Radio value="banana" label="Banana"/>
      <Radio value="orange" label="Orange"/>
    </RadioGroup>
  </Field>);

export default Horizontal;
```

## Layout: horizontal-stacked

Source: Fluent, adapted for CoreAI.

The `horizontal-stacked` layout places each radio item in a row, with labels below the radio indicator.

[Download source](/coreai-design-system/source/examples/components-radiogroup--horizontal-stacked.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import * as React from 'react';

export const HorizontalStacked = (): JSXElement => (<Field label="Favorite Fruit">
    <RadioGroup layout="horizontal-stacked">
      <Radio value="apple" label="Apple"/>
      <Radio value="pear" label="Pear"/>
      <Radio value="banana" label="Banana"/>
      <Radio value="orange" label="Orange"/>
    </RadioGroup>
  </Field>);

export default HorizontalStacked;
```

## Label Subtext

Source: Fluent, adapted for CoreAI.

Radio's label supports any formatted text. In this example, smaller text is below the main label text.

[Download source](/coreai-design-system/source/examples/components-radiogroup--label-subtext.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import * as React from 'react';

export const LabelSubtext = (): JSXElement => (<Field label="Favorite Fruit">
    <RadioGroup>
      <Radio value="A" label={<>
            Banana
            <br />
            <Text size={200}>This is an example subtext of the first option</Text>
          </>}/>
      <Radio value="B" label={<>
            Pear
            <br />
            <Text size={200}>This is some more example subtext</Text>
          </>}/>
    </RadioGroup>
  </Field>);

export default LabelSubtext;
```

## Required

Source: Fluent, adapted for CoreAI.

Use the `required` prop to indicate that one of the radio items must be selected. Or, if the RadioGroup is inside a Field, it will inherit the `required` prop from the Field.

[Download source](/coreai-design-system/source/examples/components-radiogroup--required.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import * as React from 'react';

export const Required = (): JSXElement => (<Field label="Favorite Fruit" required>
    <RadioGroup>
      <Radio value="apple" label="Apple"/>
      <Radio value="pear" label="Pear"/>
      <Radio value="banana" label="Banana"/>
      <Radio value="orange" label="Orange"/>
    </RadioGroup>
  </Field>);

export default Required;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=219564-4609)
- [Fluent guidance](https://fluent2.microsoft.design/components/web/react/core/radiogroup/usage)