Place privacy dropdown menu top if it is closer to the bottom of the viewport (#7106)
This commit is contained in:
		
							parent
							
								
									519119f657
								
							
						
					
					
						commit
						12f5f13fab
					
				
					 1 changed files with 17 additions and 5 deletions
				
			
		|  | @ -32,6 +32,10 @@ class PrivacyDropdownMenu extends React.PureComponent { | ||||||
|     onChange: PropTypes.func.isRequired, |     onChange: PropTypes.func.isRequired, | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   state = { | ||||||
|  |     mounted: false, | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   handleDocumentClick = e => { |   handleDocumentClick = e => { | ||||||
|     if (this.node && !this.node.contains(e.target)) { |     if (this.node && !this.node.contains(e.target)) { | ||||||
|       this.props.onClose(); |       this.props.onClose(); | ||||||
|  | @ -54,6 +58,7 @@ class PrivacyDropdownMenu extends React.PureComponent { | ||||||
|   componentDidMount () { |   componentDidMount () { | ||||||
|     document.addEventListener('click', this.handleDocumentClick, false); |     document.addEventListener('click', this.handleDocumentClick, false); | ||||||
|     document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); |     document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); | ||||||
|  |     this.setState({ mounted: true }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   componentWillUnmount () { |   componentWillUnmount () { | ||||||
|  | @ -66,12 +71,16 @@ class PrivacyDropdownMenu extends React.PureComponent { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|  |     const { mounted } = this.state; | ||||||
|     const { style, items, value } = this.props; |     const { style, items, value } = this.props; | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}> |       <Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}> | ||||||
|         {({ opacity, scaleX, scaleY }) => ( |         {({ opacity, scaleX, scaleY }) => ( | ||||||
|           <div className='privacy-dropdown__dropdown' style={{ ...style, opacity: opacity, transform: `scale(${scaleX}, ${scaleY})` }} ref={this.setRef}> |           // 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='privacy-dropdown__dropdown' style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} ref={this.setRef}> | ||||||
|             {items.map(item => ( |             {items.map(item => ( | ||||||
|               <div role='button' tabIndex='0' key={item.value} data-index={item.value} onKeyDown={this.handleClick} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })}> |               <div role='button' tabIndex='0' key={item.value} data-index={item.value} onKeyDown={this.handleClick} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })}> | ||||||
|                 <div className='privacy-dropdown__option__icon'> |                 <div className='privacy-dropdown__option__icon'> | ||||||
|  | @ -107,9 +116,10 @@ export default class PrivacyDropdown extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   state = { |   state = { | ||||||
|     open: false, |     open: false, | ||||||
|  |     placement: null, | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   handleToggle = () => { |   handleToggle = ({ target }) => { | ||||||
|     if (this.props.isUserTouching()) { |     if (this.props.isUserTouching()) { | ||||||
|       if (this.state.open) { |       if (this.state.open) { | ||||||
|         this.props.onModalClose(); |         this.props.onModalClose(); | ||||||
|  | @ -120,6 +130,8 @@ export default class PrivacyDropdown extends React.PureComponent { | ||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|  |       const { top } = target.getBoundingClientRect(); | ||||||
|  |       this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' }); | ||||||
|       this.setState({ open: !this.state.open }); |       this.setState({ open: !this.state.open }); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | @ -136,7 +148,7 @@ export default class PrivacyDropdown extends React.PureComponent { | ||||||
|   handleKeyDown = e => { |   handleKeyDown = e => { | ||||||
|     switch(e.key) { |     switch(e.key) { | ||||||
|     case 'Enter': |     case 'Enter': | ||||||
|       this.handleToggle(); |       this.handleToggle(e); | ||||||
|       break; |       break; | ||||||
|     case 'Escape': |     case 'Escape': | ||||||
|       this.handleClose(); |       this.handleClose(); | ||||||
|  | @ -165,7 +177,7 @@ export default class PrivacyDropdown extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { value, intl } = this.props; |     const { value, intl } = this.props; | ||||||
|     const { open } = this.state; |     const { open, placement } = this.state; | ||||||
| 
 | 
 | ||||||
|     const valueOption = this.options.find(item => item.value === value); |     const valueOption = this.options.find(item => item.value === value); | ||||||
| 
 | 
 | ||||||
|  | @ -185,7 +197,7 @@ export default class PrivacyDropdown extends React.PureComponent { | ||||||
|           /> |           /> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <Overlay show={open} placement='bottom' target={this}> |         <Overlay show={open} placement={placement} target={this}> | ||||||
|           <PrivacyDropdownMenu |           <PrivacyDropdownMenu | ||||||
|             items={this.options} |             items={this.options} | ||||||
|             value={value} |             value={value} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue