Place composer dropdown menus top if they are closer to the bottom of the viewport

th-downstream
Thibaut Girka 7 years ago
parent a60a600a10
commit d1bfe4cdad

@ -13,7 +13,6 @@ import { assignHandlers } from 'flavours/glitch/util/react_helpers';
// Handlers. // Handlers.
const handlers = { const handlers = {
// When the document is clicked elsewhere, we close the dropdown. // When the document is clicked elsewhere, we close the dropdown.
handleDocumentClick ({ target }) { handleDocumentClick ({ target }) {
const { node } = this; const { node } = this;
@ -45,6 +44,10 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
// Instance variables. // Instance variables.
this.node = null; this.node = null;
this.state = {
mounted: false,
};
} }
// On mounting, we add our listeners. // On mounting, we add our listeners.
@ -52,6 +55,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
const { handleDocumentClick } = this.handlers; const { handleDocumentClick } = this.handlers;
document.addEventListener('click', handleDocumentClick, false); document.addEventListener('click', handleDocumentClick, false);
document.addEventListener('touchend', handleDocumentClick, withPassive); document.addEventListener('touchend', handleDocumentClick, withPassive);
this.setState({ mounted: true });
} }
// On unmounting, we remove our listeners. // On unmounting, we remove our listeners.
@ -63,6 +67,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
// Rendering. // Rendering.
render () { render () {
const { mounted } = this.state;
const { handleRef } = this.handlers; const { handleRef } = this.handlers;
const { const {
items, items,
@ -87,13 +92,16 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
}} }}
> >
{({ opacity, scaleX, scaleY }) => ( {({ 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 <div
className='composer--options--dropdown--content' className='composer--options--dropdown--content'
ref={handleRef} ref={handleRef}
style={{ style={{
...style, ...style,
opacity: opacity, opacity: opacity,
transform: `scale(${scaleX}, ${scaleY})`, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null,
}} }}
> >
{items ? items.map( {items ? items.map(

@ -29,7 +29,7 @@ const handlers = {
} = this.handlers; } = this.handlers;
switch (key) { switch (key) {
case 'Enter': case 'Enter':
handleToggle(); handleToggle(key);
break; break;
case 'Escape': case 'Escape':
handleClose(); handleClose();
@ -79,7 +79,7 @@ const handlers = {
}, },
// Toggles opening and closing the dropdown. // Toggles opening and closing the dropdown.
handleToggle () { handleToggle ({ target }) {
const { handleMakeModal } = this.handlers; const { handleMakeModal } = this.handlers;
const { onModalOpen } = this.props; const { onModalOpen } = this.props;
const { open } = this.state; 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. // Otherwise, we just set our state to open.
this.setState({ open: !open }); this.setState({ open: !open });
}, },
@ -129,6 +131,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
this.state = { this.state = {
needsModalUpdate: false, needsModalUpdate: false,
open: false, open: false,
placement: null,
}; };
} }
@ -161,7 +164,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
onChange, onChange,
value, value,
} = this.props; } = this.props;
const { open } = this.state; const { open, placement } = this.state;
const computedClass = classNames('composer--options--dropdown', { const computedClass = classNames('composer--options--dropdown', {
active, active,
open, open,
@ -188,7 +191,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
/> />
<Overlay <Overlay
containerPadding={20} containerPadding={20}
placement='bottom' placement={placement}
show={open} show={open}
target={this} target={this}
> >

Loading…
Cancel
Save