Radio

Radio

The Radio component bundles an <input type="radio"> element with a label. It also hides the native radio control and provides a custom control that appears more consistent across platforms.

Props

name type description
className string Class name for the <label> container (which has the .Radio class). This should include any BEM modifier classes you wish to use.
HTML attributes various E.g. name, checked, disabled, events, etc. These are applied to the input.
children node The children are placed inside of the .Radio__label element.

Sizing Modifiers

class default
Radio--small[-breakpoint]
Radio--medium[-breakpoint] yes
Radio--large[-breakpoint]

RadioGroup

The RadioGroup component bundles multiple Radio into a single field with one value.

Props

name type default description
name string The name to use on the radio buttons
value string null The current selected value of the group
render callback Called when rendering the group. Should return the full markup up of the group. See below for details.
onChange callback A callback that will be called with the current value every time it changes
disabled boolean false Set to true if all of the radio buttons should be disabled
clearable false Set to true if the user should be able to uncheck a checked radio

render prop

The render callback should return the full markup of the group, including the container element. Using a callback gives you full control over the markup. The callback’s argument is a managed Radio component that will automatically behave nicely in the group (e.g. will be checked when its value is selected, will be disabled when the group is disabled, and will automatically update the group’s value when the user checks it).

<RadioGroup value="foo" clearable render={Radio => (
  <form>
    <Radio className="d-block Radio--large" value="foo">Foo</Radio>
    <Radio className="d-block Radio--large" value="bar">Bar</Radio>
  </form>
)} />
<div>
    <h3>Radios</h3>
    <div>
        <h6>States &amp; modifiers</h6>
        <div>
            <label class="mr4 Radio">
                <input type="radio" class="Radio__input" value="unchecked" name="states-1"
                /><span class="Radio__indicator"></span><span class="Radio__label">Unchecked</span>
            </label>
            <label class="Radio">
                <input type="radio" class="Radio__input" value="checked" name="states-1"
                checked="" /><span class="Radio__indicator"></span><span class="Radio__label">Checked</span>
            </label>
        </div>
        <div>
            <label class="mr4 Radio Radio--is-disabled">
                <input type="radio" class="Radio__input" value="unchecked" name="states-2"
                disabled="" /><span class="Radio__indicator"></span><span class="Radio__label">Disabled</span>
            </label>
            <label class="Radio Radio--is-disabled">
                <input type="radio" class="Radio__input" value="checked" name="states-2"
                checked="" disabled="" /><span class="Radio__indicator"></span><span class="Radio__label">Disabled and checked</span>
            </label>
        </div>
        <label class="d-block mt5 Radio--small Radio">
            <input type="radio" class="Radio__input" value="foo" name="small" checked=""
            /><span class="Radio__indicator"></span><span class="Radio__label">Small</span>
        </label>
        <label class="d-block mt1 Radio">
            <input type="radio" class="Radio__input" value="foo" name="medium" checked=""
            /><span class="Radio__indicator"></span><span class="Radio__label">Medium (default)</span>
        </label>
        <label class="d-block mt1 Radio--large Radio">
            <input type="radio" class="Radio__input" value="foo" name="large" checked=""
            /><span class="Radio__indicator"></span><span class="Radio__label">Large</span>
        </label>
        <label class="d-block mt1 Radio--small Radio--medium-sm Radio--large-md Radio">
            <input type="radio" class="Radio__input" value="foo" name="responsive"
            checked="" /><span class="Radio__indicator"></span><span class="Radio__label">Responsive</span>
        </label>
    </div>
    <div class="mt6">
        <h6>Sophisticated labels</h6>
        <p>You can use html in the label if it needs to be more than just a string. Clicking anywhere in the label will check the radio.</p>
        <label class="Radio">
            <input type="radio" class="Radio__input" value="foo" name="sophistication"
            /><span class="Radio__indicator"></span><span class="Radio__label">I have some footer text<p class="text-1 text-color-secondary">click me</p></span>
        </label>
    </div>
    <hr/>
    <br/>
    <h3>Radio Groups</h3>
    <div>
        <p>The <code>RadioGroup</code> component makes it easy to have a single field with a selected value, using multiple radio buttons.</p>
        <div class="mt5">
            <label class="mr4 Radio">
                <input type="radio" class="Radio__input" value="one" name="basic" /><span class="Radio__indicator"></span><span class="Radio__label">one</span>
            </label>
            <label class="mr4 Radio">
                <input type="radio" class="Radio__input" value="two" name="basic" checked=""
                /><span class="Radio__indicator"></span><span class="Radio__label">two</span>
            </label>
            <label class="Radio">
                <input type="radio" class="Radio__input" value="three" name="basic" /><span class="Radio__indicator"></span><span class="Radio__label">three</span>
            </label>
        </div>
    </div>
    <div class="mt6">
        <h6>Clearable groups</h6>
        <p>Use the <code>clearable</code> prop on the <code>RadioGroup</code> to allow the user to uncheck a checked radio. This will set the group’s value to <code>null</code>.</p>
        <div class="mt5">
            <label class="mr4 Radio">
                <input type="radio" class="Radio__input" value="a" name="clearable" checked=""
                /><span class="Radio__indicator"></span><span class="Radio__label">Uncheck me!</span>
            </label>
            <label class="Radio">
                <input type="radio" class="Radio__input" value="b" name="clearable" /><span class="Radio__indicator"></span><span class="Radio__label">Hello</span>
            </label>
        </div>
    </div>
    <div class="mt6">
        <h6>Disabled groups</h6>
        <p>Use the <code>disabled</code> prop to set all the radios in the group to disabled. As you can see in this example, you still have flexiblity to tinker with each individual radio.</p>
        <div class="mt5">
            <label class="mr4 Radio Radio--is-disabled">
            <input type="radio" class="Radio__input" value="a" name="disabled" disabled=""
            /><span class="Radio__indicator"></span><span class="Radio__label">A</span>
        </label>
            <label class="mr4 Radio Radio--is-disabled">
            <input type="radio" class="Radio__input" value="b" name="disabled" disabled=""
            /><span class="Radio__indicator"></span><span class="Radio__label">B</span>
        </label>
            <label class="Radio Radio--is-disabled">
            <input type="radio" class="Radio__input" value="c" disabled="" name="disabled"
            /><span class="Radio__indicator"></span><span class="Radio__label">I’m always disabled!</span>
        </label>
        </div>
        <div class="Button--small mt4 Button">
            <button class="Button__control" type="button">Toggle disabled</button>
        </div>
    </div>
