whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
7.88k stars 2.58k forks source link

Add AbortSignal for popover.showPopover() for initialize internal CloseWatcher #10428

Open Jxck opened 2 weeks ago

Jxck commented 2 weeks ago

What problem are you trying to solve?

popover has a CloseWatcher internally, and CloseWatcher has AbortSignal option.

new CloseWatcher({ signal: AbortSignal.timeout(1000) })

Closing popover with timeout is a common use-cases I believe, but showPopover() doesn't accept any option. You should do that manually, like described in Spec example

// https://html.spec.whatwg.org/multipage/popover.html#the-popover-attribute
setTimeout(function () {
  outSpan.hidePopover();
}, 10000);

But currently, AbortSignal is a common practice to handle Async Timeouts. So it'd be nice if popover accepts AbortSignal like below for passing it into internal CloseWatcher.

outSpan.showPopover({ signal: AbortSignal.timeout(1000) });

What solutions exist today?

// https://html.spec.whatwg.org/multipage/popover.html#the-popover-attribute
setTimeout(function () {
  outSpan.hidePopover();
}, 10000);

How would you solve it?

Add PopoverOption to showPopover(). Same as CloseWatcherOptions

dictionary PopoverOptions {
  AbortSignal signal;
};

Anything else?

No response

keithamus commented 2 weeks ago

The solution you present that exists today is different to the mechanics of CloseWatcher's signal property. It seems like you're suggesting the signal should call hidePopover after a certain time, is this correct?

Can you explain the broader motivating use case for this please? Are you trying to make time sensitive UI? Time based UI is not in conformance with WCAG 2.2.3 and so ideally we would not encode such patterns into the web.

Jxck commented 2 weeks ago

@keithamus

you're suggesting the signal should call hidePopover after a certain time, is this correct?

Yes.

Can you explain the broader motivating use case for this please?

As spec itself describes in example, there are use-cases which close after timeout period.

setTimeout(function () {
  outSpan.hidePopover();
}, 10000);

https://html.spec.whatwg.org/multipage/popover.html#the-popover-attribute

for Example, OpenUI toast proposal also mentions that.

Toasts are often displayed in the corner of app UI, and often disappear on a timeout. https://open-ui.org/components/toast.research/

Toast was the origin of popover proposal (<toast> -> <popup> -> popover), so I think toast can be build upon popover today. Isn't it obvious that there is a use case?

keithamus commented 2 weeks ago

I'm aware of the general use case but I was more directly asking you for your use case.

Making something allowable per the expressivity of a primitive, and encoding something into the standard as an ordained pattern are two different things, however. We need to be careful that we are not creating solutions which make it far easier to fall out of conformance with WCAG.

Jxck commented 2 weeks ago

I don't make sure this guideline really applicable for popover too.

The objective of this technique is to provide users with all the time they need to complete an activity.

I think not all of popover requires "user activity to complete", because if you require activation (input anything, require submitting etc), that should be done via <dialog>. (IIUC, this is the important difference between dialog and popover)

We need to be careful that we are not creating solutions which make it far easier to fall out of conformance with WCAG.

I agree that, but it depends on understanding of WCAG 2.2.3 for me. If some <toast> components pop-overs temporal message to the user in multiple times in short-period, should it be explicitly closed by user every time ? in that case, I misunderstood popover use-cases, and hope it be explicitly guided in the specs or so too.

keithamus commented 2 weeks ago

I think not all of popover requires "user activity to complete", because if you require activation (input anything, require submitting etc), that should be done via <dialog>. (IIUC, this is the important difference between dialog and popover)

Right. popover is a low-level primitive which allows for interactive and non-interactive floating UI. <dialog> is a semantic dialog (it has role=dialog) but can still be managed with popover (e.g. <dialog popover>) and is a perfectly viable pattern of a non-modal dialog. <dialog>.showModal() is different in that it focus traps but either one could contain interactive elements.

I agree that, but it depends on understanding of WCAG 2.2.3 for me.

The test procedure is quite clear on WCAG 2.2.3:

Determine if any timed interactions are present (client and/or server side).

Any interaction that is timed fails the criterion. A <toast> which pops up a temporal message fails the criterion. This doesn't mean it cannot de-duplicate but the user has to be given sufficient time to assess the contents of the toast. Consequently we need to tread very carefully in what we do to encode these features into the platform.


Going back to the original request though; the AbortSignal on CloseWatcher destroys the close watcher (it does not "close" the close watcher, the "close" event is not fired, the close watcher is effectively removed from the stack). Therefore it is not equivalent to setTimeout(() => popover.hidePopover(), 1000).

Jxck commented 2 weeks ago

Going back to the original request

That's my fault, so it just fine with showPopover({ signal }).

Any interaction that is timed fails the criterion. A which pops up a temporal message fails the criterion.

Interesting. I'm keen to see comments from others too. (and in that case, It seems better to remove the setTimeout() example from spec to avoid misreadings).

lukewarlow commented 2 weeks ago

Going back to the original request though; the AbortSignal on CloseWatcher destroys the close watcher (it does not "close" the close watcher, the "close" event is not fired, the close watcher is effectively removed from the stack). Therefore it is not equivalent to setTimeout(() => popover.hidePopover(), 1000).

Came here to say this. CloseWatcher's signal is for use to for example cleanup on element removal. Popover (and modal dialog)'s close watcher has this behaviour built in so we don't really need a signal in the close watcher sense.

If we imagine that signal will call hidePopover instead. Then other than a timeout case (Which may or may not be bad), most other signal patterns don't seem to apply?