WICG / custom-state-pseudo-class

Former home of the custom state pseudo-class feature
Other
11 stars 7 forks source link

Non-boolean states #4

Open tkent-google opened 4 years ago

tkent-google commented 4 years ago

See https://wicg.github.io/custom-state-pseudo-class/#ex-non-boolean-state

If the feature needs to support non-boolean states, probably

plinss commented 4 years ago

I did not. I characterized my understanding of what you wrote. If that understanding is incorrect, please rephrase.

It seemed pretty clear to me that Domenic's intention was: the purpose of custom elements is to do similar kinds of things to existing HTML elements, with the same genera kinds of interfaces exposed.

Perhaps you share more context with Domenic than I do. My interpretation of what he wrote was based on how I understood the words he wrote. Nothing more, nothing less.

Tab's explanation of what Domenic was likely going for makes sense to me, and I very much agree with those goals.

Let me be clear and blunt. I am not arguing for the sake of argument. I am not deliberately misrepresenting anything anyone says. I'm also not trying to "win". I may not take everything written in the exact sense in which it was meant, but all I can offer is my best effort trying to understand the sense that was conveyed. As does everyone else. Human communication is not perfect.

I am acting in good faith trying to improve the web platform. And I presume you all are too.

It's clear to me that several of you have differing viewpoints than I, and others, do. I am making best efforts to try to understand your viewpoints and take your concerns into consideration. Please do the same for me. Talking past each other is frustrating.

It's not to let them express things in whole new ways. For example, a feature to define an element where the open tag uses square brackets instead of angle brackets would probably not be a valuable addition to custom elements.

Giving an author access to a custom pseudo-element isn't a "whole new way" of expressing things. It's giving custom elements the exact same capability that HTML elements already have. That's a goal, right?

tabatkins commented 4 years ago

It's not to let them express things in whole new ways. For example, a feature to define an element where the open tag uses square brackets instead of angle brackets would probably not be a valuable addition to custom elements.

No need for hyperbolic examples here. Quoting myself from a few comments back:

Custom elements and the associated feature suite are meant to achieve overall interface feature parity with HTML - anything you can do to/with a built-in HTML element, you should be able to do to/with custom elements (such as invoke them with a meaningful tagname, produce them via the parser, interact with forms, appear in the a11y tree, etc).

The point of that feature parity is to allow people to use custom elements to achieve things that HTML will never do, and do so in a way that both feels natural, and interoperates with the rest of the ecosystem as smoothly as possible.

Swapping the bracket characters used by tags is not a useful characterization of what's being talked about here; that would be a completely novel functionality that doesn't exist anywhere in HTML, and without a strong justification, wouldn't be appropriate for custom elements.

What we're talking about here is whether or not custom pseudo-classes should be permanently restricted to a subset of pseudo-class syntax, or should (eventually) be allowed to use the full syntax that existing pseudo-classes use.


So far, I haven't seen good arguments for ruling out the possibility of custom functional pseudo-classes. The attempted arguments have been that (a) CSS only uses functional pseudo-classes to express "tree information" or combinator-ish things, not internal states of an element, and (b) there are no reasonable examples of internal states that would be better exposed as functional pseudo-classes rather than a set of boolean pseudo-classes.

Neither of these are correct. In the current Selectors spec, most of the functional pseudo-classes are combinator-ish (:is(), :not(), the various :nth-foo() pseudo-classes), but :dir() and :lang() aren't. They're exposing the actual state of the element - its direction and language. This can be influenced by attributes higher in the tree, but it's not an aspect of the tree's structure or just a higher-order modifier over an existing selector. More importantly, as I said in an earlier comment:

The fact that lang information is from the document tree isn't relevant here, it's the fact that doing :lang() with booleans would involve hundreds of distinct states, and require authors to write :is() selectors over many of them at once for some common tasks.

Even if you want to push the point that an element's language comes from the tree rather than being an internal state, you cannot argue that the design of :lang() flows from that. Its design is a result of the matching space being large and complex, such that exposing it with a set of booleans would be very complex both for the spec/browser (literally hundreds of boolean pseudo-classes!) and for the page author (Want to match any sort of English? Congrats, you have to write out an :is() with dozens of options to capture them all! And the set you need will expand over time, so I hope you're still doing page maintenance in a few years! Also maybe the set is actually infinite, due to -x-foo suffixes!)

So, concretely: @othermaciej, are you trying to argue that it is unrealistic that a custom element will ever want to do something remotely similar, where it wants to let authors match over a large (or infinite) set of states, so we shouldn't try to design an API that eventually accommodates it? I'm trying to get this argument to focus on the concrete questions rather than continuing to circle around abstract disagreements.