</div>
import * as React from 'react';
import RadioGroup from './radio_group.jsx';
import Button from '../button/button.jsx';

function RadioButtonsExamples() {
  return (
    <div>
      <h3>Radios</h3>
      <StylingExamples />
      <SophisticatedLabelExample />

      <hr />
      <br />

      <h3>Radio Groups</h3>
      <BasicGroupExample />
      <ClearableGroupExample />
      <DisabledGroupExample />
    </div>
  );
}

function StylingExamples() {
  return (
    <div>
      <h6>States &amp; modifiers</h6>

      <RadioGroup
        name="states-1"
        value="checked"
        render={Radio => (
          <div>
            <Radio value="unchecked" className="mr4">
              Unchecked
            </Radio>
            <Radio value="checked">Checked</Radio>
          </div>
        )}
      />

      <RadioGroup
        name="states-2"
        value="checked"
        disabled
        render={Radio => (
          <div>
            <Radio value="unchecked" className="mr4">
              Disabled
            </Radio>
            <Radio value="checked">Disabled and checked</Radio>
          </div>
        )}
      />

      <RadioGroup
        name="small"
        value="foo"
        render={Radio => (
          <Radio className="d-block mt5 Radio--small" value="foo">
            Small
          </Radio>
        )}
      />

      <RadioGroup
        name="medium"
        value="foo"
        render={Radio => (
          <Radio className="d-block mt1" value="foo">
            Medium (default)
          </Radio>
        )}
      />

      <RadioGroup
        name="large"
        value="foo"
        render={Radio => (
          <Radio className="d-block mt1 Radio--large" value="foo">
            Large
          </Radio>
        )}
      />

      <RadioGroup
        name="responsive"
        value="foo"
        render={Radio => (
          <Radio
            className="d-block mt1 Radio--small Radio--medium-sm Radio--large-md"
            value="foo"
          >
            Responsive
          </Radio>
        )}
      />
    </div>
  );
}

