diff --git a/app/javascript/flavours/glitch/components/icon_button.js b/app/javascript/flavours/glitch/components/icon_button.js
index c1e2f664c..521353238 100644
--- a/app/javascript/flavours/glitch/components/icon_button.js
+++ b/app/javascript/flavours/glitch/components/icon_button.js
@@ -13,6 +13,7 @@ export default class IconButton extends React.PureComponent {
onClick: PropTypes.func,
onMouseDown: PropTypes.func,
onKeyDown: PropTypes.func,
+ onKeyPress: PropTypes.func,
size: PropTypes.number,
active: PropTypes.bool,
pressed: PropTypes.bool,
@@ -45,6 +46,12 @@ export default class IconButton extends React.PureComponent {
}
}
+ handleKeyPress = (e) => {
+ if (this.props.onKeyPress && !this.props.disabled) {
+ this.props.onKeyPress(e);
+ }
+ }
+
handleMouseDown = (e) => {
if (!this.props.disabled && this.props.onMouseDown) {
this.props.onMouseDown(e);
@@ -121,6 +128,7 @@ export default class IconButton extends React.PureComponent {
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
onKeyDown={this.handleKeyDown}
+ onKeyPress={this.handleKeyPress}
style={style}
tabIndex={tabIndex}
disabled={disabled}
@@ -142,6 +150,7 @@ export default class IconButton extends React.PureComponent {
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
onKeyDown={this.handleKeyDown}
+ onKeyPress={this.handleKeyPress}
style={style}
tabIndex={tabIndex}
disabled={disabled}
diff --git a/app/javascript/flavours/glitch/features/compose/components/dropdown.js b/app/javascript/flavours/glitch/features/compose/components/dropdown.js
index 6a5f4575e..60035b705 100644
--- a/app/javascript/flavours/glitch/features/compose/components/dropdown.js
+++ b/app/javascript/flavours/glitch/features/compose/components/dropdown.js
@@ -36,11 +36,12 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
state = {
needsModalUpdate: false,
open: false,
+ openedViaKeyboard: undefined,
placement: 'bottom',
};
// Toggles opening and closing the dropdown.
- handleToggle = ({ target }) => {
+ handleToggle = ({ target, type }) => {
const { onModalOpen } = this.props;
const { open } = this.state;
@@ -55,23 +56,52 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
}
} else {
const { top } = target.getBoundingClientRect();
+ if (this.state.open && this.activeElement) {
+ this.activeElement.focus();
+ }
this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' });
- this.setState({ open: !this.state.open });
+ this.setState({ open: !this.state.open, openedViaKeyboard: type !== 'click' });
}
}
handleKeyDown = (e) => {
switch (e.key) {
- case 'Enter':
- this.handleToggle(key);
- break;
case 'Escape':
this.handleClose();
break;
}
}
+ 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.handleToggle(e);
+ e.stopPropagation();
+ e.preventDefault();
+ break;
+ }
+ }
+
handleClose = () => {
+ if (this.state.open && this.activeElement) {
+ this.activeElement.focus();
+ }
this.setState({ open: false });
}
@@ -174,6 +204,9 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
icon={icon}
inverted
onClick={this.handleToggle}
+ onMouseDown={this.handleMouseDown}
+ onKeyDown={this.handleButtonKeyDown}
+ onKeyPress={this.handleKeyPress}
size={18}
style={{
height: null,
@@ -192,6 +225,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
onChange={onChange}
onClose={this.handleClose}
value={value}
+ openedViaKeyboard={this.state.openedViaKeyboard}
/>
diff --git a/app/javascript/flavours/glitch/features/compose/components/dropdown_menu.js b/app/javascript/flavours/glitch/features/compose/components/dropdown_menu.js
index 19d35a8f4..f812be7a9 100644
--- a/app/javascript/flavours/glitch/features/compose/components/dropdown_menu.js
+++ b/app/javascript/flavours/glitch/features/compose/components/dropdown_menu.js
@@ -14,91 +14,6 @@ import { withPassive } from 'flavours/glitch/util/dom_helpers';
import Motion from 'flavours/glitch/util/optional_motion';
import { assignHandlers } from 'flavours/glitch/util/react_helpers';
-class ComposerOptionsDropdownContentItem extends ImmutablePureComponent {
-
- static propTypes = {
- active: PropTypes.bool,
- name: PropTypes.string,
- onChange: PropTypes.func,
- onClose: PropTypes.func,
- options: PropTypes.shape({
- icon: PropTypes.string,
- meta: PropTypes.node,
- on: PropTypes.bool,
- text: PropTypes.node,
- }),
- };
-
- handleActivate = (e) => {
- const {
- name,
- onChange,
- onClose,
- options: { on },
- } = this.props;
-
- // If the escape key was pressed, we close the dropdown.
- if (e.key === 'Escape' && onClose) {
- onClose();
-
- // Otherwise, we both close the dropdown and change the value.
- } else if (onChange && (!e.key || e.key === 'Enter')) {
- e.preventDefault(); // Prevents change in focus on click
- if ((on === null || typeof on === 'undefined') && onClose) {
- onClose();
- }
- onChange(name);
- }
- }
-
- // Rendering.
- render () {
- const {
- active,
- options: {
- icon,
- meta,
- on,
- text,
- },
- } = this.props;
- const computedClass = classNames('composer--options--dropdown--content--item', {
- active,
- lengthy: meta,
- 'toggled-off': !on && on !== null && typeof on !== 'undefined',
- 'toggled-on': on,
- 'with-icon': icon,
- });
-
- let prefix = null;
-
- if (on !== null && typeof on !== 'undefined') {
- prefix =