• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

react-ui-org / react-ui / 13664247057

04 Mar 2025 10:32PM UTC coverage: 90.531%. First build
13664247057

Pull #599

github

web-flow
Merge 85bfae883 into 276f39e07
Pull Request #599: Enable TypesScript for Playwright (#587)

770 of 859 branches covered (89.64%)

Branch coverage included in aggregate %.

712 of 778 relevant lines covered (91.52%)

65.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.11
/src/components/Button/Button.jsx
1
import PropTypes from 'prop-types';
2
import React, { useContext } from 'react';
3
import { withGlobalProps } from '../../providers/globalProps';
4
import { classNames } from '../../helpers/classNames/classNames';
5
import { transferProps } from '../../helpers/transferProps';
6
import { getRootColorClassName } from '../_helpers/getRootColorClassName';
7
import { getRootPriorityClassName } from '../_helpers/getRootPriorityClassName';
8
import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
9
import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
10
import { ButtonGroupContext } from '../ButtonGroup';
11
import { InputGroupContext } from '../InputGroup/InputGroupContext';
12
import getRootLabelVisibilityClassName from './helpers/getRootLabelVisibilityClassName';
13
import styles from './Button.module.scss';
14

15
export const Button = React.forwardRef((props, ref) => {
10✔
16
  const {
17
    afterLabel,
18
    beforeLabel,
19
    block,
20
    disabled,
21
    endCorner,
22
    feedbackIcon,
23
    id,
24
    label,
25
    labelVisibility,
26
    priority,
27
    size,
28
    startCorner,
29
    color,
30
    ...restProps
31
  } = props;
92✔
32
  const buttonGroupContext = useContext(ButtonGroupContext);
92✔
33
  const inputGroupContext = useContext(InputGroupContext);
92✔
34

35
  if (buttonGroupContext && inputGroupContext) {
92!
36
    throw new Error('Button cannot be placed both in `ButtonGroup` and `InputGroup`.');
×
37
  }
38

39
  const primaryContext = buttonGroupContext ?? inputGroupContext;
92✔
40

41
  return (
92✔
42
    /* No worries, `type` is always assigned correctly through props. */
43
    /* eslint-disable react/button-has-type */
44
    <button
45
      {...transferProps(restProps)}
46
      className={classNames(
47
        styles.root,
48
        getRootPriorityClassName(
49
          resolveContextOrProp(buttonGroupContext && buttonGroupContext.priority, priority),
59✔
50
          styles,
51
        ),
52
        getRootColorClassName(color, styles),
53
        getRootSizeClassName(
54
          resolveContextOrProp(primaryContext && primaryContext.size, size),
73✔
55
          styles,
56
        ),
57
        getRootLabelVisibilityClassName(labelVisibility, styles),
58
        resolveContextOrProp(buttonGroupContext && buttonGroupContext.block, block) && styles.isRootBlock,
106✔
59
        buttonGroupContext && styles.isRootInButtonGroup,
59✔
60
        inputGroupContext && styles.isRootInInputGroup,
60✔
61
        feedbackIcon && styles.hasRootFeedback,
46!
62
      )}
63
      disabled={resolveContextOrProp(primaryContext && primaryContext.disabled, disabled) || !!feedbackIcon}
157✔
64
      id={id}
65
      ref={ref}
66
    >
67
      {startCorner && (
46!
68
        <span className={styles.startCorner}>
69
          {startCorner}
70
        </span>
71
      )}
72
      {beforeLabel && (
50✔
73
        <span className={styles.beforeLabel}>
74
          {beforeLabel}
75
        </span>
76
      )}
77
      <span
78
        className={styles.label}
79
        {...(id && { id: `${id}__labelText` })}
51✔
80
      >
81
        {label}
82
      </span>
83
      {afterLabel && (
46!
84
        <span className={styles.afterLabel}>
85
          {afterLabel}
86
        </span>
87
      )}
88
      {endCorner && (
46!
89
        <span className={styles.endCorner}>
90
          {endCorner}
91
        </span>
92
      )}
93
      {feedbackIcon && (
46!
94
        <span className={styles.feedbackIcon}>
95
          {feedbackIcon}
96
        </span>
97
      )}
98
    </button>
99
    /* eslint-enable react/button-has-type */
100
  );
101
});
102

103
Button.defaultProps = {
10✔
104
  afterLabel: null,
105
  beforeLabel: null,
106
  block: false,
107
  color: 'primary',
108
  disabled: false,
109
  endCorner: null,
110
  feedbackIcon: null,
111
  id: undefined,
112
  labelVisibility: 'xs',
113
  priority: 'filled',
114
  size: 'medium',
115
  startCorner: null,
116
  type: 'button',
117
};
118

119
Button.propTypes = {
10✔
120
  /**
121
   * Element to be displayed after label, eg. an icon.
122
   */
123
  afterLabel: PropTypes.node,
124
  /**
125
   * Element to be displayed before label, eg. an icon.
126
   */
127
  beforeLabel: PropTypes.node,
128
  /**
129
   * If `true`, the button will span the full width of its parent.
130
   *
131
   * Ignored if the component is rendered within `ButtonGroup` component
132
   * as the value is inherited in such case.
133
   */
134
  block: PropTypes.bool,
135
  /**
136
   * Color variant to clarify importance and meaning of the alert. Implements
137
   * [Action, Feedback and Neutral color collections](/docs/foundation/collections#colors).
138
   */
139
  color: PropTypes.oneOf(
140
    ['primary', 'secondary', 'selected', 'success', 'warning', 'danger', 'help', 'info', 'note', 'light', 'dark'],
141
  ),
142
  /**
143
   * If `true`, the button will be disabled.
144
   *
145
   * Ignored if the component is rendered within `ButtonGroup` component
146
   * as the value is inherited in such case.
147
   */
148
  disabled: PropTypes.bool,
149
  /**
150
   * Element to be displayed in the top right corner.
151
   */
152
  endCorner: PropTypes.node,
153
  /**
154
   * Element to be displayed as a feedback icon on top of button label. When defined, it implies the
155
   * button is in feedback state.
156
   */
157
  feedbackIcon: PropTypes.node,
158
  /**
159
   * ID of the root HTML element.
160
   *
161
   * Also serves as base for ids of nested elements:
162
   * * `<ID>__labelText`
163
   */
164
  id: PropTypes.string,
165
  /**
166
   * Button label.
167
   */
168
  label: PropTypes.string.isRequired,
169
  /**
170
   * Defines minimum breakpoint from which the button label will be visible.
171
   */
172
  labelVisibility: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl', 'x2l', 'x3l', 'none']),
173
  /**
174
   * Visual priority to highlight or suppress the button.
175
   *
176
   * Ignored if the component is rendered within `ButtonGroup` component
177
   * as the value is inherited in such case.
178
   */
179
  priority: PropTypes.oneOf(['filled', 'outline', 'flat']),
180
  /**
181
   * Size of the button.
182
   *
183
   * Ignored if the component is rendered within `ButtonGroup` or `InputGroup` component as the value is inherited in
184
   * such case.
185
   */
186
  size: PropTypes.oneOf(['small', 'medium', 'large']),
187
  /**
188
   * Element to be displayed in the top left corner.
189
   */
190
  startCorner: PropTypes.node,
191
  /**
192
   * Set the HTML `type` attribute of the `button` element.
193
   */
194
  type: PropTypes.oneOf(['button', 'submit']),
195
};
196

197
export const ButtonWithGlobalProps = withGlobalProps(Button, 'Button');
10✔
198

199
export default ButtonWithGlobalProps;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc