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.

OverflowMenuButton.js 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* @flow */
  2. import InlineDialog from '@atlaskit/inline-dialog';
  3. import React, { Component } from 'react';
  4. import { createToolbarEvent, sendAnalytics } from '../../../analytics';
  5. import { translate } from '../../../base/i18n';
  6. import { IconHorizontalPoints } from '../../../base/icons';
  7. import { connect } from '../../../base/redux';
  8. import Drawer from './Drawer';
  9. import DrawerPortal from './DrawerPortal';
  10. import ToolbarButton from './ToolbarButton';
  11. /**
  12. * The type of the React {@code Component} props of {@link OverflowMenuButton}.
  13. */
  14. type Props = {
  15. /**
  16. * A child React Element to display within {@code InlineDialog}.
  17. */
  18. children: React$Node,
  19. /**
  20. * Whether or not the OverflowMenu popover should display.
  21. */
  22. isOpen: boolean,
  23. /**
  24. * Calback to change the visibility of the overflow menu.
  25. */
  26. onVisibilityChange: Function,
  27. /**
  28. * Whether to display the OverflowMenu as a drawer.
  29. */
  30. overflowDrawer: boolean,
  31. /**
  32. * Invoked to obtain translated strings.
  33. */
  34. t: Function
  35. };
  36. /**
  37. * A React {@code Component} for opening or closing the {@code OverflowMenu}.
  38. *
  39. * @extends Component
  40. */
  41. class OverflowMenuButton extends Component<Props> {
  42. /**
  43. * Initializes a new {@code OverflowMenuButton} instance.
  44. *
  45. * @param {Object} props - The read-only properties with which the new
  46. * instance is to be initialized.
  47. */
  48. constructor(props: Props) {
  49. super(props);
  50. // Bind event handlers so they are only bound once per instance.
  51. this._onCloseDialog = this._onCloseDialog.bind(this);
  52. this._onToggleDialogVisibility
  53. = this._onToggleDialogVisibility.bind(this);
  54. }
  55. /**
  56. * Implements React's {@link Component#render()}.
  57. *
  58. * @inheritdoc
  59. * @returns {ReactElement}
  60. */
  61. render() {
  62. const { children, isOpen, overflowDrawer } = this.props;
  63. return (
  64. <div className = 'toolbox-button-wth-dialog'>
  65. {
  66. overflowDrawer ? (
  67. <>
  68. {this._renderToolbarButton()}
  69. <DrawerPortal>
  70. <Drawer
  71. canExpand = { true }
  72. isOpen = { isOpen }
  73. onClose = { this._onCloseDialog }>
  74. {children}
  75. </Drawer>
  76. </DrawerPortal>
  77. </>
  78. ) : (
  79. <InlineDialog
  80. content = { children }
  81. isOpen = { isOpen }
  82. onClose = { this._onCloseDialog }
  83. placement = 'top-end'>
  84. {this._renderToolbarButton()}
  85. </InlineDialog>
  86. )
  87. }
  88. </div>
  89. );
  90. }
  91. _renderToolbarButton: () => React$Node;
  92. /**
  93. * Renders the actual toolbar overflow menu button.
  94. *
  95. * @returns {ReactElement}
  96. */
  97. _renderToolbarButton() {
  98. const { isOpen, t } = this.props;
  99. return (
  100. <ToolbarButton
  101. accessibilityLabel =
  102. { t('toolbar.accessibilityLabel.moreActions') }
  103. icon = { IconHorizontalPoints }
  104. onClick = { this._onToggleDialogVisibility }
  105. toggled = { isOpen }
  106. tooltip = { t('toolbar.moreActions') } />
  107. );
  108. }
  109. _onCloseDialog: () => void;
  110. /**
  111. * Callback invoked when {@code InlineDialog} signals that it should be
  112. * close.
  113. *
  114. * @private
  115. * @returns {void}
  116. */
  117. _onCloseDialog() {
  118. this.props.onVisibilityChange(false);
  119. }
  120. _onToggleDialogVisibility: () => void;
  121. /**
  122. * Callback invoked to signal that an event has occurred that should change
  123. * the visibility of the {@code InlineDialog} component.
  124. *
  125. * @private
  126. * @returns {void}
  127. */
  128. _onToggleDialogVisibility() {
  129. sendAnalytics(createToolbarEvent('overflow'));
  130. this.props.onVisibilityChange(!this.props.isOpen);
  131. }
  132. }
  133. /**
  134. * Maps (parts of) the Redux state to the associated props for the
  135. * {@code OverflowMenuButton} component.
  136. *
  137. * @param {Object} state - The Redux state.
  138. * @returns {Props}
  139. */
  140. function mapStateToProps(state) {
  141. const { overflowDrawer } = state['features/toolbox'];
  142. return {
  143. overflowDrawer
  144. };
  145. }
  146. export default translate(connect(mapStateToProps)(OverflowMenuButton));