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.

136 lines
3.0 KiB

  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import classNames from 'classnames';
  4. import Icon from 'mastodon/components/icon';
  5. export default 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. onMouseDown: PropTypes.func,
  12. onKeyDown: PropTypes.func,
  13. onKeyPress: PropTypes.func,
  14. size: PropTypes.number,
  15. active: PropTypes.bool,
  16. pressed: PropTypes.bool,
  17. expanded: PropTypes.bool,
  18. style: PropTypes.object,
  19. activeStyle: PropTypes.object,
  20. disabled: PropTypes.bool,
  21. inverted: PropTypes.bool,
  22. animate: PropTypes.bool,
  23. overlay: PropTypes.bool,
  24. tabIndex: PropTypes.string,
  25. };
  26. static defaultProps = {
  27. size: 18,
  28. active: false,
  29. disabled: false,
  30. animate: false,
  31. overlay: false,
  32. tabIndex: '0',
  33. };
  34. state = {
  35. activate: false,
  36. deactivate: false,
  37. }
  38. componentWillReceiveProps (nextProps) {
  39. if (!nextProps.animate) return;
  40. if (this.props.active && !nextProps.active) {
  41. this.setState({ activate: false, deactivate: true });
  42. } else if (!this.props.active && nextProps.active) {
  43. this.setState({ activate: true, deactivate: false });
  44. }
  45. }
  46. handleClick = (e) => {
  47. e.preventDefault();
  48. if (!this.props.disabled) {
  49. this.props.onClick(e);
  50. }
  51. }
  52. handleKeyPress = (e) => {
  53. if (this.props.onKeyPress && !this.props.disabled) {
  54. this.props.onKeyPress(e);
  55. }
  56. }
  57. handleMouseDown = (e) => {
  58. if (!this.props.disabled && this.props.onMouseDown) {
  59. this.props.onMouseDown(e);
  60. }
  61. }
  62. handleKeyDown = (e) => {
  63. if (!this.props.disabled && this.props.onKeyDown) {
  64. this.props.onKeyDown(e);
  65. }
  66. }
  67. render () {
  68. const style = {
  69. fontSize: `${this.props.size}px`,
  70. width: `${this.props.size * 1.28571429}px`,
  71. height: `${this.props.size * 1.28571429}px`,
  72. lineHeight: `${this.props.size}px`,
  73. ...this.props.style,
  74. ...(this.props.active ? this.props.activeStyle : {}),
  75. };
  76. const {
  77. active,
  78. className,
  79. disabled,
  80. expanded,
  81. icon,
  82. inverted,
  83. overlay,
  84. pressed,
  85. tabIndex,
  86. title,
  87. } = this.props;
  88. const {
  89. activate,
  90. deactivate,
  91. } = this.state;
  92. const classes = classNames(className, 'icon-button', {
  93. active,
  94. disabled,
  95. inverted,
  96. activate,
  97. deactivate,
  98. overlayed: overlay,
  99. });
  100. return (
  101. <button
  102. aria-label={title}
  103. aria-pressed={pressed}
  104. aria-expanded={expanded}
  105. title={title}
  106. className={classes}
  107. onClick={this.handleClick}
  108. onMouseDown={this.handleMouseDown}
  109. onKeyDown={this.handleKeyDown}
  110. onKeyPress={this.handleKeyPress}
  111. style={style}
  112. tabIndex={tabIndex}
  113. disabled={disabled}
  114. >
  115. <Icon id={icon} fixedWidth aria-hidden='true' />
  116. </button>
  117. );
  118. }
  119. }