[csswg-drafts] [css-shadow-parts] Unifying ::part() and ::--foo (#4900)

tabatkins has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-shadow-parts] Unifying ::part() and ::--foo ==
tldr: We should allow part names to also be selected as full custom pseudo-elements names, a la `my-component::--heading` in addition to `my-component::part(heading)`.

-----

In the Web Components virtual f2f today, we discussed custom pseudo-classes. In the thread about `:state(foo)` vs `:--foo` syntax, [Maciej brought up the reasonable point](https://github.com/WICG/custom-state-pseudo-class/issues/6#issuecomment-595584830) that switching away from `:state()` to `:--foo`, but leaving parts as `::part()`, is inconsistent.

I explained the reason behind maintaining `::part()`: due to CSS's bad syntax choices in the past, pseudo-element syntax implicitly contains a combinator, moving the subject of the selector into the element's "pseudo children"; as a result, you can't stack pseudo-elements to apply multiple conditions to a single pseudo-element. However, we want to allow that for parts - we want a calendar widget to be able to expose day elements for styling with something like `part="day weekend saturday week-1 us-holiday"`, and let stylesheets select on a combination of those qualities, like `::part(day weekend us-holiday)`

However, Maciej's point is still valid! Also, people have *wanted* ::--foo syntax, to mirror normal pseudo-elements, and things like UA pseudo-elements (`::-webkit-scrollbar-thumb`, for example).

Jan's idea was to unify these - allow parts to be selected *either* with `::part(foo)` *or* with `::--foo`; if you only need to select on one property, you can use the more direct form, but `::part()` remains if you have more complex selecting needs. This received general approval in the call, and I think it's a good idea personally. General thoughts?

-----

I think there's one important detail to decide, which is how to handle existing part='' content.  In general, CSSWG has made the decision that dashed-idents should be used consistently thruout APIs: you reference the `--foo` custom property with `var(--foo)`, not `var(foo)`, etc. In other words, the `--` is part of the name, not a context-specific indicator of custom-ness.

Currently, tho, `part=''` allows any ident, not just dashed-idents. How should we deal with this? I see a few options:

1. (I don't like this, it's bad, but for completeness:) `part` is unchanged. If you define `part="foo"`, you can reference it as `::part(foo)` or `::--foo`. In other words, the -- is a context-specific indicator of custom-ness, but is not used when defining it, or referencing in `::part()`.  (Note: if you said `part="--foo", it would be referenceable as `::part(--foo)` or `::----foo`.)

 This is backwards-compatible with existing code, but breaks consistency with how dashed-ident features are used everywhere else in CSS, both currently and planned.  The component author doesn't make a choice on how to expose things, but the component user is presented with two fairly different names to refer to.

2. `part` is unchanged. If you define a part as a dashed-ident, it can be referred to as a top-level pseudo-element. That is, given `part="foo --bar"`, you can use `::part(foo)`, `::part(--bar)`, or `::--bar` validly. `::--foo` will *not* match, nor will `::foo`.

 This is backwards-compatible with existing code, and consistent with CSS design principles for dashed-idents. However, it imposes a choice on component authors of whether they want to expose parts as top-level pseudos or only within `::part()`. (There *might* be a good reason to make this distinction? Unsure, but I suspect not.)

3. We restrict `part` to only allow dashed-idents. `part="foo --bar"` only defines one part name, `--bar`, which can be referenced as either `::part(--bar)` or `::--bar`. (The "foo" is ignored, as part of our forward-compatible error handling that silently drops things that aren't understood.)

 This is *not* backwards-compatible; virtually all existing content would become invalid and stop defining parts. However, it means there's no choice on the component author's side, and the component user has a closer relationship in the two syntaxes.


I slightly lean toward 3, but I'm unsure how much back-compat pain we want to take on.  I'm fine with 2 if it's preferred by others. I'll fight against 1, it's terrible.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/4900 using your GitHub account

Received on Tuesday, 24 March 2020 18:31:21 UTC