Button.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /* eslint-disable react/destructuring-assignment */
  2. import React, { PureComponent } from 'react';
  3. import classNames from 'classnames';
  4. import PropTypes from 'prop-types';
  5. import { cssClasses, strings } from '@douyinfe/semi-foundation/button/constants';
  6. import '@douyinfe/semi-foundation/button/button.scss';
  7. import { noop } from '@douyinfe/semi-foundation/utils/function';
  8. const btnSizes = strings.sizes;
  9. const { htmlTypes, btnTypes } = strings;
  10. export type HtmlType = 'button' | 'reset' | 'submit';
  11. export type Size = 'default' | 'small' | 'large';
  12. export type Theme = 'solid' | 'borderless' | 'light';
  13. export type Type = 'primary' | 'secondary' | 'tertiary' | 'warning' | 'danger';
  14. export interface ButtonProps {
  15. id?: string;
  16. block?: boolean;
  17. circle?: boolean;
  18. disabled?: boolean;
  19. className?: string;
  20. icon?: React.ReactNode;
  21. iconPosition?: 'left' | 'right';
  22. loading?: boolean;
  23. htmlType?: HtmlType;
  24. size?: Size;
  25. style?: React.CSSProperties;
  26. theme?: Theme;
  27. type?: Type;
  28. prefixCls?: string;
  29. onClick?: React.MouseEventHandler<HTMLButtonElement>;
  30. onMouseDown?: React.MouseEventHandler<HTMLButtonElement>;
  31. onMouseEnter?: React.MouseEventHandler<HTMLButtonElement>;
  32. onMouseLeave?: React.MouseEventHandler<HTMLButtonElement>;
  33. 'aria-label'?: React.AriaAttributes['aria-label'];
  34. }
  35. // TODO: icon configuration
  36. export default class Button extends PureComponent<ButtonProps> {
  37. static defaultProps = {
  38. disabled: false,
  39. size: 'default',
  40. type: 'primary',
  41. theme: 'light',
  42. block: false,
  43. htmlType: 'button',
  44. onMouseDown: noop,
  45. onClick: noop,
  46. onMouseEnter: noop,
  47. onMouseLeave: noop,
  48. prefixCls: cssClasses.PREFIX,
  49. };
  50. static propTypes = {
  51. children: PropTypes.node,
  52. disabled: PropTypes.bool,
  53. prefixCls: PropTypes.string,
  54. style: PropTypes.object,
  55. size: PropTypes.oneOf(btnSizes),
  56. type: PropTypes.oneOf(btnTypes),
  57. block: PropTypes.bool,
  58. onClick: PropTypes.func,
  59. onMouseDown: PropTypes.func,
  60. circle: PropTypes.bool,
  61. loading: PropTypes.bool,
  62. htmlType: PropTypes.oneOf(htmlTypes),
  63. theme: PropTypes.oneOf(strings.themes),
  64. className: PropTypes.string,
  65. onMouseEnter: PropTypes.func,
  66. onMouseLeave: PropTypes.func,
  67. 'aria-label': PropTypes.string,
  68. };
  69. render() {
  70. const {
  71. children,
  72. block,
  73. htmlType,
  74. loading,
  75. circle,
  76. className,
  77. style,
  78. disabled,
  79. size,
  80. theme,
  81. type,
  82. prefixCls,
  83. iconPosition,
  84. ...attr
  85. } = this.props;
  86. const baseProps = {
  87. disabled,
  88. ...attr,
  89. className: classNames(
  90. prefixCls,
  91. {
  92. [`${prefixCls}-${type}`]: !disabled && type,
  93. [`${prefixCls}-disabled`]: disabled,
  94. [`${prefixCls}-size-large`]: size === 'large',
  95. [`${prefixCls}-size-small`]: size === 'small',
  96. // [`${prefixCls}-loading`]: loading,
  97. [`${prefixCls}-light`]: theme === 'light',
  98. [`${prefixCls}-block`]: block,
  99. [`${prefixCls}-circle`]: circle,
  100. [`${prefixCls}-borderless`]: theme === 'borderless',
  101. },
  102. className
  103. ),
  104. type: htmlType,
  105. 'aria-disabled': disabled,
  106. };
  107. return (
  108. // eslint-disable-next-line react/button-has-type
  109. <button
  110. {...baseProps}
  111. onClick={this.props.onClick}
  112. onMouseDown={this.props.onMouseDown}
  113. style={style}
  114. >
  115. {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
  116. <span className={`${prefixCls}-content`} onClick={e => disabled && e.stopPropagation()}>
  117. {children}
  118. </span>
  119. </button>
  120. );
  121. }
  122. }