From cee157fc19f19bf253de03168b0ed44446363474 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 5 May 2018 17:11:48 +0200 Subject: 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 --- .../flavours/glitch/components/dropdown_menu.js | 46 ++++++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) (limited to 'app/javascript') 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 (
  • - + {text}
  • @@ -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; -- cgit