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

Add a useFocusOnMount hook to the @wordpress/compose package. #27574

Merged
merged 3 commits into from
Dec 8, 2020

Conversation

youknowriad
Copy link
Contributor

Follow-up to #27502
Similar to #27544

This extracts the existing useFocusOnMount hook from the popover component into the compose package in order to be used in the existing PopoverWrapper components.
The goal here is to be able to remove the PopoverWrapper component that is duplicated across three packages and reuse a single hook.

@youknowriad youknowriad added the [Type] New API New API to be used by plugin developers or package users. label Dec 8, 2020
@youknowriad youknowriad self-assigned this Dec 8, 2020
@github-actions
Copy link

github-actions bot commented Dec 8, 2020

Size Change: +186 B (0%)

Total Size: 1.21 MB

Filename Size Change
build/a11y/index.js 1.14 kB -1 B
build/annotations/index.js 3.8 kB -3 B (0%)
build/block-directory/index.js 8.72 kB +5 B (0%)
build/block-editor/index.js 128 kB +45 B (0%)
build/block-library/index.js 149 kB +34 B (0%)
build/block-library/style-rtl.css 8.35 kB +6 B (0%)
build/block-library/style.css 8.35 kB +4 B (0%)
build/components/index.js 172 kB -36 B (0%)
build/components/style-rtl.css 15.3 kB -2 B (0%)
build/components/style.css 15.3 kB -2 B (0%)
build/compose/index.js 10.2 kB +121 B (1%)
build/core-data/index.js 15.4 kB +5 B (0%)
build/data/index.js 8.97 kB -1 B
build/date/index.js 31.8 kB -1 B
build/edit-navigation/index.js 11.1 kB +8 B (0%)
build/edit-post/index.js 306 kB -6 B (0%)
build/edit-site/index.js 24.7 kB -1 B
build/edit-widgets/index.js 26.3 kB -3 B (0%)
build/editor/index.js 43.4 kB +12 B (0%)
build/format-library/index.js 6.74 kB -1 B
build/hooks/index.js 2.27 kB +1 B
build/keyboard-shortcuts/index.js 2.54 kB +1 B
build/keycodes/index.js 1.94 kB +1 B
build/list-reusable-blocks/index.js 3.1 kB +1 B
build/nux/index.js 3.42 kB +2 B (0%)
build/plugins/index.js 2.56 kB -2 B (0%)
build/primitives/index.js 1.43 kB +1 B
build/rich-text/index.js 13.4 kB +1 B
build/server-side-render/index.js 2.76 kB -1 B
build/shortcode/index.js 1.69 kB -4 B (0%)
build/url/index.js 2.84 kB +1 B
build/warning/index.js 1.14 kB +1 B
ℹ️ View Unchanged
Filename Size Change
build/api-fetch/index.js 3.42 kB 0 B
build/autop/index.js 2.83 kB 0 B
build/blob/index.js 665 B 0 B
build/block-directory/style-rtl.css 943 B 0 B
build/block-directory/style.css 942 B 0 B
build/block-editor/style-rtl.css 11.2 kB 0 B
build/block-editor/style.css 11.2 kB 0 B
build/block-library/editor-rtl.css 9.07 kB 0 B
build/block-library/editor.css 9.07 kB 0 B
build/block-library/theme-rtl.css 789 B 0 B
build/block-library/theme.css 790 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.06 kB 0 B
build/blocks/index.js 48.1 kB 0 B
build/data-controls/index.js 827 B 0 B
build/deprecated/index.js 769 B 0 B
build/dom-ready/index.js 571 B 0 B
build/dom/index.js 4.95 kB 0 B
build/edit-navigation/style-rtl.css 881 B 0 B
build/edit-navigation/style.css 885 B 0 B
build/edit-post/style-rtl.css 6.49 kB 0 B
build/edit-post/style.css 6.47 kB 0 B
build/edit-site/style-rtl.css 3.93 kB 0 B
build/edit-site/style.css 3.93 kB 0 B
build/edit-widgets/style-rtl.css 3.13 kB 0 B
build/edit-widgets/style.css 3.13 kB 0 B
build/editor/editor-styles-rtl.css 476 B 0 B
build/editor/editor-styles.css 478 B 0 B
build/editor/style-rtl.css 3.85 kB 0 B
build/editor/style.css 3.84 kB 0 B
build/element/index.js 4.62 kB 0 B
build/escape-html/index.js 735 B 0 B
build/format-library/style-rtl.css 547 B 0 B
build/format-library/style.css 548 B 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.57 kB 0 B
build/is-shallow-equal/index.js 698 B 0 B
build/list-reusable-blocks/style-rtl.css 476 B 0 B
build/list-reusable-blocks/style.css 476 B 0 B
build/media-utils/index.js 5.31 kB 0 B
build/notices/index.js 1.82 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.84 kB 0 B
build/reusable-blocks/index.js 2.92 kB 0 B
build/token-list/index.js 1.27 kB 0 B
build/viewport/index.js 1.86 kB 0 B
build/wordcount/index.js 1.22 kB 0 B

