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.

AbstractButton.js 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // @flow
  2. import React, { Component } from 'react';
  3. import ToolboxItem from '../ToolboxItem';
  4. import type { Styles } from '../AbstractToolboxItem';
  5. export type Props = {
  6. /**
  7. * Whether to show the label or not.
  8. */
  9. showLabel: boolean,
  10. /**
  11. * Collection of styles for the button.
  12. */
  13. styles: ?Styles,
  14. /**
  15. * Collection of styles for the button, when in toggled state.
  16. */
  17. toggledStyles: ?Styles,
  18. /**
  19. * From which direction the tooltip should appear, relative to the
  20. * button.
  21. */
  22. tooltipPosition: string,
  23. /**
  24. * Whether this button is visible or not.
  25. */
  26. visible: boolean
  27. };
  28. /**
  29. * An abstract implementation of a button.
  30. */
  31. export default class AbstractButton<P: Props, S : *> extends Component<P, S> {
  32. static defaultProps = {
  33. showLabel: false,
  34. styles: undefined,
  35. toggledStyles: undefined,
  36. tooltipPosition: 'top',
  37. visible: true
  38. };
  39. /**
  40. * A succinct description of what the button does. Used by accessibility
  41. * tools and torture tests.
  42. *
  43. * @abstract
  44. */
  45. accessibilityLabel: string;
  46. /**
  47. * The name of the icon of this button.
  48. *
  49. * @abstract
  50. */
  51. iconName: string;
  52. /**
  53. * The text associated with this button. When `showLabel` is set to
  54. * {@code true}, it will be displayed alongside the icon.
  55. *
  56. * @abstract
  57. */
  58. label: string;
  59. /**
  60. * The name of the icon of this button, when toggled.
  61. *
  62. * @abstract
  63. */
  64. toggledIconName: string;
  65. /**
  66. * The text to display in the tooltip. Used only on web.
  67. *
  68. * @abstract
  69. */
  70. tooltip: string;
  71. /**
  72. * Initializes a new {@code AbstractButton} instance.
  73. *
  74. * @param {Props} props - The React {@code Component} props to initialize
  75. * the new {@code AbstractAudioMuteButton} instance with.
  76. */
  77. constructor(props: P) {
  78. super(props);
  79. this._onClick = this._onClick.bind(this);
  80. }
  81. /**
  82. * Helper function to be implemented by subclasses, which should be used
  83. * to handle the button being clicked / pressed.
  84. *
  85. * @abstract
  86. * @private
  87. * @returns {void}
  88. */
  89. _handleClick() {
  90. // To be implemented by subclass.
  91. }
  92. /**
  93. * Gets the current icon name, taking the toggled state into account. If no
  94. * toggled icon is provided, the regular icon will also be used in the
  95. * toggled state.
  96. *
  97. * @private
  98. * @returns {string}
  99. */
  100. _getIconName() {
  101. return (this._isToggled() ? this.toggledIconName : this.iconName)
  102. || this.iconName;
  103. }
  104. /**
  105. * Gets the current styles, taking the toggled state into account. If no
  106. * toggled styles are provided, the regular styles will also be used in the
  107. * toggled state.
  108. *
  109. * @private
  110. * @returns {?Styles}
  111. */
  112. _getStyles() {
  113. const { styles, toggledStyles } = this.props;
  114. return (this._isToggled() ? toggledStyles : styles) || styles;
  115. }
  116. /**
  117. * Helper function to be implemented by subclasses, which must return a
  118. * boolean value indicating if this button is disabled or not.
  119. *
  120. * @private
  121. * @returns {boolean}
  122. */
  123. _isDisabled() {
  124. return false;
  125. }
  126. /**
  127. * Helper function to be implemented by subclasses, which must return a
  128. * boolean value indicating if this button is toggled or not.
  129. *
  130. * @private
  131. * @returns {boolean}
  132. */
  133. _isToggled() {
  134. return false;
  135. }
  136. _onClick: (*) => void;
  137. /**
  138. * Handles clicking / pressing the button, and toggles the audio mute state
  139. * accordingly.
  140. *
  141. * @private
  142. * @returns {void}
  143. */
  144. _onClick() {
  145. this._handleClick();
  146. }
  147. /**
  148. * Implements React's {@link Component#render()}.
  149. *
  150. * @inheritdoc
  151. * @returns {ReactElement}
  152. */
  153. render() {
  154. const props = {
  155. ...this.props,
  156. accessibilityLabel: this.accessibilityLabel,
  157. iconName: this._getIconName(),
  158. label: this.label,
  159. styles: this._getStyles(),
  160. tooltip: this.tooltip
  161. };
  162. return (
  163. <ToolboxItem
  164. disabled = { this._isDisabled() }
  165. onClick = { this._onClick }
  166. { ...props } />
  167. );
  168. }
  169. }