[Glitch] Improve focus handling with dropdown menus
Port b169874828 to glitch-soc
			
			
This commit is contained in:
		
							parent
							
								
									6118e8fa04
								
							
						
					
					
						commit
						ceed029a36
					
				
					 1 changed files with 35 additions and 7 deletions
				
			
		|  | @ -45,7 +45,6 @@ class DropdownMenu extends React.PureComponent { | ||||||
|     document.addEventListener('click', this.handleDocumentClick, false); |     document.addEventListener('click', this.handleDocumentClick, false); | ||||||
|     document.addEventListener('keydown', this.handleKeyDown, false); |     document.addEventListener('keydown', this.handleKeyDown, false); | ||||||
|     document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); |     document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); | ||||||
|     this.activeElement = document.activeElement; |  | ||||||
|     if (this.focusedItem && this.props.openedViaKeyboard) { |     if (this.focusedItem && this.props.openedViaKeyboard) { | ||||||
|       this.focusedItem.focus(); |       this.focusedItem.focus(); | ||||||
|     } |     } | ||||||
|  | @ -56,9 +55,6 @@ class DropdownMenu extends React.PureComponent { | ||||||
|     document.removeEventListener('click', this.handleDocumentClick, false); |     document.removeEventListener('click', this.handleDocumentClick, false); | ||||||
|     document.removeEventListener('keydown', this.handleKeyDown, false); |     document.removeEventListener('keydown', this.handleKeyDown, false); | ||||||
|     document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); |     document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); | ||||||
|     if (this.activeElement) { |  | ||||||
|       this.activeElement.focus(); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setRef = c => { |   setRef = c => { | ||||||
|  | @ -117,7 +113,7 @@ class DropdownMenu extends React.PureComponent { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleItemKeyUp = e => { |   handleItemKeyPress = e => { | ||||||
|     if (e.key === 'Enter' || e.key === ' ') { |     if (e.key === 'Enter' || e.key === ' ') { | ||||||
|       this.handleClick(e); |       this.handleClick(e); | ||||||
|     } |     } | ||||||
|  | @ -147,7 +143,7 @@ class DropdownMenu extends React.PureComponent { | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <li className='dropdown-menu__item' key={`${text}-${i}`}> |       <li className='dropdown-menu__item' key={`${text}-${i}`}> | ||||||
|         <a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyUp={this.handleItemKeyUp} data-index={i}> |         <a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}> | ||||||
|           {text} |           {text} | ||||||
|         </a> |         </a> | ||||||
|       </li> |       </li> | ||||||
|  | @ -214,15 +210,44 @@ export default class Dropdown extends React.PureComponent { | ||||||
|     } else { |     } else { | ||||||
|       const { top } = target.getBoundingClientRect(); |       const { top } = target.getBoundingClientRect(); | ||||||
|       const placement = top * 2 < innerHeight ? 'bottom' : 'top'; |       const placement = top * 2 < innerHeight ? 'bottom' : 'top'; | ||||||
| 
 |  | ||||||
|       this.props.onOpen(this.state.id, this.handleItemClick, placement, type !== 'click'); |       this.props.onOpen(this.state.id, this.handleItemClick, placement, type !== 'click'); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleClose = () => { |   handleClose = () => { | ||||||
|  |     if (this.activeElement) { | ||||||
|  |       this.activeElement.focus(); | ||||||
|  |       this.activeElement = null; | ||||||
|  |     } | ||||||
|     this.props.onClose(this.state.id); |     this.props.onClose(this.state.id); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   handleMouseDown = () => { | ||||||
|  |     if (!this.state.open) { | ||||||
|  |       this.activeElement = document.activeElement; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   handleButtonKeyDown = (e) => { | ||||||
|  |     switch(e.key) { | ||||||
|  |     case ' ': | ||||||
|  |     case 'Enter': | ||||||
|  |       this.handleMouseDown(); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   handleKeyPress = (e) => { | ||||||
|  |     switch(e.key) { | ||||||
|  |     case ' ': | ||||||
|  |     case 'Enter': | ||||||
|  |       this.handleClick(e); | ||||||
|  |       e.stopPropagation(); | ||||||
|  |       e.preventDefault(); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   handleItemClick = (i, e) => { |   handleItemClick = (i, e) => { | ||||||
|     const { action, to } = this.props.items[i]; |     const { action, to } = this.props.items[i]; | ||||||
| 
 | 
 | ||||||
|  | @ -265,6 +290,9 @@ export default class Dropdown extends React.PureComponent { | ||||||
|           size={size} |           size={size} | ||||||
|           ref={this.setTargetRef} |           ref={this.setTargetRef} | ||||||
|           onClick={this.handleClick} |           onClick={this.handleClick} | ||||||
|  |           onMouseDown={this.handleMouseDown} | ||||||
|  |           onKeyDown={this.handleButtonKeyDown} | ||||||
|  |           onKeyPress={this.handleKeyPress} | ||||||
|         /> |         /> | ||||||
| 
 | 
 | ||||||
|         <Overlay show={open} placement={dropdownPlacement} target={this.findTarget}> |         <Overlay show={open} placement={dropdownPlacement} target={this.findTarget}> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue