-
-
Notifications
You must be signed in to change notification settings - Fork 852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default theme should apply to :host as well as :root selector #437
Comments
Interesting. Are there any known repercussions with scoping design tokens to The original idea was to set them globally on the root so the user can override them anywhere in the cascade. My knee-jerk reaction to this is that scoping to |
MWC for example loads its default styles directly into the component definition. So it has a reasonable default style out-of-the-box, but users can always override any custom properties it uses from the outside. https://unpkg.com/browse/@material/mwc-button@0.20.0/mwc-button.js |
So to recap, adding the I've added the global stylesheet to --sl-color-primary-500: var(--sl-color-primary-500, tomato); The idea is to use the root design token if one is specified and fallback to My concern is that having both scopes means there's no way to fallback to a token higher up in the cascade. 😕 It seems like we need a set of custom properties that can be imported and scoped to either const tokens = { ... };
export function getBaseTokens(selector = ':root') {
return css`
${selector} {
${stringify(tokens)}
}
`;
} Then to use it in a third-party component: import { getBaseTokens } from '@shoelace-style/dist/utilities/tokens';
@customElement('my-component')
class MyComponent extends LitElement {
static styles = [getBaseTokens(':host'), ...];
} As an aside, I'd like to document the design tokens better so I can add them to I think this would also solve #438, but I'd like to hear your thoughts on this approach. |
🤦 Sorry, I just realized one of my earlier comments was wrong -- I was incorrectly remembering that you'd always be able to override a property assignment from an outer scope, but this isn't true. So yeah, you're right, you can't simply load the default property values and apply it with Maybe this is overly simplistic, but if you baked the default theme values directly into the Here's an example which also shows distributing a dark theme module, which can be applied with an import. |
I've played with the fallback method before and it gets a bit unwieldy to maintain styles that way. I've always assumed the base stylesheet to be a root-level dependency, otherwise there's no clear way to share design tokens amongst different components and across shadow roots. There are also a couple utility styles such as However, I do appreciate the use case you're presenting. I'd like to expose design tokens in an importable way, but I'm not sure how to do that without making them JavaScript-first, e.g.: export default {
'--sl-color-black': '#000',
'--sl-color-white': '#fff',
...
}; This may be helpful to component devs, but not so much for consumers who want to be able to use the cascade to override a handful of design tokens in CSS. (The JS-based tokens would be out of sync as soon as any override occurs.) Going back to your suggestion of using export default function getTokens(selector = ':root') {
return css`
${selector} {
--sl-color-black: #000;
--sl-color-white: #fff;
...
}
`;
} This would allow you to grab the full set of design tokens with a custom selector (e.g. I'm still not sure what the correct path forward is for this. Feedback is always welcome! |
Do you mean it's unwieldy to manage the defaults given that you need to consistently replicate the same fallback value across multiple I wonder if there's a downside to this approach other than the extra byte cost?
Maybe these could be factored out into modules that export a Isn't this pattern of using attribute/class selectors already a bit of an issue -- because even if you include them at the root, they won't apply through shadow roots, so you can't really do composition anyway? |
Exactly. On top of the verbosity, I'm reluctant to use Sass variables because I don't currently use them anywhere in the source and I was hoping to move to PostCSS soon. (Currently, Sass is only used for nesting and importing.)
The The other is a Edit: the base theme also includes |
The |
Ah I see. Have you considered an extra set of variables to represent the defaults? E.g. color: var(--my-property, var(--my-property-default)); The default theme stylesheet could then set the Or another option, if you're switching to PostCSS, might be to do the same as above, but then transform the |
Good suggestion. I'm not too worried about the size of the fallbacks, but more the inconvenience of having to write them out everywhere and the opportunity for human error that will likely result. It may be a necessary evil, though. 😈 I'm still not sure exactly how to solve the theming problem. Initially, I was hoping to rely on "normal CSS" for customization since this is especially popular with many users. On the other hand, this requires that the ancestral root (e.g. document or shadow) include the design tokens. This is sort of converging with #438, particularly this comment. Do you have any thoughts on that? I appreciate your insight. Theming is the next major thing I want to tackle, and I want to get it right for both consumers and components devs — just not sure how to do it with minimal friction for both. |
Heya, I ran into this not applying to host too. I was trying to do the following pattern: // using rollup-plugin-postcss-lit to import the styles when I need them
// and to help fragment
import shoelaceStyles from '@shoelace-style/shoelace/dist/themes/base.css';
import styles from './my-view-3.scss';
@customElement('my-view-3')
class MyView3 extends LitElement {
static styles = [shoelaceStyles, styles];
...
} Thing is to do this, I turn off postcss injection Personally I'd prefer not to have to have a so not to have to deal with copying files over and keeping everything within rollup. Luckily the base styles file is so small, I was able to just ctrl+c ctrl+v |
Yep...I'm still working through a backlog of smaller things before tackling theming. Probably going to ditch Sass and start exporting CSS and design tokens as mentioned in #438, that way they can be injected into arbitrary shadow roots. We also need a way to facilitate customizations, so any thoughts or opinions on that before I start experimenting are appreciated! |
Closing this so we can focus on it more actively in #438. Comment to follow. |
The changes requested here were applied in beta.48 which was released today. |
Describe the bug
The default theme stylesheet only applies to the
:root
HTML element, not the:host
for the case where Shoelace is to be encapsulated within another element that uses a shadow root.To Reproduce
Steps to reproduce the behavior:
<link>
in the element's shadow rootHere's a link to a repro: https://tinyurl.com/wwcm6wfp
Expected behavior
I should be able to use a Shoelace component within my own distributed component, without requiring the end-user to load the Shoelace stylesheet in the top level of their app.
Suggestion
If the default stylesheet rule used the selector
:root, :host
instead of simply:root
, then this is possible.The text was updated successfully, but these errors were encountered: