-
Notifications
You must be signed in to change notification settings - Fork 2
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 popover capabilities to SelectNext listbox #1540
Conversation
69b1620
to
4f9e4bf
Compare
4f9e4bf
to
c77948c
Compare
c77948c
to
8a823b1
Compare
8714ed3
to
689fa55
Compare
I think this is fine. In future you could use CSS anchor positioning for this. That is an extremely recent addition to the web platform, so not viable yet.
My understanding is that after the listbox is opened, if
So the problem here is the ordering of steps (2) and (3). If step (1) updated the DOM style synchronously, then the listbox would have its correct position by the time
Yes, that makes sense. |
One other thing that occurred to me is that you could try to make the popover and non-popover use cases more similar by rendering the listbox children into their own element which is positioned at the top-level of the DOM, like how React portals work. The downside is that event bubbling won't work, so you'd either have to emulate it, or warn consumers about this hazard. |
689fa55
to
781ca90
Compare
You are right! If the styles are directly set via |
3303ad3
to
ce84fe8
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #1540 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 63 63
Lines 1008 1041 +33
Branches 383 395 +12
=========================================
+ Hits 1008 1041 +33 ☔ View full report in Codecov by Sentry. |
ce84fe8
to
643696e
Compare
e81cd0c
to
538b24a
Compare
The only uncovered line that codecov is complaining about, is marked as |
538b24a
to
45b2435
Compare
45b2435
to
d78c20e
Compare
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.
The implementation generally looks good and worked as expected in all browsers that I tested. The main feedback I have is to add some comments for some of the more subtle issues in the code: why the listbox is being positioned manually, why the styles are applied synchronously, why we're using a popover in the first place. You don't need to repeat everything in the PR description. Just brief notes to raise awareness will do.
4ac5b64
to
b25768d
Compare
b25768d
to
af4a1c2
Compare
@@ -21,13 +21,26 @@ describe('SelectNext', () => { | |||
* Whether to renders SelectNext.Option children with callback notation. | |||
* Used primarily to test and cover both branches. | |||
* Defaults to true. | |||
* @param {boolean} [options.defaultListboxAsPopover] - | |||
* Whether we should let the `listboxAsPopover` prop use default value | |||
* if not explicitly provided, or we should initialize it instead. |
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.
Assuming most tests don't set this option, it means we'll be explicitly disabling the popover usage, right? We probably want tests to use the default behavior of the component except for tests that are specifically opting out.
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.
Yep, I agree. However, there are some tests failing when using the popover mode, mostly around testing that focusing works as expected in certain scenarios (first option gets focused when opened, the toggle recovers focus when closed, etc.). I assume it's related with the use of the top layer, but I couldn't confirm it.
I tried a couple of times to make them pass, but finally decided to disable the popover mode by default for the sake of getting existing tests to pass, and focus on popover mode only for new tests.
I will address this in a follow-up PR, as I think you are definitely right, but I wanted to offload some indirect complexity from this one.
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.
The added comments LGTM. I did have a minor query about the default value of listboxAsPopover
in tests. It looks like the default is to turn this behavior off except for tests that opt in. Is that intended?
Depends on #1548
Add
popover
attribute to theSelectNext
listbox, and open it viaelement.togglePopover()
when the browser supports it.For browsers not supporting the native popover, we continue to handle it as before.
TODO
[popover]
does not have any side effects on how components are announced.Considerations
popover
attribute to the listbox makes it render in the top layer, and therefore, it is no longer positioned relative to the toggle button.Because of that, we have to manually calculate where should it be based on some heuristics, and absolutely position it there.
Related with the point above, and because of howuseArrowKeyNavigation
internally works, I had to disable the automatic option focusing thatuseArrowKeyNavigation
provides, and add an extratoggle
event listener that mimics that logic.EDIT: This has been solved. See Add popover capabilities to SelectNext listbox #1540 (comment)
Another side effect of rendering the listbox in the top layer, is that it won't be affected by scrolling on inner elements.EDIT: This is now mitigated vialistboxAsPopover
prop. With that we can keep the listbox as is, and enable the "popover mode" only when really needed.EDIT 2: Finally we are capturing the scroll event and re-adjust the listbox positioning dynamically.
Popover
component, that can be used in other places, but this is complex enough, without having to think in more abstractions. I will delay that to after this PR has been merged, and we have at least other use case for a popover.