class SophisticatedLabelExample extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = { value: null };
  }

  render() {
    return (
      <div className="mt6">
        <h6>Sophisticated labels</h6>
        <p>
          You can use html in the label if it needs to be more than just a
          string. Clicking anywhere in the label will check the radio.
        </p>
        <RadioGroup
          name="sophistication"
          value={this.state.value}
          onChange={newValue => {
            this.setState({ value: newValue });
          }}
          render={Radio => (
            <Radio value="foo">
              I have some footer text
              <p className="text-1 text-color-secondary">click me</p>
            </Radio>
          )}
        />
      </div>
    );
  }
}

class BasicGroupExample extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = { value: 'two' };
  }

  render() {
    return (
      <div>
        <p>
          The <code>RadioGroup</code> component makes it easy to have a single
          field with a selected value, using multiple radio buttons.
        </p>
        <RadioGroup
          name="basic"
          value={this.state.value}
          onChange={newValue => {
            this.setState({ value: newValue });
          }}
          render={Radio => (
            <div className="mt5">
              <Radio className="mr4" value="one">
                one
              </Radio>
              <Radio className="mr4" value="two">
                two
              </Radio>
              <Radio value="three">three</Radio>
            </div>
          )}
        />
      </div>
    );
  }
}

class ClearableGroupExample extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = { value: 'a' };
  }

  render() {
    return (
      <div className="mt6">
        <h6>Clearable groups</h6>
        <p>
          Use the <code>clearable</code> prop on the <code>RadioGroup</code> to
          allow the user to uncheck a checked radio. This will set the group’s
          value to <code>null</code>.
        </p>
        <RadioGroup
          name="clearable"
          clearable
          value={this.state.value}
          onChange={newValue => {
            this.setState({ value: newValue });
          }}
          render={Radio => (
            <div className="mt5">
              <Radio className="mr4" value="a">
                Uncheck me!
              </Radio>
              <Radio value="b">Hello</Radio>
            </div>
          )}
        />
      </div>
    );
  }
}

class DisabledGroupExample extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = { value: null, disabled: true };
  }

  render() {
    return (
      <div className="mt6">
        <h6>Disabled groups</h6>
        <p>
          Use the <code>disabled</code> prop to set all the radios in the group
          to disabled. As you can see in this example, you still have flexiblity
          to tinker with each individual radio.
        </p>
        <RadioGroup
          name="disabled"
          disabled={this.state.disabled}
          value={this.state.value}
          onChange={newValue => {
            this.setState({ value: newValue });
          }}
          render={Radio => (
            <div className="mt5">
              <Radio className="mr4" value="a">
                A
              </Radio>
              <Radio className="mr4" value="b">
                B
              </Radio>
              <Radio value="c" disabled>
                I’m always disabled!
              </Radio>
            </div>
          )}
        />
        <Button
          className="Button--small mt4"
          onClick={() => {
            this.setState({ disabled: !this.state.disabled });
          }}
        >
          Toggle disabled
        </Button>
      </div>
    );
  }
}

