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

Block Gallery: deselect first/last image on blur #14930

Merged
merged 3 commits into from
Feb 27, 2020

Conversation

oandregal
Copy link
Member

Fixes #14823

@oandregal oandregal changed the title Fix/gallery image deselect Block Gallery: deselect first/last image on blur Apr 11, 2019
@oandregal oandregal self-assigned this Apr 11, 2019
@oandregal oandregal added [Block] Gallery Affects the Gallery Block - used to display groups of images [Type] Bug An existing feature does not function as intended labels Apr 11, 2019
@oandregal oandregal added this to the 5.5 (Gutenberg) milestone Apr 11, 2019
@oandregal oandregal force-pushed the fix/gallery-image-deselect branch from 90c6591 to d99971e Compare April 12, 2019 11:41
@aduth aduth removed this from the 5.5 (Gutenberg) milestone Apr 12, 2019
@oandregal oandregal added this to the 5.6 (Gutenberg) milestone Apr 23, 2019
//
// onBlur / onFocus events are quick operations (<5ms apart in my testing),
// so 50ms accounts for 10x lagging while feels responsive to the user.
this.debouncedOnDeselect = debounce( this.props.onDeselect, 50 );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't get from this comment why focus on the same element would be called right after blur. In what circumstances does rapid focus & blur happen?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the comment to better explain the mechanism: the idea is to call onDeselect when focus has transitioned to a different React component (another GalleryImage, toolbar, etc.) but not when focus transitions within the DOM elements that form this React component (figure, image, caption, toolbar, etc).

Does it make more sense now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ellatrix any chance you'd be able to review this and see if the comment makes more sense now?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we instead just check that the window.activeElement property is not a children of the wrapper (using a ref) instead of this magic trick :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just code! Perhaps the comment is more confusing than the code itself? Suggestions welcome :)

I had tried the comparison with the activeElement, but the global focus handler won't be reliably dispatched, so I resorted to the focus events dispatched by the children instead.

Copy link
Member Author

@oandregal oandregal Nov 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't get from this comment why focus on the same element would be called right after blur. In what circumstances does rapid focus & blur happen?

Now that I revisit this thread I think I can explain this better! It's not that rapid focus and blur happen on the same element, but that focus and blur on children element bubble to figure. In the DOM, blur and focus don't bubble, but React Events mechanism normalizes all events to bubble - even blur and focus. So this is how events work in gallery:

  • user clicks image => focus event is fired with image as target then it bubbles to figure
  • user tabs to figcaption =>
    • blur event is fired for image as target, then it bubbles to figure
    • focus event is fired for figcaption, then it bubbles to figure

And the same thing for the GalleryImage buttons (icons to remove or move the image). So, instead of tracking blur events individually, this PR tracks them in a single place.

Also worth noting that if you check the activeElement in a blur event it'll be body in Firefox and Chrome (it doesn't give you the next element to focus). So, the only alternative I see would be to listen to focus events at the window level, and check if the activeElement is one of the GalleryImage children. This doesn't work because the focus won't bubble in some situations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nosolosw Could you do something like event.currentTarget.contains( event.relatedTarget ) in the onBlur to detect when focus moved outside a gallery image?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would work and it seems to have good browser support. However, the feature is marked as experimental and is only in a working draft. My gut feeling is that we shouldn't use it just yet, what do you think?

@mapk
Copy link
Contributor

mapk commented Apr 24, 2019

I tested and if an image is selected, after tabbing away, the image deselects. Thanks @nosolosw!

@oandregal oandregal requested a review from ellatrix April 29, 2019 12:15
@gziolo gziolo removed this from the 5.6 (Gutenberg) milestone May 6, 2019
@oandregal oandregal force-pushed the fix/gallery-image-deselect branch from 0533054 to a198701 Compare May 16, 2019 15:59
@youknowriad
Copy link
Contributor

Would be good to revisit this at some point, it looks like a simple quick fix.

@oandregal oandregal force-pushed the fix/gallery-image-deselect branch from a198701 to abe4412 Compare November 19, 2019 18:42
@oandregal
Copy link
Member Author

I've rebased this and it still works as expected.

@youknowriad the alternative approach you mentioned (to hook into the window focus event and compare the activeElement to all the children of GalleryImage) didn't work for me. For some reason, the focus event isn't reliably dispatched. I also think this is more performant and simpler than having to track refs for all children.

@youknowriad
Copy link
Contributor

@ellatrix do you think you can help review this PR :)

@oandregal
Copy link
Member Author

cc @youknowriad @ellatrix bumping visibility for this.

@oandregal oandregal force-pushed the fix/gallery-image-deselect branch from abe4412 to fcbb7c6 Compare January 22, 2020 11:36
@oandregal
Copy link
Member Author

This has been rebased with the latest changes in master and this is ready for review.

@oandregal oandregal force-pushed the fix/gallery-image-deselect branch from fcbb7c6 to 970f5dd Compare February 7, 2020 17:30
@oandregal
Copy link
Member Author

Rebased to fix code formatting issues (presumably after the prettier merge).

@mkevins
Copy link
Contributor

mkevins commented Feb 13, 2020

