Re: [webcomponents]: The Shadow Cat in the Hat Edition

On Mon, Sep 9, 2013 at 4:32 PM, Dimitri Glazkov <dglazkov@google.com> wrote:
> For what it's worth, it would be fairly easy to make shadow tree rules
> match shadow host only when ":host" is present in a rule.
>
> Unfortunately, this would leave Tab (and other CSS WG folks) in a sad
> state, since addressing these arguments makes it harder to keep a
> straight face with the concept of a pseudo class in regard to :host.
> See discussion on bug for the gory details.
>
> As of now, we are in that angsty state of not knowing what to do next.
> Any ideas are appreciated. Note that there are some well-established
> concepts in CSS and inventing fewer new concepts is much preferred.
> Reuse, reduce, recycle.

Yeah, having the mere *presence* of a pseudo-class in a selector
change the set of elements the selector is matched against is a bad,
bad idea.  It breaks an invariant in a confusing way, and prevents
easy refactoring of selectors.

The best way to do this is to introduce an at-rule that adds the host
element to the set of elements matched by the rules within it, perhaps
called @host.  This was extraordinarily clumsy the first time we tried
to do it, but that was due to a host of other syntax issues that have
since been resolved.  Now, just using @host to change the context, and
:host/:host() to select things, should work okay.

If we do this, should :host() still work in non-@host contexts?  It
would match *any* element in the tree, if something in the ancestor
list, starting with the host element, matched the selector.  Perhaps
it requires a different name now, to distinguish it from :host?

> Part 2: Party ::part part
>
> Another possible wrinkle is the ::part pseudo element. After also
> chewing on ::part for a little while, our brave guinea pi.. erm,
> people also declared it to be tasting somewhat bitter.
>
> The best symptom can be seen here:
> https://www.w3.org/Bugs/Public/show_bug.cgi?id=23162. When explained
> that you would just chain x-nurk::part(woot)::part(zorp)::part(bler)
> to cross each shadow tree boundary, the guinea people looked at me
> like this: <_<. Then they pointed out that this both:
>
> a) implies ever-growing "part" API for each component, which will
> quickly lead to the anti-pattern of developers simply declaring all
> elements in their shadow tree as parts, and
>
> b) just looks ugly and constipated.
>
> Agitated shouts of "Y U NO LET US JUS DO EET" were echoing across the
> San Francisco Bay, frightening America's Cup spectators.
>
> To calm the brave guinea people down, I showed them a magic trick. Out
> of my sleeve, I pulled out two new combinators: A hat (^) and a cat
> (^^).
>
> You would use them instead of ::part. The hat is generally equivalent
> to a descendant combinator, except it crosses 1 (one) shadow tree
> boundary (from shadow host to shadow root). The cat is similar, except
> it crosses any number of boundaries. So, to target "bler" in the
> previous part-y chain could be written as simply as
> x-nurk^^[part=bler] or x-nurk^^#bler if ids are used instead of
> part="bler" attribute. Respectively, you would target "woot" as simply
> x-nurk^#woot.

We talked about auto-surfacing the parts from contained components
previously.  We decided not to do it, but we can address this at the
demand side by just introducing a second pseudo-element alongside
::part which selects amongst all the parts, including those of
contained components.  No need to introduce new combinator syntax -
pseudo-elements are already combinators of a sort.

> But wait there's more: you could use these new combinators in
> querySelector, I proclaimed! In the nascent shadow DOM code, we
> already started seeing the blood-curling
> document.querySelector('x-nurk').shadowRoot.querySelector('#woot').shadowRoot.querySelector('#zorp')
> chains of hell -- a problem that these new combinators would solve.
>
> Think of them simply general combinators that opens shadow trees for
> selector traversal, just like Element.shadowRoot did for DOM
> traversal.

You should be able to just do this with ::part as well.  Note, though,
that this mixes up the questions of exposing a part for styling, and
exposing it for script-based manipulation.  I was under the impression
that HTML elements that exposed a native shadow DOM would expose their
parts for styling, but were still black boxes for interaction
purposes.  Has that changed?

On Mon, Sep 9, 2013 at 5:29 PM, Scott Miles <sjmiles@google.com> wrote:
>>> finally ruined encapsulation?
>
> As I see it the main Web Components system is based on soft encapsulation.
> Each boundary is in force by default, but each one is also easily pierced
> when needed.
>
> E.g., shadow-roots are traversable, JS prototypes are mungeable (in
> general). Ability to pierce CSS encapsulation (on purpose, doesn't happen
> incidentally) allows us to do theming and other necessary customization
> tasks without having to over-engineer.

I am okay with piercable boundaries, but I'm still concerned about the
pain that'll come from having *all* of your DOM exposed to all
clients, meaning it becomes difficult/impossible to upgrade a
component used by many people, since you have no clue what parts of
your existing markup structure are being depended on by others.

I'd greatly prefer to stick with the current plan of having to mark
things to be exposed explicitly, but would be okay with a switch to
toggle this to fully-open, like you can do with selectors today.  We
could even build this into the existing switch that lets selectors
match across the boundary, adding a partially-open value that keeps
selectors from matching across naively, but allows matching when you
explicitly pierce the boundary with ::part.

~TJ

Received on Tuesday, 10 September 2013 00:53:10 UTC