1
votes

I'm trying out StencilJS for creating reusable web components for multiple projects that I'm working on. But I'm having a hard time to inherit the color themes from my main applications to, let's say, my Stencil button component. Example: I want to use different primary and secondary coloring for my applications that applies on my Stencil components like a primary colored button. But how do I manage to do so? I'm using sass styling and have the primary variable locally set in my Stencil project with my theme. But I don't know how to import external sass/css files after compilation.

<my-button color="primary">This is a primary button</my-button>
2

2 Answers

6
votes

One option is to turn off the Shadow DOM when you are defining the component. This will allow your web component to inherit the CSS from the app the component is being used in.

@Component({
  tag: 'shadow-component',
  styleUrl: 'shadow-component.css',
  shadow: false
})
4
votes

At the bottom of the Styling docs there is a section about how to use CSS variables:

In this example we have defined a CSS Variable called --app-primary-color that is set to the color #488aff. The :root selector in this example is a CSS pseudo selector that defines the variable on the root element of your project (usually <html>) so that the variable can be used across your app.

So if you have a button component like this:

@Component({ tag: 'my-button', styleUrl: 'button.css' })
export class Button {
  render() {
    return <div class="button"><slot /></div>;
  }
}

And the following button.css for it:

.button {
  background: var(--primary-color, tomato);
  color: var(--light-color, white);

  display: block;
  padding: 1em 2em;
  border-radius: 0.2em;
  font-family: sans-serif;
  text-align: center;
  text-transform: uppercase;
}

Then you can overwrite all button colors by setting the variable somewhere in your CSS:

:root {
  --primary-color: mediumseagreen;
}

CSS Variables can also be set using Javascript, and they are even polyfilled by Stencil for older browsers.

JSFiddle example: http://jsfiddle.net/5fv9r6e1/


Btw, in your component decorator you can also set shadow: true to enable Shadow DOM, and then you can use the :host selector and don't need the wrapping div in this example:

@Component({ tag: 'my-button', styleUrl: 'button.css', shadow: true })
export class Button {
  render() {
    return <slot />;
  }
}

css:

:host {
  background: var(--primary-color, tomato);
  color: var(--light-color, white);

  display: block;
  padding: 1em 2em;
  border-radius: 0.2em;
  font-family: sans-serif;
  text-align: center;
  text-transform: uppercase;
}

Ionic 4 uses this concept a lot, so it might be worth having a look at their Stencil components: https://github.com/ionic-team/ionic/tree/master/core/src/components