Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External Media: Fix Modal focus loss on arrow keypress #16055

Merged
merged 6 commits into from
Jun 9, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 41 additions & 6 deletions extensions/shared/external-media/sources/with-media.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import apiFetch from '@wordpress/api-fetch';
import { createHigherOrderComponent } from '@wordpress/compose';
import { Component } from '@wordpress/element';
import { withNotices, Modal } from '@wordpress/components';
import { UP, DOWN, LEFT, RIGHT } from '@wordpress/keycodes';
import { __ } from '@wordpress/i18n';

/**
Expand Down Expand Up @@ -53,6 +54,42 @@ export default function withMedia() {
};
}

modalRef = el => {
if ( el ) {
// Find the modal wrapper.
this.modalElement = el.closest( '.jetpack-external-media-browser' );

// Attach the listener if found.
if ( this.modalElement ) {
this.modalElement.addEventListener( 'keydown', this.stopArrowKeysPropagation );
}
} else if ( this.modalElement ) {
// Remove listeners when unmounting.
this.modalElement.removeEventListener( 'keydown', this.stopArrowKeysPropagation );
this.modalElement = null;
jeryj marked this conversation as resolved.
Show resolved Hide resolved
}
};

stopArrowKeysPropagation = event => {
/**
* When the External Media modal is open, pressing any arrow key causes
* it to close immediately. This is happening because the keydown event
* propagates outside the modal, triggering a re-render and a blur event
* eventually. We could avoid that by isolating the modal from the Image
* block render scope, but it is not possible in current implementation.
*
* This handler makes sure that the keydown event doesn't propagate further,
* which fixes the issue described above while still keeping arrow keys
* functional inside the modal.
*
* This can be removed once
* https://github.com/WordPress/gutenberg/issues/22940 is fixed.
*/
if ( [ UP, DOWN, LEFT, RIGHT ].includes( event.keyCode ) ) {
event.stopPropagation();
}
};

setAuthenticated = isAuthenticated => this.setState( { isAuthenticated } );

mergeMedia( initial, media ) {
Expand Down Expand Up @@ -171,17 +208,13 @@ export default function withMedia() {
this.setState( { path }, cb );
};

stopPropagation( event ) {
event.stopPropagation();
}

renderContent() {
const { media, isLoading, nextHandle, isAuthenticated, path } = this.state;
const { noticeUI, allowedTypes, multiple = false } = this.props;

return (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<div onMouseDown={ this.stopPropagation }>
<div>
{ noticeUI }

<OriginalComponent
Expand Down Expand Up @@ -216,7 +249,9 @@ export default function withMedia() {
title={ isCopying ? __( 'Copying Media', 'jetpack' ) : __( 'Select Media', 'jetpack' ) }
className={ classes }
>
{ isCopying ? <CopyingMedia items={ isCopying } /> : this.renderContent() }
<div ref={ this.modalRef }>
{ isCopying ? <CopyingMedia items={ isCopying } /> : this.renderContent() }
</div>
</Modal>
);
}
Expand Down