Re: [w3ctag/design-reviews] [WebComponents] Custom state pseudo class (#428)

@tkent-google and I spent some time discussing how to collect data on this subject, as well as the general problem space. Here is where we ended up:

> Given that people are currently exposing state in custom elements by using attributes, and using attribute selectors, and this feature is meant to supplant that practice,

We don't think this is the right premise to be operating from.  This feature is for states which depend on extrinsic factors such as user input, as [the first paragraph of the explainer](https://github.com/w3c/webcomponents/blob/gh-pages/proposals/custom-states-and-state-pseudo-class.md#introduction) mentions.  Component authors can't map such states to content attributes now, or do so but then end up with a fragile public interface---because component users can modify content attribute values.

To see what we mean, consider the built-in pseudo-class states `:active`, `:hover`, `:valid`, and `:invalid`, which can't be mapped to content attributes. I.e., what would `aEl.removeAttribute("hover")` mean? This feature is intended for cases like that.

(Side note: there are some older pseudo-classes like `:checked` which map more directly to content attributes, but newer elements like `<dialog>` and `<details>`, or element proposals like `<std-switch>`, do not create redundant pseudo-classes that are 1:1 with content attributes, instead allowing authors to do normal attribute selectors like `dialog[open] { ... }` or `std-switch[on] { ... }`.)

Regardless, we respect the call for research and did a bit of looking through existing custom element control libraries to find what types of internal states they expose.

* Ionic Framework doesn't need non-boolean states as [@adamdbradley's comment](https://github.com/w3ctag/design-reviews/issues/428#issuecomment-542881859) states.

* Polymer elements: We found only one candidate non-boolean state; the [immediateValue of `<paper-slider>`](https://www.webcomponents.org/element/PolymerElements/paper-slider/elements/paper-slider#property-immediateValue). However we don't think exposing such a continuous value as a state is reasonable. It's unlikely that people want to apply different styles for each of continuous values. Instead, a component can behave like the native `<input type=range>`: it can expose a state change event, and/or provide boolean states like is-minimum-value, is-maximum-value, is-less-than-criterion for such continuous values.

So our conclusion is that we don't need to support non-boolean states and the current API using `DOMTokenList` is enough.  If a component author want to expose a non-boolean state, it should be converted to multiple boolean states or a state change event can be provided for maximum flexibility.

---

That said, we recognize that in the overall mission of allowing "custom X" features to be as powerful as "built-in X" features, there is a missing gap for X = "custom pseudo-functions" like `:dir()`, `:lang()`, `:is()`, `:not()`, `:where()`, `:has()`, `:nth-child()`, `:nth-col()`, etc.

For the reasons explained in previous posts in this thread, we don't think these should be considered as an extension of the problem space being tackled here, i.e. in the same ways as custom states that reflect element-internal properties. As shown by the use case analysis on libraries (as well as analysis of the existing built-in HTML elements/CSS pseudo-functions), custom pseudo-functions don't provide an element-specific API. As such ElementInternals is not the right place for them.

We'd expect these to fit better with the Houdini efforts to make CSS more extensible and tied to JavaScript in general. For example:

* Developers creating a custom layout might want to create a selector like `:nth-col()` that works well with that custom layout, or
* Developers might want to adjust specificity in a useful way like `:where()` and `:is()` do, or
* Developers might want to use a JavaScript function to express boolean logic on a set of selectors like `:is()` and `:not()` do, or
* Developers might want to perform some general inspection of related DOM nodes and text content as `:dir()`, `:lang()`, and `:has()` do.

All of these are not specific to a given custom element's implementation, but are powerful and interesting pieces of functionality that would be good to allow developers access to, as part of the general explain-CSS effort.

We hope this helps!

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3ctag/design-reviews/issues/428#issuecomment-549532912

Received on Monday, 4 November 2019 20:29:50 UTC