Note that I'm skipping over the multiple examples of functional pseudoclasses that have been proposed that are definitely based on internal state, which I linked to and talked about in previous comments; this response is too long already.


It might be that, in some cases, we need to go beyond the way existing HTML elements have done things to enable specific other kinds of elements. But that has to be actually demonstrated, not just assumed. And it ought to be a real need, not just a gratuitous difference from how existing elements do things.

I strongly agree, but that's completely tangential to the question at hand, which is whether custom pseudo-classes will ever want to do use the full set of syntax that existing pseudo-classes do. Nothing being discussed here has suggested going beyond current CSS syntax in any way.

othermaciej commented 4 years ago

This spec is not "custom pseudo-classes", it's "custom state pseudo-class" in particular. So we don't necessarily need to expose every possible face of CSS pseudo-element syntax. Just enough to express states.

Current HTML elements often express state as a styling hook. This is generally specific to one element or a subset of elements. Mostly they are documented here and they represent a specific state of the element. https://html.spec.whatwg.org/#pseudo-classes

It's really easy to think of examples of states that aren't one of the built-in ones which might apply to novel custom elements. For example, a toggle-button custom element would surely want to express :state(toggled) (or :--togged). A custom-notification custom element would want to express :state(shown) (or :--shown).

All I'm asking for is a plausible example of element-specific state like the above which would clearly benefit from the functional syntax, to the point that a fixed set of values wouldn't do the job.

In particular, I don't think :dir or :lang are suitable examples. They are not element-specific, or about element-internal state. They are generic and about the shape of the DOM tree. If we felt it was necessary to add an extension point to add things like this, then it should be a separate CSS extension point to add a custom pseudo-class that applies to all elements, not part of an API tied to Custom Elements.

Also, an argument along the lines of "who knows what custom elements could do, they could do anything" is not, itself, a suitable example.

Also, the only examples I see in previous comments are how existing state-like pseudo-classes could be reworked to use functional syntax, but they do not explain why it would be necessary or helpful to do so. (It seems seems self-evidently not necessary).

If no one can present such an example, then I think we can presume there's no obvious use case. So far, the only real argument presented is syntax completionism, and I don't think that's a good enough reason to add complexity to this particular API.

tkent-google commented 4 years ago

Because I don't think non-boolean state support is mandatory, the first version of the feature and its implementations won't have non-boolean state support, and it's possible that we never add non-boolean state support. Web developers will use the first version for a while, and they would be confused if the feature had weird syntax and API.

I'd propose the first version as:

A future version might have non-boolean states. Non-boolean states will be supported by a different selector syntax and a different IDL attribute.

Any objections?

annevk commented 4 years ago

I wonder how well worked out setlike/maplike are. In existing collection classes, e.g., Headers or DOMTokenList, all the methods perform argument validation, for instance.

plinss commented 4 years ago

I don't object to the first part of your proposal (for the first version).

While I still feel that non-boolean states are useful, as I've said multiple times, I'm OK with version 1 being boolean only, so long as there's a reasonable path to go beyond that.

I can live with a setlike API, however I still prefer a maplike, even for V1. A maplike can still have an additional void add(DOMString key); method that is equivalent to set(key, undefined). The :--foo selector can then match whenever the key '--foo' is present, regardless of value. This would give an equivalent API and behavior to your proposal (with the exception of iteration) and provides for extensibility without adding a clunky API later. Users can use .keys() to replicate the setlike iteration behavior.

If we start with a setlike, we can still add void set(DOMString key, DOMString value); to it, but then iteration becomes weird. (Frankly I think maplike iteration should have just iterated over the keys, like Python does, which would have made this all much simpler.)

I do object to your plans for a future version for several reasons. 1) While it's important to think about possible future API surface to design an extensible API now, it's premature to actually specify that future API. If we're going to specify the non-boolean now, let's just specify it and implement that. 2) This is the wrong venue to specify selector behavior, that should be done by the CSSWG. 3) I really don't like the idea of a separate state set and state map. Especially without clearly defining how they interact when the same key is set in both. If we do support non-boolean states in the future, there should be a single states object.

tkent-google commented 4 years ago

I wonder how well worked out setlike/maplike are. In existing collection classes, e.g., Headers or DOMTokenList, all the methods perform argument validation, for instance.

According to the current definition of setlike, we can override add() delete() and clear(), but can't override has(). I think overriding add() is enough in practice.

tkent-google commented 4 years ago

While I still feel that non-boolean states are useful, as I've said multiple times, I'm OK with version 1 being boolean only, so long as there's a reasonable path to go beyond that.

I still think non-boolean states is unnecessary. Probably we won't implement it in Google Chrome unless other browser vendors strongly support it.