Skip to content

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

Open
anaskim wants to merge 3 commits into
whatwg:mainfrom
anaskim:platform-provided-behaviors-1
Open

Add platform-provided behaviors for custom elements & submit behavior#12409
anaskim wants to merge 3 commits into
whatwg: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
@anaskim anaskim force-pushed the platform-provided-behaviors-1 branch from 4bed3e8 to 149f508 Compare May 15, 2026 19:33
@anaskim anaskim added the agenda+ To be discussed at a triage meeting label May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agenda+ To be discussed at a triage meeting

Development

Successfully merging this pull request may close these issues.

2 participants