Closed devongovett closed 2 years ago
Thanks for stopping by! I'm glad this seems interesting; I've had trouble getting anyone to express interest in https://github.com/WICG/proposals/issues/18 so I decided to just make a personal repo for now.
I'm happy to take feedback at this stage. The main thing to keep in mind is that the explainer is a bit outdated as (1) the cancel event is probably not going to be in v1, as I talk about below; (2) writing the spec on <dialog>
and fullscreen integration has crystalized my thinking on those a bit more. https://domenic.github.io/close-watcher/ provides more detail on what I'm currently thinking (although certainly not final!).
This feels like it could be potentially problematic in cases where you might have multiple open "panels" or some such UI. Did you consider whether it might make sense to scope close events to a DOM element and trigger the event by bubbling from the activeElement?
Currently the most-recently-created close watcher gets the signal. I usually think of signals as rather global gestures, not as something that specifically targets the currently-focused DOM element. I guess what you're envisioning is a bunch of non-modal panels, e.g. a webpage with a sidebar open, a datepicker open outside the sidebar, and then the whole thing in fullscreen? And you'd have something where if you focus inside the sidebar and press Esc, it closes the sidebar; if you focus inside the datepicker and press Esc, it closes the picker; and if you focus neither it exits fullscreen?
I suppose that could work. I'm unsure if it's what users expect, but it's hard to say.
Another potential advantage to that approach would be the ability to include pointer events such as clicking outside the element as a close signal.
This seems like it might be convenient, but I'm not sure where to draw the line on adding such conveniences. For example, I think it's better to wire up a close button explicitly to the close watcher, i.e. closeButton.onclick = () => watcher.signalClose()
. But we could similarly add sugar, like your { signalWhenClickingOutside: element }
(or { signalWhenClickingOutside: true, scope: element }
). Such sugar would be something like { signalWhenClickingOn: closeButton }
.
I feel like it's probably better to provide the basic signalClose()
mechanism, and say that its up to you to wire that up to any application-specific close affordances. Then, the line is clear: you only get automatic close signaling from genuine browser close signals.
Another question is whether JavaScript can potentially cancel a close signal. For example, if you had a custom input within a dialog that cleared when you pressed the escape key, you wouldn't want the dialog to close. Would preventDefault on the keyboard event prevent the close signal from firing (i.e. does the event need to bubble all the way back to the document - or whatever element the handler is scoped to if the above option is used)?
Yeah, so we definitely recognize people want this use case.
What I've currently specified is that if the close signal would fire an event, then canceling that event prevents the close signal from being delivered. So this works for e.g. the Esc key, but not the Android back button. (Although, see #2.)
The explainer additionally has a cancel
event which you can preventDefault()
: https://github.com/domenic/close-watcher#asking-for-confirmation . This is supposed to trigger a non-spoofable browser UI asking for confirmation, similar to beforeunload
today (but without blocking the event loop).
However, implementation-wise this feature is more difficult than the rest of the API combined. So I'm not sure it's going to survive in v1.
If we do launch without it, developers would need to resort to other patterns, such as not clearing the custom input when closing the dialog (so when the user reopens it that input is still there), as you can see from GitHub's "Review changes" popup. Or using a new URL plus https://github.com/WICG/app-history/issues/32 , like Twitter does with their "New Tweet" button.
It'd be great to hear if you have any data on how often this API would be usable without such a feature, e.g. by checking your app to see how many dialogs/pickers/sidebars/etc. would require such a confirmation step vs. how many would be OK without it.
I'll close this for now, but feel free to open issues on any followup questions you have! Note that the proposal has continued to evolve, and e.g. it now does have the cancel
event.
This looks very interesting! As someone who works on component libraries, this is something I've often wanted - especially the ability to tie into hardware back button and screen reader close signals. Apologies if the proposal isn't ready for feedback yet - feel free to disregard if so.
One question I had is if it makes sense for close events to be scoped. At the moment, my understanding is that the proposal is that they are global. If multiple
CloseWatcher
instances are created, then the most recently created instance is triggered. This feels like it could be potentially problematic in cases where you might have multiple open "panels" or some such UI. Did you consider whether it might make sense to scope close events to a DOM element and trigger the event by bubbling from theactiveElement
? Another potential advantage to that approach would be the ability to include pointer events such as clicking outside the element as a close signal.Another question is whether JavaScript can potentially cancel a close signal. For example, if you had a custom input within a dialog that cleared when you pressed the escape key, you wouldn't want the dialog to close. Would
preventDefault
on the keyboard event prevent the close signal from firing (i.e. does the event need to bubble all the way back to the document - or whatever element the handler is scoped to if the above option is used)?