Button

For buttons to behave properly on touch devices, make sure you include a touch event handler to the DOM (document.addEventListener("touchstart", function() {},false); or <body ontouchstart="">). This signals to the browser that there are touch-related CSS styles that need to be applied.

Props

If a button has an href prop, the component renders an achor tag with role=button. Otherwise, the button is rendered as a true button HTML element.

name type default description
className string Class name for the root element. This should include any BEM modifier classes you wish to use.
disabled boolean If true, renders the button in a disabled state and adds an aria-disabled attribute for assistive technologies. For true buttons, sets the disabled attribute on the element. For anchor-tagged buttons, adds tabIndex=-1 to prevent user interaction and disables click handling/pointer events.
href string Determines if the component renders an anchor-tagged button or a true button. If the href prop is '#', event.preventDefault() is automatically called on click events.
onClick function Handler for click events. Called with the SyntheticEvent as the only argument.
type one of: 'button', 'submit', 'reset' 'button' Passed type attribute for the button element. Ignored by anchor-tagged buttons.

Valid HTML attributes and additional event handlers for the button or a element tags may be safely passed as extra props. Passing a prop that is not a legal DOM attribute will cause React to trigger an unknown prop warning. Additionally, you should take care that the props you’re passing make sense for the element type being rendered (for example, you should only be passing a target or rel prop to an anchor-tagged button).

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
Button--small false true
Button--medium true true
Button--large false true
Button--primary false false
Button--danger false false
Button--link false false

Usage

Content for the button should be passed as children of the Button component:

Javascript:

<Button>Click me!</Button>
<Button href="#">No, click me!</Button>

Rendered markup:

<div class="Button">
  <button class="Button__control" type="button">Click me!</button>
</div>
<div class="Button">
  <a href="#" class="Button__control" role="button">No, click me!</a>
</div>
<!-- Default -->
<div class="Button">
    <button class="Button__control" type="button">Button</button>
</div>

<!-- Default: disabled -->
<div class="Button Button--is-disabled">
    <button disabled="" aria-disabled="true" class="Button__control" type="button">Disabled button</button>
</div>

<!-- Using anchor tag -->
<div class="Button"><a href="https://amino.com" target="_blank" class="Button__control" role="button">Anchor-tagged button ↗️</a>
</div>

<!-- Using anchor tag: disabled -->
<div class="Button Button--is-disabled"><a href="#" aria-disabled="true" class="Button__control" role="button" tabindex="-1">Disabled anchor-tagged button</a>
</div>

<!-- Primary -->
<div class="Button--primary Button">
    <button class="Button__control" type="button">Primary button</button>
</div>

<!-- Primary: disabled -->
<div class="Button--primary Button Button--is-disabled">
    <button disabled="" aria-disabled="true" class="Button__control" type="button">Disabled primary button</button>
</div>

<!-- Danger -->
<div class="Button--danger Button">
    <button class="Button__control" type="button">Danger button</button>
</div>

<!-- Danger: disabled -->
<div class="Button--danger Button Button--is-disabled">
    <button disabled="" aria-disabled="true" class="Button__control" type="button">Disabed danger button</button>
</div>

<!-- Link -->
<div class="Button--link Button">
    <button class="Button__control" type="button">Link-style button</button>
</div>

<!-- Link: disabled -->
<div class="Button--link Button Button--is-disabled">
    <button disabled="" aria-disabled="true" class="Button__control" type="button">Disabled link-style button</button>
</div>

<!-- Small -->
<div class="Button--small Button">
    <button class="Button__control" type="button">Small button</button>
</div>

<!-- Large -->
<div class="Button--large Button">
    <button class="Button__control" type="button">Large button</button>
</div>

<!-- Responsive -->
<div class="Button--small Button--medium-sm Button--large-md Button">
    <button class="Button__control" type="button">Responsive button</button>
</div>

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

import AnchorButton from './anchor_button.jsx';
import TrueButton from './true_button.jsx';

function Button(props) {
  const Component = props.href ? AnchorButton : TrueButton;

  return (
    <Component
      {...props}
      aria-disabled={props.disabled}
      className={classes(props.className, 'Button', {
        'Button--is-disabled': props.disabled,
      })}
    />
  );
}

export default Button;
/* Default */
{
  "children": "Button"
}

/* Default: disabled */
{
  "children": "Disabled button",
  "disabled": true
}

/* Using anchor tag */
{
  "children": "Anchor-tagged button ↗️",
  "href": "https://amino.com",
  "target": "_blank"
}

/* Using anchor tag: disabled */
{
  "children": "Disabled anchor-tagged button",
  "href": "#",
  "disabled": true
}

/* Primary */
{
  "children": "Primary button",
  "className": "Button--primary"
}

/* Primary: disabled */
{
  "children": "Disabled primary button",
  "className": "Button--primary",
  "disabled": true
}

/* Danger */
{
  "children": "Danger button",
  "className": "Button--danger"
}

/* Danger: disabled */
{
  "children": "Disabed danger button",
  "className": "Button--danger",
  "disabled": true
}

/* Link */
{
  "children": "Link-style button",
  "className": "Button--link"
}

/* Link: disabled */
{
  "children": "Disabled link-style button",
  "className": "Button--link",
  "disabled": true
}

/* Small */
{
  "children": "Small button",
  "className": "Button--small"
}

/* Large */
{
  "children": "Large button",
  "className": "Button--large"
}

