I'm building a web component with stenciljs and i want to be able to load the css theme file based on the proprety called theme.
@Component({
tag: 'pm-header',
styleUrl: 'pm-header.scss',
shadow: true
})
export class PmHeader {
@Prop() theme: string = 'default';
...
render() {
return (<nav class={this.theme}></nav>)
}
}
I know this is late, but this should hopefully help others as it is not documented and I just spent a lot of time figuring it out. The following code allows your custom components to use a "mode" attribute to determine which style is loaded.
Step 1: Define multiple styleUrls (aka. "modes") in your component definition. I am using "dark" and "default" - but you can define as many as you want. For example, ionic uses "ios" and "md".
@Component({
tag: 'my-component',
styleUrls: {
default: 'my-component.default.pcss',
dark: 'my-component.dark.pcss',
},
})
export class MyComponent { ... }
Step 2: Create the style files (usually with shared common styles):
my-component.common.css
:host { display: block }
my-component.default.css
@import './my-component.common.css';
:host { color: black }
my-component.dark.css
@import './my-component.common.css';
:host { background: black; color: white }
Step 3: Update your stencil.config.ts to use a globalScript:
export const config: Config = {
namespace: 'mycomponent',
globalScript: './src/globals/global.ts',
...
}
Step 4: Create the global script and define a "setMode" function like this:
import { setMode } from '@stencil/core';
setMode(elm => {
// NOTE: you can write whatever you want here - it's up to you. This
// function must return one of the style "modes" defined in step 1.
return (elm as any).mode || elm.getAttribute('mode') || 'default';
});
Step 5: Use your custom component like this:
<!-- default mode -->
<my-component />
<my-component mode="default" />
<!-- dark mode -->
<my-component mode="dark" />
You can customize the setMode
function for determining the mode - for example you could look for a property on the window
, or check for a className on the element. It's up to you. The above is just a simple example which allows you to use a "mode" attribute on the element... falling back to "default" if nothing is specified.
Please have a look at the below example. It will work even when shadow is set to true
@Component({
tag: 'my-component',
styleUrls: [
'my-component.scss'
],
shadow: true
})
export class MyComponent{
@State() theme: string // when theme changes render needs to be called again
render () {
return (
<div>
{
this.theme &&
<link rel="stylesheet" href={`path_to_css/${this.theme}.css`} />
}
<p>{this.text}</p>
</div>
)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With