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

The implementation, which is based on Bootstrap 4, uses an extra element and CSS to achieve the custom look, preserving accessibility.

The component provides responsive utility classes (see Modifiers below) that can be used to scale the custom checkbox control and the text label together.

Props

name type description
className string Class name for the input element. This should include any BEM modifier classes you wish to use.
HTML attributes various e.g. checked: true, disabled: true, events, etc. are applied to the input

Valid HTML attributes and event handlers for the input element may be safely passed as additional props. These props will be applied to the <input> element, not the root element of the component.

Passing a prop that is not a legal DOM attribute will cause React to trigger an unknown prop warning.

Note that there are several attributes that work differently between React and HTML. In these cases, attributes should be passed the React-y way.

Modifiers

class default responsive notes
Checkbox--small[-breakpoint] false true Responsive breakpoint token optional
Checkbox--medium[-breakpoint] true true Responsive breakpoint token optional
Checkbox--large[-breakpoint] false true Responsive breakpoint token optional

For the responsive classes, append a responsive breakpoint token to apply the associated sizing styles at that breakpoint and up. For example, .Checkbox--small .Checkbox--medium-sm .Checkbox--large-md will give you a small size checkbox on xs screens, medium on sm screens, and large on md screens and up.

<!-- Default -->
<label class="Checkbox">
    <input type="checkbox" class="Checkbox__input" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Checkbox label</span>
</label>

<!-- Checked -->
<label class="Checkbox">
    <input type="checkbox" class="Checkbox__input" checked="" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Checked</span>
</label>

<!-- Disabled -->
<label class="Checkbox Checkbox--is-disabled">
    <input type="checkbox" class="Checkbox__input" disabled="" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Disabled</span>
</label>

<!-- Disabled Checked -->
<label class="Checkbox Checkbox--is-disabled">
    <input type="checkbox" class="Checkbox__input" disabled="" checked=""
    /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Disabled checked</span>
</label>

<!-- Small -->
<label class="Checkbox--small Checkbox">
    <input type="checkbox" class="Checkbox__input" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Small</span>
</label>

<!-- Small Checked -->
<label class="Checkbox--small Checkbox">
    <input type="checkbox" class="Checkbox__input" checked="" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Small checked</span>
</label>

<!-- Small Disabled -->
<label class="Checkbox--small Checkbox Checkbox--is-disabled">
    <input type="checkbox" class="Checkbox__input" disabled="" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Small disabled</span>
</label>

<!-- Small Disabled Checked -->
<label class="Checkbox--small Checkbox Checkbox--is-disabled">
    <input type="checkbox" class="Checkbox__input" disabled="" checked=""
    /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Small disabled checked</span>
</label>

<!-- Large -->
<label class="Checkbox--large Checkbox">
    <input type="checkbox" class="Checkbox__input" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Large</span>
</label>

<!-- Large Checked -->
<label class="Checkbox--large Checkbox">
    <input type="checkbox" class="Checkbox__input" checked="" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Large checked</span>
</label>

<!-- Large Disabled -->
<label class="Checkbox--large Checkbox Checkbox--is-disabled">
    <input type="checkbox" class="Checkbox__input" disabled="" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Large disabled</span>
</label>

<!-- Large Disabled Checked -->
<label class="Checkbox--large Checkbox Checkbox--is-disabled">
    <input type="checkbox" class="Checkbox__input" disabled="" checked=""
    /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Large disabled checked</span>
</label>

<!-- Responsive -->
<label class="Checkbox--small Checkbox--medium-sm Checkbox--large-md Checkbox">
    <input type="checkbox" class="Checkbox__input" /><span class="Checkbox__indicator"></span><span class="Checkbox__label">Resize me!</span>
</label>

import * as React from 'react';
import classes from 'classnames';

function Checkbox(props) {
  const { className, label, ...htmlProps } = props;
  return (
    <label
      className={classes(className, 'Checkbox', {
        // Most of the styling for disabled checkboxes is tied to the :disabled input state --
        // adding this modifier on the root element enables the `not-allowed` cursor for
        // child elements with `pointer-events: none`
        'Checkbox--is-disabled': htmlProps.disabled,
      })}
    >
      <input type="checkbox" className="Checkbox__input" {...htmlProps} />
      <span className="Checkbox__indicator" />
      <span className="Checkbox__label">{props.label}</span>
    </label>
  );
}

export default Checkbox;
/* Default */
{
  "label": "Checkbox label"
}

/* Checked */
{
  "label": "Checked",
  "defaultChecked": true
}

/* Disabled */
{
  "label": "Disabled",
  "disabled": true
}

/* Disabled Checked */
{
  "label": "Disabled checked",
  "disabled": true,
  "defaultChecked": true
}

/* Small */
{
  "label": "Small",
  "className": "Checkbox--small"
}

/* Small Checked */
{
  "label": "Small checked",
  "defaultChecked": true,
  "className": "Checkbox--small"
}

/* Small Disabled */
{
  "label": "Small disabled",
  "disabled": true,
  "className": "Checkbox--small"
}

