I'm trying to specify a theme as a property, and then override the static styles
property on the Lit element.
This would be handy because then I could share an interface with my users such that they would have a type-safe way of composing custom themes of my web components for their own apps.
However, when I change the static styles
property, Lit doesn't seem aware of the change, nothing actually happens. I've tried doing it in both the constructor
and connectedCallback
methods, but neither worked. In my real-world use case, it's slightly more complicated because I have a BaseComponent
being inherited with its styles by other components, but let's leave it aside for this question, I guess.
Is this really possible? Or should I stick to using styleMap
, classMap
and regular CSS custom properties.
On the Lit's Discord server, another user mentioned that I might need to use Constructable Stylesheets — and it's apparently what Lit uses under the hood — but I'm not sure where to even start with that.
You can take a look at this example on Lit's playground here.
I think part of the problem is that I just can't seem to change the stylesheet part of components (static styles
) during runtime, only at compile (transpile) time.
Lit Component:
import {html, css, unsafeCSS, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
type Color = string;
interface CustomTheme {
primary: Color;
}
const customTheme = {
primary: "orange"
}
function themeToLitCss(theme: CustomTheme) {
return css`
p {
color: ${unsafeCSS(theme.primary)}
}
`
}
@customElement('hello-world')
export class HelloWorld extends LitElement {
static styles = [];
@property({
attribute: 'custom-theme',
converter: (attrValue: string | undefined) =>
attrValue ? JSON.parse(attrValue) : undefined,
})
customTheme?: CustomTheme;
override connectedCallback() {
super.connectedCallback();
// Overriding the styles with an external theme specified by the user
if (this.customTheme) HelloWorld.styles = [this.customTheme];
}
render() {
return html`<p>Hello World</p>`;
}
}
The HTML would look like this:
<hello-world custom-theme='{"primary": "orange"}'></hello-world>
I've also created an issue on Lit's Github repo.