I have tested this on mobile, and I have not encountered any regressions. 👍

@oandregal
Copy link
Member Author

@youknowriad @talldan @ellatrix @jorgefilipecosta how do you feel about this PR code-wise? Should we go ahead with this implementation or should we close it for now and revisit later?

@youknowriad
Copy link
Contributor

I think we should move forward, I'd have preferred a simpler fix but we can go with that one for now.

@oandregal
Copy link
Member Author

ok, so this would need a 👍 then.

@youknowriad
Copy link
Contributor

When tabbing backward, the image controls (remove, reorder buttons) are skipped entirely, is that expected?

@oandregal oandregal force-pushed the fix/gallery-image-deselect branch from 806dda7 to 92a87e4 Compare February 26, 2020 16:37
@oandregal
Copy link
Member Author

FYI: I've just rebased this from master.

When tabbing backward, the image controls (remove, reorder buttons) are skipped entirely, is that expected?

@youknowriad That's the behavior on master and this PR doesn't change it as far as I can test.

@github-actions
Copy link

Size Change: +146 B (0%)

Total Size: 866 kB

Filename Size Change
build/block-library/index.js 116 kB +146 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.01 kB 0 B
build/annotations/index.js 3.43 kB 0 B
build/api-fetch/index.js 3.39 kB 0 B
build/autop/index.js 2.58 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/index.js 6.02 kB 0 B
build/block-directory/style-rtl.css 760 B 0 B
build/block-directory/style.css 760 B 0 B
build/block-editor/index.js 104 kB 0 B
build/block-editor/style-rtl.css 10.5 kB 0 B
build/block-editor/style.css 10.5 kB 0 B
build/block-library/editor-rtl.css 7.66 kB 0 B
build/block-library/editor.css 7.66 kB 0 B
build/block-library/style-rtl.css 7.49 kB 0 B
build/block-library/style.css 7.5 kB 0 B
build/block-library/theme-rtl.css 669 B 0 B
build/block-library/theme.css 671 B 0 B
build/block-serialization-default-parser/index.js 1.65 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/blocks/index.js 57.6 kB 0 B
build/components/index.js 191 kB 0 B
build/components/style-rtl.css 15.5 kB 0 B
build/components/style.css 15.5 kB 0 B
build/compose/index.js 5.76 kB 0 B
build/core-data/index.js 10.5 kB 0 B
build/data-controls/index.js 1.03 kB 0 B
build/data/index.js 8.22 kB 0 B
build/date/index.js 5.37 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 568 B 0 B
build/dom/index.js 3.06 kB 0 B
build/edit-post/index.js 90.9 kB 0 B
build/edit-post/style-rtl.css 8.59 kB 0 B
build/edit-post/style.css 8.58 kB 0 B
build/edit-site/index.js 4.62 kB 0 B
build/edit-site/style-rtl.css 2.51 kB 0 B
build/edit-site/style.css 2.51 kB 0 B
build/edit-widgets/index.js 4.41 kB 0 B
build/edit-widgets/style-rtl.css 2.59 kB 0 B
build/edit-widgets/style.css 2.58 kB 0 B
build/editor/editor-styles-rtl.css 325 B 0 B
build/editor/editor-styles.css 327 B 0 B
build/editor/index.js 44.6 kB 0 B
build/editor/style-rtl.css 4.01 kB 0 B
build/editor/style.css 4 kB 0 B
build/element/index.js 4.45 kB 0 B
build/escape-html/index.js 733 B 0 B
build/format-library/index.js 7.6 kB 0 B
build/format-library/style-rtl.css 502 B 0 B
build/format-library/style.css 502 B 0 B
build/hooks/index.js 1.92 kB 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.48 kB 0 B
build/is-shallow-equal/index.js 710 B 0 B
build/keyboard-shortcuts/index.js 2.3 kB 0 B
build/keycodes/index.js 1.68 kB 0 B
build/list-reusable-blocks/index.js 2.99 kB 0 B
build/list-reusable-blocks/style-rtl.css 226 B 0 B
build/list-reusable-blocks/style.css 226 B 0 B
build/media-utils/index.js 4.85 kB 0 B
build/notices/index.js 1.57 kB 0 B
build/nux/index.js 3.02 kB 0 B
build/nux/style-rtl.css 616 B 0 B
build/nux/style.css 613 B 0 B
build/plugins/index.js 2.54 kB 0 B
build/primitives/index.js 1.49 kB 0 B
build/priority-queue/index.js 879 B 0 B
build/redux-routine/index.js 2.84 kB 0 B
build/rich-text/index.js 14.3 kB 0 B
build/server-side-render/index.js 2.54 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.27 kB 0 B
build/url/index.js 4 kB 0 B
build/viewport/index.js 1.61 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.18 kB 0 B

compressed-size-action

@oandregal oandregal merged commit 013ef92 into master Feb 27, 2020
@oandregal oandregal deleted the fix/gallery-image-deselect branch February 27, 2020 09:28
@github-actions github-actions bot added this to the Gutenberg 7.7 milestone Feb 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Gallery Affects the Gallery Block - used to display groups of images [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Block gallery: deselect first/last image
8 participants