/* Small Disabled Checked */
{
  "label": "Small disabled checked",
  "disabled": true,
  "defaultChecked": true,
  "className": "Checkbox--small"
}

/* Large */
{
  "label": "Large",
  "className": "Checkbox--large"
}

/* Large Checked */
{
  "label": "Large checked",
  "defaultChecked": true,
  "className": "Checkbox--large"
}

/* Large Disabled */
{
  "label": "Large disabled",
  "disabled": true,
  "className": "Checkbox--large"
}

/* Large Disabled Checked */
{
  "label": "Large disabled checked",
  "disabled": true,
  "defaultChecked": true,
  "className": "Checkbox--large"
}

/* Responsive */
{
  "label": "Resize me!",
  "className": "Checkbox--small Checkbox--medium-sm Checkbox--large-md"
}

  • Content:
    // scss-lint:disable SelectorFormat ElsePlacement StringQuotes
    
    @import '../../../styles/lib/str-replace';
    
    // Checkbox based on Bootstrap's "custom control"
    // https://github.com/twbs/bootstrap/blob/v4-dev/scss/_custom-forms.scss
    
    @mixin checkbox-sizer($size: 'medium') {
      @if $size == 'small' {
        $width: modular-scale-px(-1);
    
        @include text-1;
        padding-left: $width + $spacer-2;
    
        .Checkbox__indicator {
          background-position: 1px 1px;
          background-size: 8px 8px;
          height: $width;
          top: 1px;
          width: $width;
        }
      }
    
      @else if $size == 'medium' {
        $width: modular-scale-px(0);
    
        @include text-2;
        padding-left: $width + $spacer-2;
    
        .Checkbox__indicator {
          background-position: 1px 2px;
          background-size: 10px 9px;
          height: $width;
          top: 1px;
          width: $width;
        }
      }
    
      @else if $size == 'large' {
        $width: modular-scale-px(2);
    
        @include text-4;
        padding-left: $width + $spacer-3;
    
        .Checkbox__indicator {
          background-position: 2px 3px;
          background-size: 14px 11px;
          height: $width;
          top: 2px;
          width: $width;
        }
      }
    }
    
    @mixin checkbox-icon($fill: $white, $fill-opacity: 1) {
      background-image: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 9'%3E%3Cpolygon fill='#{$fill}' fill-opacity='#{$fill-opacity}' points='3.5 5.45 1.5 3.45 0 4.95 3.5 8.45 10 1.95 8.5 .45'/%3E%3C/svg%3E%0A"), '#', '%23');
    }
    
    .Checkbox {
      @include checkbox-sizer;
      display: inline-block;
      margin: 0;
      position: relative;
    }
    
    .Checkbox__input {
      opacity: 0;
      position: absolute;
      z-index: -1;
    
      &:focus ~ .Checkbox__indicator {
        border-color: $blue-100;
        box-shadow: 0 0 11px rgba($blue-100, $alpha-500);
      }
    
      &:active ~ .Checkbox__indicator {
        background-color: $gray-100;
        border-color: $gray-400;
      }
    
      &:checked ~ .Checkbox__indicator {
        @include checkbox-icon;
        background-color: $gray-800;
        border-color: $gray-800;
      }
    
      &:checked:focus ~ .Checkbox__indicator {
        border-color: $gray-800;
        box-shadow: 0 0 0 2px rgba($blue-200, $alpha-400);
      }
    
      &:checked:active ~ .Checkbox__indicator {
        @include checkbox-icon($fill-opacity: $alpha-600);
        background-color: $gray-800;
        border-color: $gray-800;
      }
    
      &:disabled ~ .Checkbox__indicator,
      &:disabled:active ~ .Checkbox__indicator,
      &:disabled:checked:active {
        background-color: $gray-200;
        border-color: $gray-200;
      }
    
      &:disabled:checked ~ .Checkbox__indicator,
      &:disabled:checked:active ~ .Checkbox__indicator {
        @include checkbox-icon($fill: $gray-400);
      }
    
      &:disabled ~ .Checkbox__label {
        color: $text-color-secondary;
      }
    }
    
    .Checkbox__indicator {
      background-color: $white;
      background-repeat: no-repeat;
      border: $border-width solid $gray-300;
      border-radius: $border-radius;
      left: 0;
      pointer-events: none;
      position: absolute;
      user-select: none;
    }
    
    .Checkbox--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);
    
          .Checkbox--medium#{$suffix} { @include checkbox-sizer; }
          .Checkbox--small#{$suffix} { @include checkbox-sizer('small'); }
          .Checkbox--large#{$suffix} { @include checkbox-sizer('large'); }
        }
      }
    } @else {
      .Checkbox--small { @include checkbox-sizer('small'); }
      .Checkbox--large { @include checkbox-sizer('large'); }
    }
    
  • URL: /components/raw/checkbox/_checkbox.scss
  • Filesystem Path: library/components/checkbox/_checkbox.scss
  • Size: 3.6 KB