diff --git a/app/javascript/mastodon/components/dropdown_menu.js b/app/javascript/mastodon/components/dropdown_menu.js
index 982d34718e2..0a6e7c62721 100644
--- a/app/javascript/mastodon/components/dropdown_menu.js
+++ b/app/javascript/mastodon/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;
diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
index 6b22ba84a53..a772c1c953b 100644
--- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
+++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
@@ -42,22 +42,65 @@ class PrivacyDropdownMenu extends React.PureComponent {
}
}
- handleClick = e => {
- if (e.key === 'Escape') {
- this.props.onClose();
- } else if (!e.key || e.key === 'Enter') {
- const value = e.currentTarget.getAttribute('data-index');
-
- e.preventDefault();
+ handleKeyDown = e => {
+ const { items } = this.props;
+ const value = e.currentTarget.getAttribute('data-index');
+ const index = items.findIndex(item => {
+ return (item.value === value);
+ });
+ let element;
+ switch(e.key) {
+ case 'Escape':
this.props.onClose();
- this.props.onChange(value);
+ break;
+ case 'Enter':
+ this.handleClick(e);
+ break;
+ case 'ArrowDown':
+ element = this.node.childNodes[index + 1];
+ if (element) {
+ element.focus();
+ this.props.onChange(element.getAttribute('data-index'));
+ }
+ break;
+ case 'ArrowUp':
+ element = this.node.childNodes[index - 1];
+ if (element) {
+ element.focus();
+ this.props.onChange(element.getAttribute('data-index'));
+ }
+ break;
+ case 'Home':
+ element = this.node.firstChild;
+ if (element) {
+ element.focus();
+ this.props.onChange(element.getAttribute('data-index'));
+ }
+ break;
+ case 'End':
+ element = this.node.lastChild;
+ if (element) {
+ element.focus();
+ this.props.onChange(element.getAttribute('data-index'));
+ }
+ break;
}
}
+ handleClick = e => {
+ const value = e.currentTarget.getAttribute('data-index');
+
+ e.preventDefault();
+
+ this.props.onClose();
+ this.props.onChange(value);
+ }
+
componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, false);
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
+ if (this.focusedItem) this.focusedItem.focus();
this.setState({ mounted: true });
}
@@ -70,6 +113,10 @@ class PrivacyDropdownMenu extends React.PureComponent {
this.node = c;
}
+ setFocusRef = c => {
+ this.focusedItem = c;
+ }
+
render () {
const { mounted } = this.state;
const { style, items, value } = this.props;
@@ -80,9 +127,9 @@ class PrivacyDropdownMenu extends React.PureComponent {
// It should not be transformed when mounting because the resulting
// size will be used to determine the coordinate of the menu by
// react-overlays
-
+
{items.map(item => (
-
+
@@ -147,9 +194,6 @@ export default class PrivacyDropdown extends React.PureComponent {
handleKeyDown = e => {
switch(e.key) {
- case 'Enter':
- this.handleToggle(e);
- break;
case 'Escape':
this.handleClose();
break;