Open frivoal opened 5 years ago
I think there's still a little missing from this. Imagine you had an outer component with 2 somewhat deep and complex inner components from different sources. This inner ones support themes but one uses foo-theme-
prefix and the other uses bar-theme-
prefix but the outer component would just like to present a single theme prefix.
We could support renaming themes in exportparts or we could support wild-card renaming in exportparts.
@fergald The main thinking behind this is to have a way to compose multiple "child" components from a variety of sources into a single custom component but avoid the need to have deeply nested exportparts=
chains.
This thought was to avoid having a massive wrecking ball that could reach anywhere and make it more of a small strategic hammer.
Wildcards would still require exportparts=
chains and in our ecosystem of teams creating new components from several nested others we want to make it as easy as we can to tweak the entire component as the author intends.
What are your thoughts on a potential solution for this? Would you please illustrate it with example markup?
I've noticed that the ::theme selector has been removed from the spec published in November[1] as well as the most recent working draft from April[2]:
1. https://www.w3.org/TR/css-shadow-parts-1/
2. https://drafts.csswg.org/css-shadow-parts/
Why was it removed and what was the context around the removal? Old versions of the spec seemed to include both ::part and ::theme.
Does ::theme still exist outside of this repo?
Edit- I see this is referenced in #3467! And the syntax there seems to be a better direction. I suppose my question is now, what is the status of ::theme?
The spec became a spec for part only to narrow the focus and get one thing agreed and implemented. Theme is not off the table, it should come back at some point, probably as a separate spec.
Speculation: Wouldn’t :theme
be better served as a pseudo selector inside the shadow DOM where consumers can select one or more themes setting one or more matching values on a new theme
property?
I often see authors put stylistic attributes on custom elements (such as color
or weight
) and then consuming authors have to make sure to set the right stylistic attributes at the right place in the markup. For example say that a custom button has an optional weight
attribute with slim
and strong
options. And my style-guide says all buttons inside tables should be slim
, then I just have to remember to set this attribute each time I put a button inside a table. It would be much easier if I could just set a theme
property—to something the author has carefully crafted and documented—in my stylesheet.
/* inside shadow DOM */
:host {
--background: var(--button-background, ivory);
--color: var(--button-color, rebeccapurple);
--color-disabled: var(--button-color-disabled, thistle);
}
:theme(danger) {
--background: var(--button-bakground-danger, mistyrose);
--color: var(--button-color-danger, firebrick);
}
button {
background: var(--background);
border: 2px solid currentcolor;
color: var(--color);
padding: 0.5ex 1em;
}
button:disabled {
--background: var(--background-disabled);
--color: var(--color-disabled);
}
:theme(slim) button {
background: transparent;
border: none;
padding: 0;
text-decoration: underline;
}
:theme(strong) button {
background: var(--color);
border-color: var(--color);
color: white;
}
Then a consumer can write:
table my-button {
theme: slim;
}
.danger-zone my-button {
theme: danger;
}
dialog my-button[type="submit"] {
theme: strong primary;
}
::part
?This gives the author of the custom element more power to carefully craft well designed elements using multiple properties on one or more child elements. With ::part
consuming authors would need to copy and paste some of these styles, and be careful not to mix colors from different color scemes, and then apply on different shadow parts. Consuming authors would have an easier time selecting one or more of the documented themes.
We could support renaming themes in exportparts or we could support wild-card renaming in exportparts.
+1 to the idea of allowing support for wildcards inside ::theme
@runarberg You raise an interesting suggestion. At Red Hat, we've approached this in our web component project using data attributes as a means of opting into "variants".
<pfe-accordion pfe-variant="earth">
Perhaps what you describe could be a new idea under a different name such as :variant
? I see your proposal as a little different than one of the original goals of ::theme
, which was to provide a means for cascading styles into shadow DOM (including nested shadow DOMs) without having to use custom properties.
Indeed what I’m suggesting is a little more powerful version of a mixin that is limited to the shadow root. But I feel like theme
is the right name for it. The current suggestion if ::theme
has a confusing name in my opinion. A theme is usually something curated by an author and then selected by a consumer. If I have to write my own styles inside a theme it doesn’t feel like a theme.
In my opinion what we now call ::theme
would be better named something like ::broadcast-parts
.
@runarberg I can see the perspective that the label theme might be a misnomer. I do like the idea of broadcast
and your suggestion of broadcast-parts
is more descriptive of what is happening (though I tend to prefer less verbosity when possible).
The approach @runarberg proposes is pretty much the same thing as we at Vaadin tried early on (https://github.com/vaadin/vaadin-themable-mixin/issues/12#issuecomment-327802249) as a way to control theme variant propagation and as a way for style sheet authors to have control over them instead of the HTML markup. I would very much like that to be the case, that it would be possible to choose predefined variants using a style sheet.
Unfortunately, our implementation ended up being terrible for performance and we moved back to the HTML attribute based solution.
This also reminds me of the idea @justinfagnani surfaced in another related discussion about theming shadow roots (https://github.com/w3c/webcomponents/issues/864#issuecomment-601924132). I see it as basically the same idea, but with a slightly different API.
The API proposed here feels like it would be easier to author. I don’t know if Justin had thoughts how the author defines the mapping between the “logical properties” and the final properties it is expanded into?
Comparing the two, from a consumer perspective:
mwc-card {
--material-elevation: 2;
}
mwc-card {
theme: material-elevation-2;
}
From the author perspective (shadow root of mwc-card):
:host {
/* Not sure how --material-elevation would be processed? */
}
:theme(material-elevation-2) {
box-shadow: var(--material-elevation-2-box-shadow);
}
(Split from issue #3467, reported by @stefsullrew)
The current description of the ::theme selector is perhaps a bit too broad for real world usage. However the ability to access any ::part within the context of a component, without elaborate
exportparts=
chains would be much easier to work with in the context of a design system.In the example below, a theme context is defined for
**x-foo**
with the prefix of “foo-
”. This would grant access to all child parts that match the name within the declared theme's context. This scoping limits the reach of ::theme while avoiding the potentially complex exportparts= chains. Particularly when there's deep composition of components not owned by a single team.