The explainer seems to go down a route to a full composition (an array of behavior with conflict resolution), while mainly defining use cases to do with buttons.
OTOH, a "mutually exclusive" version (a single type) was dismissed as being too restrictive, and splitting those behaviors to very small atoms seems to difficult to use without creating accessibility and usability issues.
Suggesting that there is a middle ground, where we can define "clusters" of mutually exclusive behaviors, but those clusters can be composed.
Specifically, we can define something like activationBehavior that can be either submit-button, reset-button, regular button, or link - but it can't be both a reset button and a link, for example.
We can later define other types or clusters of behaviors like this if we so choose, e.g. a replacedContent behavior that can support either image/video/canvas etc.
We can then reason about which behaviors are mutually exclusive or parallel, but the general idea is that most confict resolution occurs on the WebIDL level rather than in internal logic - you don't have to create some underlying behavior or an error for {behaviors: ["button", "link"]}, it's simply impossible to do that in the API.
So something like this: (totally bikesheddable)
class MySubmitButton extends HTMLElement {
// Either static or only changeable when element is disconnected
// This element would now get all of the activation behavior of submit buttons like focus,
// default aria role, responding to `Enter` etc
static activationBehavior = "submit";
constructor() {
const internals = this.attachInternals();
internals.activationBehavior.formAction = "POST";
}
}
class MyLink extends HTMLElement {
// Either static or only changeable when element is disconnected
// This element would now get all of the activation behavior of links,
// like right-click to open in a new tab or hover to prerender.
static activationBehavior = "link";
constructor() {
const internals = this.attachInternals();
internals.activationBehavior.href = "/example/";
}
}
Later if we want to compose activation with replaced content:
(This is illustrative, I'm not sure it's a good idea on its own but it would be a way to compose things)
class MyVideoButton extends HTMLElement {
static activation = "button";
static replacedContent = "video";
constructor() {
const internals = this.attachInternals();
internals.replacedContent.src = "/example.mp4";
}
}
The explainer seems to go down a route to a full composition (an array of behavior with conflict resolution), while mainly defining use cases to do with buttons.
OTOH, a "mutually exclusive" version (a single
type) was dismissed as being too restrictive, and splitting those behaviors to very small atoms seems to difficult to use without creating accessibility and usability issues.Suggesting that there is a middle ground, where we can define "clusters" of mutually exclusive behaviors, but those clusters can be composed.
Specifically, we can define something like
activationBehaviorthat can be either submit-button, reset-button, regular button, or link - but it can't be both a reset button and a link, for example.We can later define other types or clusters of behaviors like this if we so choose, e.g. a
replacedContentbehavior that can support either image/video/canvas etc.We can then reason about which behaviors are mutually exclusive or parallel, but the general idea is that most confict resolution occurs on the WebIDL level rather than in internal logic - you don't have to create some underlying behavior or an error for
{behaviors: ["button", "link"]}, it's simply impossible to do that in the API.So something like this: (totally bikesheddable)
Later if we want to compose activation with replaced content:
(This is illustrative, I'm not sure it's a good idea on its own but it would be a way to compose things)