Skip to content

Add platform-provided behaviors for custom elements & submit behavior#12409

Open
anaskim wants to merge 2 commits intowhatwg:mainfrom
anaskim:platform-provided-behaviors-1
Open

Add platform-provided behaviors for custom elements & submit behavior#12409
anaskim wants to merge 2 commits intowhatwg:mainfrom
anaskim:platform-provided-behaviors-1

Conversation

@anaskim
Copy link
Copy Markdown
Member

@anaskim anaskim commented Apr 27, 2026

#12150

This change introduces platform-provided behaviors, a mechanism that allows autonomous custom elements to adopt built-in HTML element capabilities via attachInternals(). The initial element behavior is HTMLSubmitButtonBehavior, which gives a custom element submit button semantics including form submission, activation, focusability, and an implicit ARIA role.

Explainer: https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/PlatformProvidedBehaviors/explainer.md

(See WHATWG Working Mode: Changes for more details.)


/custom-elements.html ( diff )
/dom.html ( diff )
/form-control-infrastructure.html ( diff )
/forms.html ( diff )
/index.html ( diff )
/interaction.html ( diff )
/semantics-other.html ( diff )

@anaskim anaskim marked this pull request as draft April 27, 2026 21:36
@anaskim anaskim force-pushed the platform-provided-behaviors-1 branch from 0456d21 to 809a55a Compare April 27, 2026 21:39
@anaskim anaskim force-pushed the platform-provided-behaviors-1 branch from d75a481 to af114db Compare May 1, 2026 18:58
@anaskim anaskim marked this pull request as ready for review May 1, 2026 19:04
@keithamus
Copy link
Copy Markdown
Member

I have done an initial pass, just glossing over this. Things look generally good (though I will look a lot closer later this week). One question that stands out from a first pass: we use instanceof checks to check a behaviour, which prompts me to check subclasses. The behaviour is a little surprising... So for example in Chrome today:

class Foo extends HTMLSubmitButtonBehavior { };
class Bar extends HTMLSubmitButtonBehavior { };
class MyEl extends HTMLElement { 
  constructor() {
    super();
    this.foo = new Foo();
    this.bar = new Bar();
    this.attachInternals({ behaviors: [this.foo, this.bar] });
  }
}
customElements.define('my-el', MyEl);
document.createElement('my-el');

This gives me an error of Uncaught TypeError: Failed to execute 'attachInternals' on 'HTMLElement': Only one instance of HTMLSubmitButtonBehavior is allowed per element. which seems right, but it's a confusing message as MyEl only attached Foo and Bar.

My assumption would have been we prevent users from extending behaviours; there are a lot of questions about what inheriting means, especially for a native behaviour. Might be worth some investigation. I think the plausible answers are "prevent inheritance" or "offer a lot more detail on what's possible/use cases for inheritance".

@anaskim anaskim added the agenda+ To be discussed at a triage meeting label May 4, 2026
@anaskim
Copy link
Copy Markdown
Member Author

anaskim commented May 6, 2026

I have done an initial pass, just glossing over this. Things look generally good (though I will look a lot closer later this week). One question that stands out from a first pass: we use instanceof checks to check a behaviour, which prompts me to check subclasses. The behaviour is a little surprising... So for example in Chrome today:

class Foo extends HTMLSubmitButtonBehavior { };
class Bar extends HTMLSubmitButtonBehavior { };
class MyEl extends HTMLElement { 
  constructor() {
    super();
    this.foo = new Foo();
    this.bar = new Bar();
    this.attachInternals({ behaviors: [this.foo, this.bar] });
  }
}
customElements.define('my-el', MyEl);
document.createElement('my-el');

This gives me an error of Uncaught TypeError: Failed to execute 'attachInternals' on 'HTMLElement': Only one instance of HTMLSubmitButtonBehavior is allowed per element. which seems right, but it's a confusing message as MyEl only attached Foo and Bar.

My assumption would have been we prevent users from extending behaviours; there are a lot of questions about what inheriting means, especially for a native behaviour. Might be worth some investigation. I think the plausible answers are "prevent inheritance" or "offer a lot more detail on what's possible/use cases for inheritance".

Thanks for taking a look, @keithamus! My inclination is to say that subclassing platform-provided behaviors like HTMLSubmitButtonBehavior should not be allowed. The instanceof-based duplicate check makes subclass interactions confusing, as your example shows, and there isn’t a clear semantic for what customizing a native/platform-provided behavior through inheritance should mean.

I’ve updated the spec text so HTMLSubmitButtonBehavior() throws a TypeError when constructed through a subclass,
and added a short note explaining that platform-provided behaviors are not designed to be subclassed. Let me know if you think this should be captured differently, but I think preventing subclassing is the cleaner option for this proposal.

@anaskim anaskim removed the agenda+ To be discussed at a triage meeting label May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants