w3ctag / design-reviews

W3C specs and API reviews
Creative Commons Zero v1.0 Universal
318 stars 55 forks source link

Invokers API #920

Closed keithamus closed 3 months ago

keithamus commented 6 months ago

こんにちは TAG-さん!

I'm requesting a TAG review of the "Invokers API", as described in the Open UI explainer.

Adding invoketarget and invokeaction attributes to <button> and <input type="button"> / <input type="reset"> elements would allow authors to assign behaviour to buttons in a more accessible and declarative way, while reducing bugs and simplifying the amount of JavaScript pages are required to ship for interactivity. Buttons with invoketarget will - when clicked, touched, or enacted via keypress - dispatch an InvokeEvent on the element referenced by invoketarget, with some default behaviours.

<button invoketarget="my-dialog">This opens a dialog</button>
<dialog id="my-dialog">This is the dialog</dialog>

While there are many ideas for what those behaviours will be, for the initial implementation we want to ship:


Further details:

You should also know that...

We are looking for help with resolving the naming of actions, and how we can best fit the existing system. We're explicitly interested in feedback from the TAG!

This works surrounds some larger work pieces, for example there is follow on work to add more actions, follow on work to add an interesttarget which will do the same but for hover/focus style interactions, and we are also looking to deprecate popovertarget in favour of this API. While we're not seeking review for those parts, I hope they can paint a broader context of what is planned here.

We'd prefer the TAG provide feedback as:

🐛 open issues in our GitHub repo for each point of feedback

martinthomson commented 4 months ago

@plinss and I discussed this briefly and while we think the overall capability looks good, we have some questions:

Is there a way to detect that this feature exists?

Why is there no generic .invoke() method for invocation targets? If targets have default action (called "auto"?) this might make it more ergonomic for authors rather than needing to work out how to achieve an action.

Why does <details> have "toggle" and "auto" actions doing the same thing?

Why does the <dialog> "toggle" action do the same thing as "cancel"? Why does this not show the dialog when it is not already open?

Is there a polyfill planned?

Does invoking alter focus? If something is invoked, does that receive focus? It seems like this would usually be the case, but some actions might not need that. Pausing a video doesn't need to draw focus, but you would want to focus <select> or <dialog> or a popover. Whatever the behavior is, it should be specified so to be consistent across UAs.

lukewarlow commented 4 months ago

Is there a way to detect that this feature exists?

Checking if an element has an invokeTargetElement property could be used as a feature detection mechanism.

Why is there no generic .invoke() method for invocation targets? If targets have default action (called "auto"?) this might make it more ergonomic for authors rather than needing to work out how to achieve an action.

While this is possible it would be potentially superfluous, popovers already have a togglePopover() function for example. It has been considered that actions should have a corresponding JS API though but idk if it makes sense to have the two go hand in hand always.

Why does <details> have "toggle" and "auto" actions doing the same thing?

Auto is the missing value default for the invokeaction attribute. `toggle' is just an explicit token for said action in the details case. This is something we're not entirely sure on and intentionally it's left as a question for future as it's not a blocker for v1 actions.

Why does the <dialog> "toggle" action do the same thing as "cancel"?

Apologies this is a mistake in the explainer.

Is there a polyfill planned?

https://github.com/keithamus/invokers-polyfill

lukewarlow commented 4 months ago

Does invoking alter focus? If something is invoked, does that receive focus?

I Think this ultimately depends on the action itself like you say for showPicker the select should be focused, for pause a video probably not. We'll ensure these are concretely specced.

lukewarlow commented 4 months ago

To further help in your review of the explainer (though your feedback and input on the extended feature design is definitely welcome and encouraged) it may be worth noting that the initial version only has actions for popover and Modal Dialogs.

Along with the concept of custom actions and their associated naming restrictions.

keithamus commented 4 months ago

To add to Luke's commentary:

Is there a way to detect that this feature exists?

'invokeTargetElement' in HTMLButtonElement.prototype or 'invokeAction' in HTMLButtonElement.prototype, either one will do.

Why is there no generic .invoke() method for invocation targets? If targets have default action (called "auto"?) this might make it more ergonomic for authors rather than needing to work out how to achieve an action.

Generally speaking invoke actions map to imperative APIs, where "auto" is an alias for "do the most common action". So if an invoker is pointing to a popover, the default action is to call togglePopover(), if it is pointing to a dialog, it will call either close() or showModal() depending on the state of the dialog. We spoke of adding a toggleModal() to Dialog, and have https://github.com/openui/open-ui/issues/954 raised to decide if we should more closely map the actions to imperative APIs, which may mean adding new methods.

Why does <details> have "toggle" and "auto" actions doing the same thing?

"auto" is the stand-in for when the attribute value is missing, so <button invoketarget=my_details> (no invokeaction) will do the "auto" behaviour. This is being changed to be "the auto state" (as in a null or empty string of the attribute) so explicitly "auto" will do nothing. See https://github.com/openui/open-ui/pull/1006

Does invoking alter focus? [...] Whatever the behavior is, it should be specified so to be consistent across UAs.

"It depends". When it does, it will most certainly be specified. Specifically for a popover it runs the popover focusing steps - which may or may not change focus, and for <dialog> elements it runs the dialog focusing steps, which definitely does change focus. Those are the only two specced right now but the others we will be sure to specify whether they change focus or not.

mfreed7 commented 4 months ago

"It depends". When it does, it will most certainly be specified. Specifically for a popover it runs the popover focusing steps - which may or may not change focus, and for <dialog> elements it runs the dialog focusing steps, which definitely does change focus. Those are the only two specced right now but the others we will be sure to specify whether they change focus or not.

I think another way to think about this is that the invoker logic should (always?) execute an existing imperative algorithm/function. And those should already be doing the right thing. So for popover and dialog, the showPopover and showModal functions should already correctly manage the focus.

martinthomson commented 3 months ago

@hober, @plinss, and I discussed this today.

We're broadly in favor of invokers because it unifies some existing interaction patterns.

We feel it makes sense to have an invoke(action, invoker) method because it lays a path for future interactions with elements. We think that this might be more useful for custom elements or future features that are added to the platform.

We observe that a lack of additional arguments to invocations (or invoke()) are a concession toward the declarative nature of the core feature. Rather than a flaw, we see this as an important characteristic of the design. It simplifies this design and this characteristic seems like it is worth protecting. Richer interactions can remain the domain of script.

Having invoke() also helps discoverability. We think that this would be more useful if it were possible to get the list of available actions from elements.

(A footnote from me: when we ask questions, like the one above about focus, we appreciate your helpful answers. We appreciate those answers being added to documentation even more.)