闭社主体 forked from https://github.com/tootsuite/mastodon
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.2 KiB

  1. import React from 'react';
  2. import Motion from 'react-motion/lib/Motion';
  3. import spring from 'react-motion/lib/spring';
  4. import PropTypes from 'prop-types';
  5. class IconButton extends React.PureComponent {
  6. static propTypes = {
  7. className: PropTypes.string,
  8. title: PropTypes.string.isRequired,
  9. icon: PropTypes.string.isRequired,
  10. onClick: PropTypes.func,
  11. size: PropTypes.number,
  12. active: PropTypes.bool,
  13. style: PropTypes.object,
  14. activeStyle: PropTypes.object,
  15. disabled: PropTypes.bool,
  16. inverted: PropTypes.bool,
  17. animate: PropTypes.bool,
  18. overlay: PropTypes.bool,
  19. };
  20. static defaultProps = {
  21. size: 18,
  22. active: false,
  23. disabled: false,
  24. animate: false,
  25. overlay: false,
  26. };
  27. handleClick = (e) => {
  28. e.preventDefault();
  29. if (!this.props.disabled) {
  30. this.props.onClick(e);
  31. }
  32. }
  33. render () {
  34. const style = {
  35. fontSize: `${this.props.size}px`,
  36. width: `${this.props.size * 1.28571429}px`,
  37. height: `${this.props.size * 1.28571429}px`,
  38. lineHeight: `${this.props.size}px`,
  39. ...this.props.style,
  40. ...(this.props.active ? this.props.activeStyle : {}),
  41. };
  42. const classes = ['icon-button'];
  43. if (this.props.active) {
  44. classes.push('active');
  45. }
  46. if (this.props.disabled) {
  47. classes.push('disabled');
  48. }
  49. if (this.props.inverted) {
  50. classes.push('inverted');
  51. }
  52. if (this.props.overlay) {
  53. classes.push('overlayed');
  54. }
  55. if (this.props.className) {
  56. classes.push(this.props.className);
  57. }
  58. return (
  59. <Motion defaultStyle={{ rotate: this.props.active ? -360 : 0 }} style={{ rotate: this.props.animate ? spring(this.props.active ? -360 : 0, { stiffness: 120, damping: 7 }) : 0 }}>
  60. {({ rotate }) =>
  61. <button
  62. aria-label={this.props.title}
  63. title={this.props.title}
  64. className={classes.join(' ')}
  65. onClick={this.handleClick}
  66. style={style}>
  67. <i style={{ transform: `rotate(${rotate}deg)` }} className={`fa fa-fw fa-${this.props.icon}`} aria-hidden='true' />
  68. </button>
  69. }
  70. </Motion>
  71. );
  72. }
  73. }
  74. export default IconButton;