-
Notifications
You must be signed in to change notification settings - Fork 3
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
Fix Popover not opening when not using the native API #1804
Conversation
@@ -355,8 +355,7 @@ function SelectMain<T>({ | |||
listboxOverflow = 'truncate', | |||
'aria-label': ariaLabel, | |||
'aria-labelledby': ariaLabelledBy, | |||
/* eslint-disable-next-line no-prototype-builtins */ | |||
listboxAsPopover = HTMLElement.prototype.hasOwnProperty('popover'), | |||
listboxAsPopover, |
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.
This was duplicated. The fallback logic now lives in Popover
and we don't need to define a default value here anymore.
This problem actually happens with native popovers in Safari at the moment. Clicking the toggle button for a If using the native <button popovertarget="mypopover" popovertargetaction="toggle">
Toggle popover
</button>
<div id="mypopover" popover>Popover content</div> If using the same terminology as the web APIs, then we are saying that we assume the popover is anchored to element that controls it, which is currently always the case. In future we could evolve the API by making it possible to specify a separate control element vs anchor element. I'm not sure if we'll actually need that. |
Good catch. I guess we could do the same check in the
This would be another option, but I would prefer to not introduce this to avoid mixing a controlled and uncontrolled component. Perhaps we could eventually have an But let's do that when all browsers we support can use the popover API. Right now it might be a bit complicated to coordinate.
Perfect, let's do that. |
I tried this, and it breaks the behavior in Chrome and Firefox. I even tried making sure onClick is not added if those attributes are, but then the popover is opened empty because rendering the children is still based on the So basically we need to either transition to a completely different model where popover events are the source of truth that drive state updates, or we do state the source of truth that drives toggling the native popover, but a mix doesn't work. And the later is the only option as long as we support browsers which do not support the popover API. Unfortunately, my suggestion of doing the same on the I may need your help debugging this, as I don't have access to a Safari browser. |
I would suggest not to worry about the Safari issue for this PR, since it isn't a regression. I can take a look next week and try to understand better what the difference is between Chrome/FF and Safari when using native popovers. |
Yeah, good point. |
24215dc
to
41c7ccb
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #1804 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 68 68
Lines 1231 1234 +3
Branches 467 468 +1
=========================================
+ Hits 1231 1234 +3 ☔ View full report in Codecov by Sentry. |
This PR fixes some regressions introduced in #1800, when
onClose
was implemented, and the logic to close the popover on click away and on Escape press was moved from theSelect
component to thePopover
.The issues affect only browsers where the native popover API is not supported.
Context
Originally, the popover was part of
Select
, anduseCickAway()
was invoked there with the container wrapping both the toggle button and the popover.After the
Popover
was extracted as a standalone component, we realized it had click-away capabilities built-in when using the native popover API, so we decided to moveuseClickAway
there as well for consistency.However, the element passed to
useClickAway
became the popover only, as it was no longer aware of any toggle or wrapper.This introduced the first issue fixed here: Clicking the toggle button now triggers a
setOpen(true)
, but also a click-away, which sets it back to false, so the popover could not be opened anymore.This has been addressed by ensuring
useClickAway
is enabled only while the popover is open.But this introduces the second issue: We now have the oposite problem. The popover can be opened, but when trying to close it by clicking the toggle, it first triggers a click-away, closing the popover, and then triggers the click on the toggle button, opening it again immediately after.
This has been addressed by ensuring
useClickAway
ignores events triggered on the popover's anchor element, which is usually its toggle button.Considerations
I think the first solution is non-controversial, but the second one is making some assumptions which may not always be correct.
In the
Select
case, the anchor element is the toggle button, so the solution applied is correct, but in future we may want to anchor popovers to elements which are not triggers, in which case we would wantuseClickAway
to behave the same when clicking on them.I'm open to suggestions on alternative solutions for the second issue.
Testing steps
The issue was reproducible only when not using the native API, so you first need to apply this diff:
Then go to http://localhost:4001/feedback-popover and verify popovers can be opened/closed by clicking the toggle, clicking away or pressing Escape.
Note
There's an unrelated issue when not using the native popover API, in which popovers never grow more than their anchor element. I'm addressing that separately.