Skip to content

Commit c6753e0

Browse files
authored
Platform provided behaviors feedback 9 (#1293)
- Resolve open question on automatically exposing attributes and properties on the element rather than on the behavior. - Resolve to propose the current API shape where web developers would hold direct references to behaviors.
1 parent c7e0e1b commit c6753e0

File tree

1 file changed

+23
-42
lines changed

1 file changed

+23
-42
lines changed

PlatformProvidedBehaviors/explainer.md

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -232,23 +232,15 @@ This ensures that element-specific properties like `behavior.form` and `behavior
232232
233233
### API design
234234
235-
The current API uses instantiated behaviors with a single `behaviors` property:
235+
Behaviors are instantiated with `new` and passed to `attachInternals()`:
236236
237237
- `behaviors` option in `attachInternals({ behaviors: [...] })` accepts behavior instances.
238238
- `behaviors` property on `ElementInternals` is a read-only `FrozenArray`.
239239
- Developers hold direct references to their behavior instances.
240240
241241
*Note: An ordered array is preferred over a set because order may be significant for [conflict resolution](#behavior-composition-and-conflict-resolution). `behaviors` uses a `FrozenArray` because behaviors are immutable after attachment.*
242242
243-
**Pros:**
244-
- Single property name.
245-
- No array lookup or `instanceof` checks needed as developers hold direct references.
246-
- *Future* developer-defined behaviors are simpler: just instantiate and attach.
247-
- Consistent mental model: behaviors are objects you create and manage.
248-
249-
**Cons:**
250-
- Requires developers to manage behavior instances themselves.
251-
- More setup code compared to passing class references directly.
243+
Developers hold direct references to their behavior instances. This aligns with the [W3C design principle that classes should have constructors](https://www.w3.org/TR/design-principles/#constructors) that allow authors to create and configure instances, and it extends naturally to future developer-defined behaviors that follow the same `new` + attach pattern.
252244
253245
*For future developer-defined behaviors:*
254246
@@ -270,27 +262,6 @@ this._internals = this.attachInternals({ behaviors: [this._tooltipBehavior] });
270262
this._tooltipBehavior.content = 'Helpful tooltip text';
271263
```
272264
273-
#### Alternative 1: Class references
274-
275-
Pass behavior classes (not instances) to `attachInternals()`:
276-
277-
```javascript
278-
// Attach a behavior during initialization (class reference).
279-
this._internals = this.attachInternals({ behaviors: [HTMLSubmitButtonBehavior] });
280-
281-
// Access behavior state via named accessor.
282-
this._internals.behaviors.htmlSubmitButton.formAction = '/custom';
283-
```
284-
285-
**Pros:**
286-
- Named access via `this._internals.behaviors.<behaviorName>` requires no iteration.
287-
- Less setup code as developers don't manage behavior instances.
288-
289-
**Cons:**
290-
- Platform instantiates the behavior, so constructor parameters aren't available. This conflicts with the [design principle that classes should have constructors](https://www.w3.org/TR/design-principles/#constructors) that allow authors to create and configure instances.
291-
- Requires a `behaviors` interface for named access.
292-
- *Future* developer-defined behaviors would need a way to name their behaviors.
293-
294265
### Behavior composition and conflict resolution
295266
296267
When multiple behaviors are attached to an element, they may provide overlapping capabilities. This section discusses strategies for resolving such conflicts.
@@ -839,17 +810,6 @@ Although this proposal currently focuses on custom elements, the behavior patter
839810
840811
## Open questions
841812
842-
### Should behavior properties be automatically exposed on the element?
843-
844-
The current proposal uses manual property delegation: developers create getters/setters that delegate to the stored behavior instance. This gives authors full control over their public API, avoids naming conflicts, and allows validation or side effects in setters. The tradeoff is boilerplate for each exposed property.
845-
846-
Two alternatives have been considered:
847-
848-
- **Automatic property exposure:** The platform adds behavior properties directly to the custom element (e.g., `btn.disabled = true` works without any getter/setter). This matches how native elements work but introduces naming conflicts, reduces API control, and feels "magical."
849-
- **Opt-in automatic exposure:** Authors choose per-element whether properties are auto-exposed via an option like `exposeProperties: true`. This offers flexibility but adds API complexity.
850-
851-
Future behaviors like `HTMLCheckboxBehavior` or `HTMLInputBehavior` would require developers to write boilerplate for key properties (`checked`, `value`) that external code needs to access. A consistent approach across all behaviors should be decided before additional behaviors ship.
852-
853813
### Is there a better name than "behavior" for this concept?
854814
855815
The American English spelling of behavior throughout this proposal follows the [WHATWG spec style guidelines](https://wiki.whatwg.org/wiki/Specs/style#:~:text=Use%20standard%20American%20English%20spelling). However, the word "behavior" has some drawbacks:
@@ -1042,6 +1002,27 @@ customElements.define('custom-button', CustomButton);
10421002
10431003
`HTMLSubmitButtonBehavior` could itself be designed as a decorator, but decorators can't easily access `ElementInternals` or instance state during application. Decorators would need to coordinate with `attachInternals()` timing. Additionally, getting a reference to the behavior instance for property access (e.g., `behavior.formAction`) would require additional wiring.
10441004
1005+
### Alternative to API design: Class references
1006+
1007+
Pass behavior classes (not instances) to `attachInternals()`:
1008+
1009+
```javascript
1010+
// Attach a behavior during initialization (class reference).
1011+
this._internals = this.attachInternals({ behaviors: [HTMLSubmitButtonBehavior] });
1012+
1013+
// Access behavior state via named accessor.
1014+
this._internals.behaviors.htmlSubmitButton.formAction = '/custom';
1015+
```
1016+
1017+
**Pros:**
1018+
- Named access via `this._internals.behaviors.<behaviorName>` requires no iteration.
1019+
- Less setup code as developers don't manage behavior instances.
1020+
1021+
**Cons:**
1022+
- Platform instantiates the behavior, so constructor parameters aren't available. This conflicts with the [design principle that classes should have constructors](https://www.w3.org/TR/design-principles/#constructors) that allow authors to create and configure instances.
1023+
- Requires a `behaviors` interface for named access.
1024+
- *Future* developer-defined behaviors would need a way to name their behaviors.
1025+
10451026
## Accessibility, security, and privacy considerations
10461027
10471028
### Accessibility

0 commit comments

Comments
 (0)