diff options
author | Thibaut Girka <thib@sitedethib.com> | 2018-05-05 17:11:48 +0200 |
---|---|---|
committer | Thibaut Girka <thib@sitedethib.com> | 2018-05-05 17:11:48 +0200 |
commit | cee157fc19f19bf253de03168b0ed44446363474 (patch) | |
tree | 54da9e34ba1e209dcc87d67896851519a48b1ee7 /app/javascript/flavours | |
parent | cb62935c0b00f41ff5d4ab77a8cc38174b05d186 (diff) |
Improve accessibility of toot dropdown menu
* Prevent Enter keypresses from triggering dropdown display toggle twice * Give focus to first/selected item of dropdown menus * Implement keyboard navigation in generic dropdown menus Partial port from ef7d64c80109074b39983b50cc8cf701c337cdcc to glitch-soc
Diffstat (limited to 'app/javascript/flavours')
-rw-r--r-- | app/javascript/flavours/glitch/components/dropdown_menu.js | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/app/javascript/flavours/glitch/components/dropdown_menu.js b/app/javascript/flavours/glitch/components/dropdown_menu.js index 245bebef3..27b2586e5 100644 --- a/app/javascript/flavours/glitch/components/dropdown_menu.js +++ b/app/javascript/flavours/glitch/components/dropdown_menu.js @@ -43,6 +43,7 @@ class DropdownMenu extends React.PureComponent { componentDidMount () { document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); + if (this.focusedItem) this.focusedItem.focus(); this.setState({ mounted: true }); } @@ -55,6 +56,46 @@ class DropdownMenu extends React.PureComponent { this.node = c; } + setFocusRef = c => { + this.focusedItem = c; + } + + handleKeyDown = e => { + const items = Array.from(this.node.getElementsByTagName('a')); + const index = items.indexOf(e.currentTarget); + let element; + + switch(e.key) { + case 'Enter': + this.handleClick(e); + break; + case 'ArrowDown': + element = items[index+1]; + if (element) { + element.focus(); + } + break; + case 'ArrowUp': + element = items[index-1]; + if (element) { + element.focus(); + } + break; + case 'Home': + element = items[0]; + if (element) { + element.focus(); + } + break; + case 'End': + element = items[items.length-1]; + if (element) { + element.focus(); + } + break; + } + } + handleClick = e => { const i = Number(e.currentTarget.getAttribute('data-index')); const { action, to } = this.props.items[i]; @@ -79,7 +120,7 @@ class DropdownMenu extends React.PureComponent { return ( <li className='dropdown-menu__item' key={`${text}-${i}`}> - <a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' autoFocus={i === 0} onClick={this.handleClick} data-index={i}> + <a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyDown={this.handleKeyDown} data-index={i}> {text} </a> </li> @@ -156,9 +197,6 @@ export default class Dropdown extends React.PureComponent { handleKeyDown = e => { switch(e.key) { - case 'Enter': - this.handleClick(e); - break; case 'Escape': this.handleClose(); break; |