/* Responsive */
{
  "children": "Responsive button",
  "className": "Button--small Button--medium-sm Button--large-md"
}

  • Content:
    // scss-lint:disable SelectorFormat ElsePlacement
    
    @mixin button-sizer($size: 'medium') {
      .Button__control {
        @if $size == 'small' {
          font-size: $font-size-2;
          padding: modular-scale-px(-6) modular-scale-px(-1) modular-scale-px(-5);
        }
    
        @else if $size == 'medium' {
          font-size: $font-size-3;
          padding: modular-scale-px(-3) modular-scale-px(2) modular-scale-px(-2);
        }
    
        @else if $size == 'large' {
          font-size: $font-size-4;
          padding: modular-scale-px(0) modular-scale-px(4) modular-scale-px(1);
        }
      }
    }
    
    // Basic button
    // ------------
    
    .Button {
      @include button-sizer;
      display: inline-block;
    }
    
    .Button__control {
      // scss-lint:disable PropertySortOrder
      background: rgba($black, $alpha-200);
      border: 0;
      border-radius: $border-radius;
      color: $text-color-primary;
      cursor: pointer;
      display: inline-block;
      font-weight: $font-weight-normal;
      line-height: $line-height-base;
      text-align: center;
      transition: all .2s ease-out;
      vertical-align: middle;
      white-space: nowrap;
      width: 100%;
    
      // scss-lint:disable VendorPrefix
      // TODO: Add Autoprefixer
      -moz-user-select: none;
      -ms-user-select: none;
      -webkit-user-select: none;
      user-select: none;
    }
    
    .Button__control:hover,
    .Button__control:focus {
      @include depth(4);
      background: rgba($black, $alpha-200 + .05);
      color: $text-color-primary;
      text-decoration: none;
      transform: translateY(-2.25px) scaleX(1.015) scaleY(1.015);
      transition-duration: .08s;
    }
    
    .Button__control:active,
    .Button--is-active .Button__control,
    .Button--is-active .Button__control:focus {
      @include depth(0);
      background: rgba($black, $alpha-200 + .11);
      transform: translateY(0) scaleX(1) scaleY(1);
      transition-duration: 0s;
    }
    
    // Allow focus indicator when tabbing but hide it if clicking
    .Button__control:active:focus,
    .Button--is-active .Button__control:focus, {
      outline: 0;
    }
    
    .Button__control:disabled,
    .Button--is-disabled .Button__control {
      opacity: $alpha-600;
      pointer-events: none;
    }
    
    .Button--is-disabled {
      cursor: not-allowed;
    }
    
    // Danger button
    // -------------
    
    .Button--danger {
      .Button__control {
        background: $red;
        color: $white;
        font-weight: $font-weight-bold;
    
        &:hover,
        &:focus {
          background: darken($red, 5);
          color: $white;
        }
      }
    
      .Button__control:active,
      &.Button--is-active .Button__control {
        background: darken($red, 11);
      }
    }
    
    // Primary button
    // --------------
    
    .Button--primary {
      .Button__control {
        @include depth(4);
        background: $blue;
        color: $white;
        font-weight: $font-weight-bold;
    
        &:hover,
        &:focus {
          @include depth(7);
          background: darken($blue, 5);
          color: $white;
        }
      }
    
      .Button__control:active,
      &.Button--is-active .Button__control {
        @include depth(0);
        background: darken($blue, 11);
      }
    }
    
    // Link style button
    // -----------------
    
    .Button--link .Button__control {
      .Button__control {
        background: transparent;
        color: $blue;
    
        &:hover,
        &:focus {
          background: rgba($black, .05);
          color: $blue-300;
        }
      }
    
      .Button__control:active,
      &.Button--is-active .Button__control {
        background: rgba($black, .11);
        color: $blue-400;
      }
    }
    
    // Touch devices
    // -------------
    // Touch devices apply the hover state when a button is tapped,
    // so we use that in place of the active state. Since there's no
    // hovering on a touch device, we remove the hover transitions too.
    
    // Note: remember to include an ontouchstart listener on the document
    // This: document.addEventListener("touchstart", function() {},false);
    // Or this: <body ontouchstart="">
    
    @media (pointer: coarse), (any-pointer: coarse) {
      .Button__control:hover {
        @include depth(0);
        background: rgba($black, $alpha-200 + .11);
        transform: translateY(1px) scaleX(.985) scaleY(.985);
      }
    
      .Button--danger .Button__control:hover {
        background: darken($red, 11);
      }
    
      .Button--primary .Button__control:hover {
        background: darken($blue, 11);
      }
    
      .Button--link .Button__control:hover {
        background: rgba($black, .11);
        color: $blue-400;
      }
    }
    
    // Sizers and responsive utilities
    // -------------------------------
    
    @if $enable-responsive-form-components {
      @each $breakpoint in map-keys($grid-breakpoints) {
        @include media-breakpoint-up($breakpoint) {
          $suffix: breakpoint-suffix($breakpoint, $grid-breakpoints);
          .Button--medium#{$suffix} { @include button-sizer; }
          .Button--small#{$suffix} { @include button-sizer('small'); }
          .Button--large#{$suffix} { @include button-sizer('large'); }
        }
      }
    } @else {
      .Button--small { @include button-sizer('small'); }
      .Button--large { @include button-sizer('large'); }
    }
    
  • URL: /components/raw/button/_button.scss
  • Filesystem Path: library/components/button/_button.scss
  • Size: 4.7 KB