Open josepharhar opened 2 months ago
Allowing :popover-open to be matched reveals internal implementation details of
<select>
.
In general the less API surface there is, the less problems are likely going to come up in the future. Web APIs should be designed to last. We could decide that popover is no longer the right paradigm for pickers in the future. Should we be stuck with supporting :popover-open
then?
There shouldn't be more than one way to detect this state in CSS, so we should use select:open instead of ::picker(select):popover-open.
Quoting @fantasai: We want form controls to act like they’re built into the language, not built out of author facilities in the language; and that their full functionality can be implemented without those author facilities.
:open
/ :closed
covers the different use cases fine.
Should developers care that this is a popover honestly? I think what really matters for the purposes of styling and animation is that it's an element in the top layer. It doesn't really matter if it's a popover or a dialog.
As a developer, for me I don't care if it's a popover.
It would be much simpler and less expensive to learn to standardize on one :open
for all scenarios.
Also, even if both selectors are supported, the CSS compressor will be compressed to the shorter :open
in the future, and from that perspective, :popover-open
will be used by fewer people in the future.
I think requiring :popover-open
to match would very much go against our earlier decision not to reuse ::part()
. Whether or not ::picker(select)
points to an HTML element with a popover
attribute set is an implementation detail. If implementations want to implement ::picker(select)
without an element node they should be allowed to do that. ::picker(select)
needs to behave like popovers in a number of respects, but it shouldn't be required to use the exact same mechanism underneath.
Now I suppose we could update the :popover-open
requirements to say that ::picker(select)
also needs to be matched, but that seems kinda pointless to me given that we already plan to add :open
to select
elements.
The draft HTML spec that I've written explicitly says that ::picker(select) maps to an element which has the popover attribute, and we resolved on making it a part-like pseudo element. I still don't see how adding a special case to not parse :popover-open is helpful, but since its functionally the same as :open for popover animations and therefore doesn't limit what authors can do, and there seems to be significant pushback, I'll let it go and add a console message in this case to help point developers to the accepted syntax.
Proposed resolution: add a special case to not parse :popover-open for the ::picker(select) pseudo-element.
While we resolved against using ::part()
itself, we did resolve to make it a "part-like pseudo-element", and that means it acts like ::part() but is just spelled differently. Notably, ::part() does expose implementation details like what pseudo-classes and pseudo-elements are usable on the element, and this is intentional. (As opposed to the other pseudo-elements, which only allow a limited subset of pseudo classes/elements after them.)
I don't think we should try to diverge ::picker()
from the agreed-upon concept of part-like pseudos.
I don't think we should be locking ourselves in unnecessarily by exposing things that are not useful and may potentially cause a compat hazard later if something needs to change. While popover may seem like an appropriate concept to re-use now, it might not be the case later.
Fwiw, I'm also OK with making :popover-open
not match instead of not parse (there's a subtle difference there), if that preserves the technical purity a bit more.
I agree that we should stick to the concept of part-like pseudo-elements.
If we add an exception here, how many other exceptions will we add? How much working group time and implementor time will be spent implementing those exceptions, that could have been used for something else? And how much author confusion will result?
I really do think that what we're trying to do here is to provide an author-facing model for complex built-in widgets that exposes to developers that these widgets are composed of more basic pieces of web technology. This has been the plan for a long time (>20 years) because it seemed like the only practical way to standardize the stylability of complex widgets, and I still think this is the case. I thought that the conclusion in https://github.com/w3c/csswg-drafts/issues/9951#issuecomment-1997897418 agreed with this concept but concluded that we would not use the name ::part()
because it was for author-built components and for standardized components that were built in to the Web platform.
I don't think I argued against making it a part-like pseudo-element? Not sure why that is being revisited.
I argued against exposing the fact that ::picker()
matches a particular type of element. I think the tradeoff is between forever enshrining that this needs to act as if there was an HTML element with a popover
attribute set underneath versus keeping it more general and only requiring more "obvious" pseudo classes to match, such as :hover
. Who knows, we might introduce a better suited element such as <popup>
at one point which would not match :popover-open
. In order to reuse it here we'd have to add special cases at that point.
The other argument against it matching is that it introduces redundant API surface. This is slightly weaker, but whenever we don't have to, I'd definitely prefer not introducing redundant ways to do the same thing, especially if the redundant way is significantly more verbose and addresses fewer scenarios.
The markup structure of a base ::picker() is going to be precisely standardized, I thought. That's required, in practice, for it to be predictably styleable, which is the point of the base
feature in the first place. Any changes we make to the markup structure are going to be constrained by compat, or gated behind a new appearance
keyword if they're too radical.
Looking back at the spec for part-like pseudos, I see that it doesn't actually carry over the bit of [::part()'s definition](https://drafts.csswg.org/css-shadow-parts/#part:~:text=The%20%3A%3Apart()%20pseudo%2Delement%20can%20take%20additional%20pseudo%2Dclasses%20after%20it) that allows arbitrary pseudo-classes to be used on it, but that was the intention. I'll look into getting that fixed.
The markup structure of a base ::picker() is going to be precisely standardized, I thought. That's required, in practice, for it to be predictably styleable, which is the point of the
base
feature in the first place. Any changes we make to the markup structure are going to be constrained by compat, or gated behind a newappearance
keyword if they're too radical.
This was my thought as well. It feels very confusing to developers to see that the <select>
is using a popover (per spec), but have :popover-open
not match (or worse, not parse!) on that popover.
I see it a bit differently. Internal shadow trees allow us to more precisely define the observable behavior of certain built-in elements and give us a handful of shortcuts in defining such behavior, but:
The CSS Working Group just discussed [css-ui] Should `::picker(select)` match `:popover-open`?
, and agreed to the following:
RESOLVED: don't create a special exception to not parse :popover-open on ::picker(select)
Maybe it should be contingent on the value of appearance
, so that in the future, when an alternative, possibly better rendering of select
is implemented without this part, authors can choose. This opens, it seems to me, a path to the desired by many commenters forward compatibility. (But carves in stone the currently planned variant with the part, so that, even if one day considered legacy, implementations will have to continue supporting it.)
In general, each model of some control type with some innards exposed would need its own value of appearance
. And if a need arises, multiple can exist for the same control type.
And two values of apperarance
would always be available. Namely, none
, which gives an element no special rendering or parts, and default (auto
or base
?) with no exposed parts but with possibly some special implementation-dependent rendering (satisfying some quite general constraints) and a limited set of applicable CSS properties.
We resolved to make
::picker(select)
be a part-like pseudo-element here: https://github.com/w3c/csswg-drafts/issues/10758However, there were questions about whether we should make it match
:popover-open
.I believe that since
::picker(select)
is a part-like pseudo-element, it should match:popover-open
.Here are some reasons I understood were brought up that it shouldn't match
:popover-open
with my counterarguments:select:open
instead of::picker(select):popover-open
.:popover-open
to be matched reveals internal implementation details of<select>
.::picker(select)
is a popover, so any spec-abiding implementation must make this work. I'm sure that other uses of part-like pseudo-elements must reveal other sorts of internal implementation details about the element they match like this, so why should this one be disallowed? I'd like to try giving an example of this but I'm not up to speed on the other proposed or completed usages of part-like pseudo-elements.