Rework actions modal to bring it closer to upstream and fix modal stacking issue

This commit is contained in:
Claire
2022-02-09 14:39:12 +01:00
parent bc2eaf3581
commit e1a4590bca
6 changed files with 149 additions and 165 deletions

View File

@@ -21,10 +21,9 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
icon: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.shape({
icon: PropTypes.string,
meta: PropTypes.node,
meta: PropTypes.string,
name: PropTypes.string.isRequired,
on: PropTypes.bool,
text: PropTypes.node,
text: PropTypes.string,
})).isRequired,
onModalOpen: PropTypes.func,
onModalClose: PropTypes.func,
@@ -32,10 +31,15 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
value: PropTypes.string,
onChange: PropTypes.func,
container: PropTypes.func,
renderItemContents: PropTypes.func,
closeOnChange: PropTypes.bool,
};
static defaultProps = {
closeOnChange: true,
};
state = {
needsModalUpdate: false,
open: false,
openedViaKeyboard: undefined,
placement: 'bottom',
@@ -106,6 +110,23 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
this.setState({ open: false });
}
handleItemClick = (e) => {
const {
items,
onChange,
onModalClose,
closeOnChange,
} = this.props;
const i = Number(e.currentTarget.getAttribute('data-index'));
const { name } = this.props.items[i];
e.preventDefault(); // Prevents focus from changing
if (closeOnChange) onModalClose();
onChange(name);
};
// Creates an action modal object.
handleMakeModal = () => {
const component = this;
@@ -124,6 +145,8 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
// The object.
return {
renderItemContents: this.props.renderItemContents,
onClick: this.handleItemClick,
actions: items.map(
({
name,
@@ -132,48 +155,11 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
...rest,
active: value && name === value,
name,
onClick (e) {
e.preventDefault(); // Prevents focus from changing
onModalClose();
onChange(name);
},
onPassiveClick (e) {
e.preventDefault(); // Prevents focus from changing
onChange(name);
component.setState({ needsModalUpdate: true });
},
})
),
};
}
// If our modal is open and our props update, we need to also update
// the modal.
handleUpdate = () => {
const { onModalOpen } = this.props;
const { needsModalUpdate } = this.state;
// Gets our modal object.
const modal = this.handleMakeModal();
// Reopens the modal with the new object.
if (needsModalUpdate && modal && onModalOpen) {
onModalOpen(modal);
}
}
// Updates our modal as necessary.
componentDidUpdate (prevProps) {
const { items } = this.props;
const { needsModalUpdate } = this.state;
if (needsModalUpdate && items.find(
(item, i) => item.on !== prevProps.items[i].on
)) {
this.handleUpdate();
this.setState({ needsModalUpdate: false });
}
}
// Rendering.
render () {
const {
@@ -185,6 +171,8 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
onChange,
value,
container,
renderItemContents,
closeOnChange,
} = this.props;
const { open, placement } = this.state;
const computedClass = classNames('composer--options--dropdown', {
@@ -225,10 +213,12 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
>
<DropdownMenu
items={items}
renderItemContents={renderItemContents}
onChange={onChange}
onClose={this.handleClose}
value={value}
openedViaKeyboard={this.state.openedViaKeyboard}
closeOnChange={closeOnChange}
/>
</Overlay>
</div>