export default RadioButtonsExamples;
/* No context defined for this component. */
  • Content:
    @mixin radio-small {
      $size: modular-scale-px(-1);
      $dot-size: modular-scale-px(-7);
    
      @include text-1;
      padding-left: $size + $spacer-1;
    
      .Radio__indicator {
        height: $size;
        top: 1px;
        width: $size;
    
        &::after {
          height: $dot-size;
          left: 2px;
          top: 2px;
          width: $dot-size;
        }
      }
    }
    
    @mixin radio-medium {
      $size: modular-scale-px(0);
      $dot-size: modular-scale-px(-7);
    
      @include text-2;
      padding-left: $size + $spacer-1;
    
      .Radio__indicator {
        height: $size;
        top: 1px;
        width: $size;
    
        &::after {
          height: $dot-size;
          left: 3px;
          top: 3px;
          width: $dot-size;
        }
      }
    }
    
    @mixin radio-large {
      $size: modular-scale-px(2);
      $dot-size: modular-scale-px(-6);
    
      @include text-4;
      padding-left: $size + $spacer-2;
    
      .Radio__indicator {
        height: $size;
        top: 2px;
        width: $size;
    
        &::after {
          height: $dot-size;
          left: 5px;
          top: 5px;
          width: $dot-size;
        }
      }
    }
    
    .Radio {
      @include radio-medium;
      display: inline-block;
      margin: 0;
      position: relative;
    }
    
    .Radio__input {
      opacity: 0;
      position: absolute;
      z-index: -1;
    
      &:focus ~ .Radio__indicator {
        border-color: $blue-100;
        box-shadow: 0 0 11px rgba($blue-100, $alpha-500);
      }
    
      &:active ~ .Radio__indicator {
        background-color: $gray-100;
        border-color: $gray-400;
      }
    
      &:checked ~ .Radio__indicator {
        background-color: $gray-800;
        border-color: $gray-800;
        color: $white;
    
        // Show the dot
        &::after {
          display: block;
        }
      }
    
      &:checked:focus ~ .Radio__indicator {
        border-color: $gray-800;
        box-shadow: 0 0 0 2px rgba($blue-200, $alpha-400);
      }
    
      &:checked:active:not(:disabled) ~ .Radio__indicator {
        background-color: $gray-800;
        border-color: $gray-800;
    
        &::after {
          opacity: $alpha-600;
        }
      }
    
      &:disabled ~ .Radio__indicator,
      &:disabled:active ~ .Radio__indicator,
      &:disabled:checked:active {
        background-color: $gray-200;
        border-color: $gray-200;
      }
    
      &:disabled:checked ~ .Radio__indicator,
      &:disabled:checked:active ~ .Radio__indicator {
        &::after {
          background-color: $gray-400;
        }
      }
    
      &:disabled ~ .Radio__label {
        color: $text-color-secondary;
      }
    }
    
    .Radio__indicator {
      background-color: $white;
      border: $border-width solid $gray-300;
      border-radius: 50%;
      left: 0;
      pointer-events: none;
      position: absolute;
      user-select: none;
    
      &::after {
        background-color: $white;
        border-radius: 50%;
        content: '';
        display: none;
        position: absolute;
      }
    }
    
    .Radio--is-disabled {
      cursor: not-allowed;
    }
    
    @if $enable-responsive-form-components {
      @each $breakpoint in map-keys($grid-breakpoints) {
        @include media-breakpoint-up($breakpoint) {
          $suffix: breakpoint-suffix($breakpoint, $grid-breakpoints);
    
          .Radio--small#{$suffix} { @include radio-small; }
          .Radio--medium#{$suffix} { @include radio-medium; }
          .Radio--large#{$suffix} { @include radio-large; }
        }
      }
    } @else {
      .Radio--small { @include radio-small; }
      .Radio--large { @include radio-large; }
    }
    
  • URL: /components/raw/radio/_radio.scss
  • Filesystem Path: library/components/radio/_radio.scss
  • Size: 3.1 KB