-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Adding constrainTabbing
prop to useDialog
hook
#57962
Adding constrainTabbing
prop to useDialog
hook
#57962
Conversation
Tabbing constraint is currently tied to the `focusOnMount` prop in `useDialog'; if `focusOnMount` is not `false`, tabbing will be constrained. Sometimes we want the `focusOnMount` behaviour, without constrained tabbing. This patch adds a separate `constrainTabbing` prop, which implicitly maintains the current behaviour, taking its default value from `focusOnMount`. Otherwise, if set explicitly, tabbing will be constrained based on the value passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather that the individual props, I wonder if we should consider a modal
boolean prop:
- when
true
, the popover constrains tabbing and sets the rest of the document as inert - when
false
, the popover doesn't constrain tabbing nor removes the rest of the document from the accessible tree
(cc @mirka )
This sounds ideal to me in theory, and it aligns with the terminology/behavior used for the One caveat is that I don't have too much context on the overall dialog strategy used in our codebase — looking at the Popover/Modal components, some parts are handled with wp-compose hooks while other parts use one-off utils like this That said, at first glance it does seem feasible to add an |
Trying to think if there's ever a situation where a dialog would want to constrain tabbing, but not be modal. Or, equally, if there's a case for something to be modal but not a dialog. Just wondering if it's worth creating another hook ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to think if there's ever a situation where a dialog would want to constrain tabbing, but not be modal.
I did some digging here. MDN docs state that a dialog can be non-modal (we knew this).
They also state that for most dialogs, the expected behavior is that the dialog's tab order wraps.
They go on to say that for non-modal dialogs there will have to be a global keyboard shortcut that allows focus to be moved between opened dialogs and the main page.
I also like @mirka's idea of having a isModal
prop to handle all this.
The fun thing here is that although the hook is called Unfortunately, without a fair bit of refactoring, I'm not sure as we can safely assume |
Given all the uncertainty, it does sound like it would be more manageable to keep things modular so we have the flexibility to combine behaviors as needed. Let's stick with |
I started working on tests for this, but discovered a bug in Essentially, So we either wait for that to be resolved, or we proceed without working tests. |
Scaffold the test and then proceed whilst also raising an Issue to re-enable the tests once fixed? |
Size Change: +2.34 kB (0%) Total Size: 1.7 MB
ℹ️ View Unchanged
|
I've added some tests, but disabled the ones that currently fail (essentially any that expect tab constraint). Will file a new issue to sort that if/when this lands. |
Flaky tests detected in e7f4d59. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/7646504342
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Things are looking good, at least when using the component in isolation.
@getdave , would this PR work for the use case that you initially brought up?
Unrelated to this PR, but I noticed that, at least when testing in Storybook, clicking on the <Popover />
component's children closes the popover. The behavior can also be reproduced on trunk
. I don't think that's expected ?
Testing this now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my testing this works well.
I tested using
gutenberg/packages/format-library/src/link/inline.js
Lines 244 to 251 in a241134
<Popover | |
anchor={ popoverAnchor } | |
onClose={ stopAddingLink } | |
onFocusOutside={ onFocusOutside } | |
placement="bottom" | |
offset={ 10 } | |
shift | |
> |
I set some test variables and passed them to the Popover
and also console.log
them so you can see the results of each test.
focusOnMount | constrainTabbing | Result | Screencapture |
---|---|---|---|
false |
undefined |
Passed | Video |
true |
undefined |
Passed | Video |
true |
false |
Passed | Video |
false |
true |
Passed | Video |
Left a test nit, but nothing major. Thank you for working on this 🙇
@mirka @ciampo don't know if you have any final thoughts, but this seems ready to land.
Can't comment on whether it's expected, but it does seem a bit weird! If it's happening in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
Resolves #57877.
What?
This patch adds a
constrainTabbing
prop to theuseDialog
hook (and consumes it in thePopover
component).Why?
Tabbing constraint is currently tied to the
focusOnMount
prop inuseDialog
; iffocusOnMount
is notfalse
, tabbing will be constrained. Sometimes we want thefocusOnMount
behaviour, without constrained tabbing.How?
Tabbing constraint is now controlled by the
constrainTabbing
prop. To maintain backwards compatibility/current behaviour, it implicitly takes its default value fromfocusOnMount
.Otherwise, if set explicitly, tabbing will be constrained based on the value passed.
Testing Instructions
useDialog
andPopover
should continue to work as before.Hooks don't seem to have unit tests, but I should probably add one to
Popover
(and maybe a story).