Button.tsx 4.5 KB

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