about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Yip <yipdw@member.fsf.org>2018-04-12 03:28:22 -0500
committerGitHub <noreply@github.com>2018-04-12 03:28:22 -0500
commiteb72c3398cd70c6b595fae5a0cb6730a3e49bd61 (patch)
tree284dfe28ae42ef4a6414cf2ef3bab667f58b7396
parent0b326950bf8d38fd7c98a71d6bc1c93067c8ceb5 (diff)
parente74e5c7eb903d6e9aa88629e975a81574fe49159 (diff)
Merge pull request #418 from ThibG/glitch-soc/fixes/composer-dropdowns
Place composer dropdown menus top if they are closer to the bottom of the viewport
-rw-r--r--app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js12
-rw-r--r--app/javascript/flavours/glitch/features/composer/options/dropdown/index.js11
2 files changed, 17 insertions, 6 deletions
diff --git a/app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js b/app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js
index b3a472999..b76410561 100644
--- a/app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js
+++ b/app/javascript/flavours/glitch/features/composer/options/dropdown/content/index.js
@@ -13,7 +13,6 @@ import { assignHandlers } from 'flavours/glitch/util/react_helpers';
 
 //  Handlers.
 const handlers = {
-
   //  When the document is clicked elsewhere, we close the dropdown.
   handleDocumentClick ({ target }) {
     const { node } = this;
@@ -45,6 +44,10 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
 
     //  Instance variables.
     this.node = null;
+
+    this.state = {
+      mounted: false,
+    };
   }
 
   //  On mounting, we add our listeners.
@@ -52,6 +55,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
     const { handleDocumentClick } = this.handlers;
     document.addEventListener('click', handleDocumentClick, false);
     document.addEventListener('touchend', handleDocumentClick, withPassive);
+    this.setState({ mounted: true });
   }
 
   //  On unmounting, we remove our listeners.
@@ -63,6 +67,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
 
   //  Rendering.
   render () {
+    const { mounted } = this.state;
     const { handleRef } = this.handlers;
     const {
       items,
@@ -87,13 +92,16 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
         }}
       >
         {({ opacity, scaleX, scaleY }) => (
+          // It should not be transformed when mounting because the resulting
+          // size will be used to determine the coordinate of the menu by
+          // react-overlays
           <div
             className='composer--options--dropdown--content'
             ref={handleRef}
             style={{
               ...style,
               opacity: opacity,
-              transform: `scale(${scaleX}, ${scaleY})`,
+              transform: mounted ? `scale(${scaleX}, ${scaleY})` : null,
             }}
           >
             {items ? items.map(
diff --git a/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js b/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js
index d63d90a9f..b3462e25a 100644
--- a/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js
+++ b/app/javascript/flavours/glitch/features/composer/options/dropdown/index.js
@@ -29,7 +29,7 @@ const handlers = {
     } = this.handlers;
     switch (key) {
     case 'Enter':
-      handleToggle();
+      handleToggle(key);
       break;
     case 'Escape':
       handleClose();
@@ -79,7 +79,7 @@ const handlers = {
   },
 
   //  Toggles opening and closing the dropdown.
-  handleToggle () {
+  handleToggle ({ target }) {
     const { handleMakeModal } = this.handlers;
     const { onModalOpen } = this.props;
     const { open } = this.state;
@@ -98,6 +98,8 @@ const handlers = {
       }
     }
 
+    const { top } = target.getBoundingClientRect();
+    this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' });
     //  Otherwise, we just set our state to open.
     this.setState({ open: !open });
   },
@@ -129,6 +131,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
     this.state = {
       needsModalUpdate: false,
       open: false,
+      placement: null,
     };
   }
 
@@ -161,7 +164,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
       onChange,
       value,
     } = this.props;
-    const { open } = this.state;
+    const { open, placement } = this.state;
     const computedClass = classNames('composer--options--dropdown', {
       active,
       open,
@@ -188,7 +191,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
         />
         <Overlay
           containerPadding={20}
-          placement='bottom'
+          placement={placement}
           show={open}
           target={this}
         >