compressed-size-action


- Type: `Function`

A function reference that must be passed to the DOM element where constrained tabbing should be enabled.
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to change.

Copy link
Contributor

@ntsekouras ntsekouras left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@youknowriad youknowriad merged commit 3cb657c into master Dec 8, 2020
@youknowriad youknowriad deleted the add/focus-on-mount-hook branch December 8, 2020 15:26
@github-actions github-actions bot added this to the Gutenberg 9.6 milestone Dec 8, 2020
@youknowriad youknowriad changed the title Extract the focusOnMount hook from the Popover component Add a useFocusOnMount hook to the @wordpress/compose package. Dec 8, 2020
@ellatrix
Copy link
Member

ellatrix commented Dec 9, 2020

Is there any other use case for this hook right now, since we're exporting this API? I see some uncertainties around the ref, so maybe it's too early to export/stabilise?

@youknowriad
Copy link
Contributor Author

I've used the hook in more places in a follow-up. In all PopoverWrapper components. What's the uncertainty here?


### `ref`

- Type: `Function`
Copy link
Member

Choose a reason for hiding this comment

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

So this is incorrect, right? An object ref is returned.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh right! I guess it should just say "Element ref". We don't really care whether it's a function or object.

@ellatrix
Copy link
Member

ellatrix commented Dec 9, 2020

Ah ok 👍

What's the uncertainty here?

The kind of ref returned, which is a minor thing I guess. Still, it could be a breaking change.

@youknowriad
Copy link
Contributor Author

The kind of ref returned, which is a minor thing I guess. Still, it could be a breaking change.

That's a good point, though, for me, it should probably reference the React Ref Element type. Users of the hook shouldn't be assuming what kind of ref it is.

@youknowriad
Copy link
Contributor Author

I'll do a follow-up to type these hooks properly.

@ellatrix
Copy link
Member

ellatrix commented Dec 9, 2020

Right, they shouldn't, but sometimes you're using the current property assuming the ref will always be an object. We have some code like that. :) I sometimes think it could be useful to create refs that are both, meaning a function which also has a getter named current.

const focusOnMountRef = useRef( focusOnMount );
useEffect( () => {
focusOnMountRef.current = focusOnMount;
}, [ focusOnMount ] );
Copy link
Member

Choose a reason for hiding this comment

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

Since focusOnMount is only used on mount, there doesn't really seem to be a need for updating it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As implemented here yes but I updated this hook later to solve the issue where the "ref" changes. an element can unmount without the component unmounting.

@ellatrix
Copy link
Member

I'm still not sure if it's a good idea to stabilise this hook. Components should autofocus themselves, the parent component shouldn't do that. That's why the timeout is needed I think. Unless this problem can be solved, there remains some uncertainty around this API in my opinion.

I think we should pass a prop down to the component that need autofocusing.

@youknowriad
Copy link
Contributor Author

Components should autofocus themselves

For me no but I'd love to hear more about why you think that.
For me components should be agnostic about where they are used:

  • If I use an Input as the first tabbable element in a popover/modal, and I auto-focus it this input is not reusable (can't be a reusable component)
  • If I use an autofocus prop for that input, and only pass it to true if it's a modal/popover is a parent, it means two things: All of our tabbable components must have the "auto-focus" prop and it also means that if for some reason you move the components around, say you add a button before the input, you shouldn't forget to change which component automounts.

For me, it's far less than ideal and breaks composability.

@ellatrix
Copy link
Member

I explored this in #27698.

The first item doesn't necessarily need receive focus, it could be any element. When it's done by the Popover implementor, they can do whatever they want.

@ellatrix
Copy link
Member

Ok, I agree with you. Let's keep the current behaviour. Still trying to get rid of the strange timeout in #27699.

@youknowriad
Copy link
Contributor Author

yes, I didn't give the timeout much thought in my refactoring, I just kept it from the previous implementation. Maybe it's not useful anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] New API New API to be used by plugin developers or package users.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants