# All files / react/Button index.jsx

96.88% Statements 31/32
94.44% Branches 17/18
100% Functions 8/8
96.43% Lines 27/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132

    2x
    53x
    53x

    4x
    52x

    52x
    11x

    52x
    9x

    52x
    8x

    52x

    2x

    2x

    2x

    53x

    53x
    53x

    46x
    6x

    2x
    1x

    1x

    2x

    2x

    2x

    2x

     import React from 'react'
    import cx from 'classnames'
    import PropTypes from 'prop-types'
    import styles from './styles.styl'
    import Icon from '../Icon'

    const btnClass = function(options) {
      const { className, extension, size, theme, variant } = options
      return cx(className, styles['c-btn'], {
        [styles[`c-btn--${theme}`]]: theme,
        [styles[`c-btn--${size}`]]: size,
        [styles[`c-btn--${variant}`]]: variant,
        [styles[`c-btn--${extension}`]]: extension
      })
    }

    const transformToAria = tag => props => {
      const { busy, disabled, ...newProps } = props

      if (busy) {
        newProps['aria-busy'] = true
      }
      if (disabled) {
        newProps['aria-disabled'] = true
      }
      if (tag === 'button' && disabled) {
        newProps['disabled'] = true
      }

      return newProps
    }

    const tagToTransformProps = {
      button: transformToAria('button'),
      a: transformToAria('a')
    }

    const identity = x => x

    const BaseButton = props => {
      const {
        children,
        icon,
        label,
        subtle,
        className,
        extension,
        size,
        theme,
        tag: Tag,
        ...restProps
      } = props

      const transformProps = tagToTransformProps[Tag] || identity
      return (
        <Tag
          {...transformProps(restProps)}
          className={btnClass({
            extension,
            size,
            theme,
            className,
            variant: subtle && 'subtle'
          })}
        >
          <span>
            {Icon.isProperIcon(icon) ? <Icon icon={icon} /> : icon}
            {label && <span>{label}</span>}
            {children}
          </span>
        </Tag>
      )
    }

    const Button = props => <BaseButton {...props} />
    const ButtonLink = props => <BaseButton {...props} />

    export { Button, ButtonLink }

    const DefaultButton = props => {
      Iif (!props.tag) {
        return <Button {...props} />
      } else {
        return <BaseButton {...props} />
      }
    }

    export default DefaultButton

    // Proptypes (unfortunately, Styleguidist does not pick
    // proptypes coming from a spread so we have to keep both
    // proptypes in sync)
    Button.propTypes = {
      /** DEPRECATED: please use label and icon */
      children: PropTypes.node,
      /** Label of the button */
      label: PropTypes.node,
      /** Icon of the button */
      icon: PropTypes.node,
      theme: PropTypes.string,
      size: PropTypes.oneOf(['tiny', 'small', 'large']),
      /** Spacing of the button */
      extension: PropTypes.oneOf(['narrow', 'full']),
      /** Extra class */
      className: PropTypes.string,
      /** What to do on click */
      onClick: PropTypes.func,

      // Only for Button
      /** Will display a spinner if true */
      busy: PropTypes.bool,
      /** Disables the button */
      disabled: PropTypes.bool,
      /** Type of the underlying `<button />` */
      type: PropTypes.oneOf(['button', 'reset', 'submit']),
      /** Use the `subtle` alternative look for the Button  */
      subtle: PropTypes.bool
    }

    BaseButton.defaultProps = {
      role: 'button'
    }

    Button.defaultProps = {
      type: 'submit',
      tag: 'button'
    }

    ButtonLink.defaultProps = {
      tag: 'a'
    }