Default

Loading interactive example. Full source is available below.

View example source
Download source
// 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;

Resources

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.
API referenceGenerated CoreAI prop and type summaries

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.

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.

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.

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

Controlled Value

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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;