Skip to main content
RadioGroup
@coinbase/cds-web@8.13.6
Radio is a control component that allows users to select one option from a set.
Import
import { RadioGroup } from '@coinbase/cds-web/controls/RadioGroup'
SourceView source codeStorybookView StorybookFigmaView Figma
Related components

Deprecation Notice

Deprecated Component

RadioGroup is deprecated and will be removed in a future version.

Use ControlGroup with role="radiogroup" instead for better accessibility, consistency, and maintainability.

Types

RadioGroup onChange fails without a string type declaration for setGroup fns.

const [group, setGroup] = useState<string>();

Migration Guide

The new recommended approach provides better accessibility, cleaner API, and consistent behavior across the design system.

Loading...
Live Code
function RecommendedRadioGroup() {
  const options = [
    { value: 'btc', children: 'Bitcoin' },
    { value: 'eth', children: 'Ethereum' },
    { value: 'ltc', children: 'Litecoin' },
  ];

  const [selectedCurrency, setSelectedCurrency] = useState('btc');

  return (
    <VStack gap={2}>
      <ControlGroup
        role="radiogroup"
        ControlComponent={Radio}
        label="Choose a Currency"
        options={options}
        value={selectedCurrency}
        onChange={(e) => setSelectedCurrency(e.target.value)}
        name="recommended-radio-group"
      />
      <Text font="caption" color="fgMuted">
        Selected: {selectedCurrency}
      </Text>
    </VStack>
  );
}

Migration Steps

  1. Replace RadioGroup with ControlGroup:

    // Old (deprecated)
    <RadioGroup
    value={selectedValue}
    onChange={onChange}
    options={{ btc: 'Bitcoin', eth: 'Ethereum' }}
    />

    // New (recommended)
    <ControlGroup
    role="radiogroup"
    ControlComponent={Radio}
    options={[
    { value: 'btc', children: 'Bitcoin' },
    { value: 'eth', children: 'Ethereum' }
    ]}
    value={selectedValue}
    onChange={onChange}
    />
  2. Update options format:

    // Old: Object format
    const options = { btc: 'Bitcoin', eth: 'Ethereum' };

    // New: Array format
    const options = [
    { value: 'btc', children: 'Bitcoin' },
    { value: 'eth', children: 'Ethereum' },
    ];
  3. Update onChange handler:

    // Old: Direct value callback
    const oldOnChange = (value) => setSelected(value);

    // New: Event-based handler
    const newOnChange = (e) => setSelected(e.target.value);
  4. Add proper role:

    // Always include role="radiogroup" for accessibility
    <ControlGroup
    role="radiogroup"
    ControlComponent={Radio}
    // ... other props
    />

Legacy Usage (Deprecated)

Legacy Example

The following examples show the deprecated RadioGroup usage. Do not use this in new code. Use ControlGroup instead.

Basic RadioGroup (Legacy)

Loading...
Live Code
function LegacyRadioGroupDemo() {
  // static values should live outside the component in product code.
  const options = {
    btc: 'Bitcoin',
    eth: 'Ethereum',
    dai: 'Dai',
  };

  const [group, setGroup] = useState('btc');

  return (
    <VStack gap={2}>
      <Text font="headline">Currency Selection (Legacy RadioGroup)</Text>
      <RadioGroup
        aria-labelledby="choose-a-currency"
        id="currency-radio-group"
        label={
          <Text as="span" font="headline" id="choose-a-currency">
            Choose a currency
          </Text>
        }
        name="radio-group1"
        value={group}
        onChange={setGroup}
        options={options}
      />
      <Text font="caption" color="fgMuted">
        Selected: {group}
      </Text>
    </VStack>
  );
}

With Custom Label (Legacy)

Loading...
Live Code
function LegacyRadioGroupWithLabel() {
  const options = {
    'yellow-jacket': 'Yellow Jacket',
    bruin: 'Bruin',
    bronco: 'Bronco',
  };

  const [mascot, setMascot] = useState('bruin');

  return (
    <RadioGroup
      aria-labelledby="choose-a-mascot"
      id="mascot-radio-group"
      label={
        <Text as="span" font="headline" id="choose-a-mascot">
          Choose a mascot
        </Text>
      }
      name="radio-group2"
      value={mascot}
      onChange={setMascot}
      options={options}
    />
  );
}

Color Customization (Legacy)

Like other control components (i.e. Checkbox, Switch), you can customize the color of the Radio by setting the controlColor prop.

Loading...
Live Code
function CustomColors() {
  // static values should live outside the component in product code.
  const options = {
    btc: 'Bitcoin',
    eth: 'Ethereum',
    dai: 'Dai',
  };

  const [checked, setChecked] = useState(false);
  const [group, setGroup] = useState();

  return (
    <VStack>
      <Radio
        controlColor="accentBoldGreen"
        onChange={() => setChecked((s) => !s)}
        checked={checked}
      >
        Custom control color
      </Radio>
      <Divider paddingY={2} />
      <RadioGroup
        id="mascot-radio-group"
        aria-labelledby="choose-a-mascot"
        name="radio-group2"
        controlColor="accentBoldGreen"
        value={group}
        onChange={setGroup}
        options={options}
      />
    </VStack>
  );
}

For more advanced color customization, you can use additional style props on individual Radio components like background, borderColor, and color:

Loading...
Live Code
function AdvancedCustomColors() {
  const [checked, setChecked] = useState(false);

  return (
    <VStack gap={2}>
      <Radio checked={checked} controlColor="bgPositive" onChange={() => setChecked((s) => !s)}>
        Control color prop
      </Radio>
      <Radio
        background={checked ? 'accentBoldPurple' : 'bg'}
        borderColor={checked ? 'bgNegative' : 'bgWarning'}
        checked={checked}
        color="bgPrimary"
        controlColor="bgPositive"
        onChange={() => setChecked((s) => !s)}
      >
        Advanced styling
      </Radio>
    </VStack>
  );
}

Is this page useful?

Coinbase Design is an open-source, adaptable system of guidelines, components, and tools that aid the best practices of user interface design for crypto products.