UNPKG

2.45 kBJavaScriptView Raw
1import React, { useCallback } from 'react';
2import PropTypes from 'prop-types';
3import classNames from 'classnames';
4import { mapToCssModules, tagPropType } from './utils';
5import CloseButton from './CloseButton';
6
7const propTypes = {
8 /** Manually set the visual state of the button to active */
9 active: PropTypes.bool,
10 /** Aria label */
11 'aria-label': PropTypes.string,
12 block: PropTypes.bool,
13 /** Pass children so this component can wrap them */
14 children: PropTypes.node,
15 /** Add custom class */
16 className: PropTypes.string,
17 /** Change existing className with a new className */
18 cssModule: PropTypes.object,
19 /** Use the button as a close button */
20 close: PropTypes.bool,
21 /** Change color of Button to one of the available colors */
22 color: PropTypes.string,
23 /** Disables the button */
24 disabled: PropTypes.bool,
25 innerRef: PropTypes.oneOfType([
26 PropTypes.object,
27 PropTypes.func,
28 PropTypes.string,
29 ]),
30 /** Function to be triggered on click */
31 onClick: PropTypes.func,
32 /** Adds outline to the button */
33 outline: PropTypes.bool,
34 /** Make the button bigger or smaller */
35 size: PropTypes.string,
36 /** Set a custom element for this component */
37 tag: tagPropType,
38};
39
40function Button(props) {
41 const onClick = useCallback(
42 (e) => {
43 if (props.disabled) {
44 e.preventDefault();
45 return;
46 }
47
48 if (props.onClick) {
49 return props.onClick(e);
50 }
51 },
52 [props.onClick, props.disabled],
53 );
54
55 let {
56 active,
57 'aria-label': ariaLabel,
58 block,
59 className,
60 close,
61 cssModule,
62 color = 'secondary',
63 outline,
64 size,
65 tag: Tag = 'button',
66 innerRef,
67 ...attributes
68 } = props;
69
70 if (close) {
71 return <CloseButton {...attributes} />;
72 }
73
74 const btnOutlineColor = `btn${outline ? '-outline' : ''}-${color}`;
75
76 const classes = mapToCssModules(
77 classNames(
78 className,
79 'btn',
80 btnOutlineColor,
81 size ? `btn-${size}` : false,
82 block ? 'd-block w-100' : false,
83 { active, disabled: props.disabled },
84 ),
85 cssModule,
86 );
87
88 if (attributes.href && Tag === 'button') {
89 Tag = 'a';
90 }
91
92 return (
93 <Tag
94 type={Tag === 'button' && attributes.onClick ? 'button' : undefined}
95 {...attributes}
96 className={classes}
97 ref={innerRef}
98 onClick={onClick}
99 aria-label={ariaLabel}
100 />
101 );
102}
103
104Button.propTypes = propTypes;
105
106export default Button;