Skip to content

Instantly share code, notes, and snippets.

@alexlafroscia
Last active August 6, 2018 19:13
Show Gist options
  • Save alexlafroscia/f0b2493c1abebd28a22d7164832ddaa7 to your computer and use it in GitHub Desktop.
Save alexlafroscia/f0b2493c1abebd28a22d7164832ddaa7 to your computer and use it in GitHub Desktop.
Skate.js ShadyCSS Mixin

ShadyCSS Skate.js Mixin

Out of the box, Skate.js doesn't work that well with ShadyCSS. This is a mixin that helps bridge the gap.

Usage

The usage example below assumes you're using a build tool like Webpack to transform a CSS file into a string when loaded.

import Component from 'skatejs';
import StyledMixin from './styled-mixin.js';
import styles from './styles.css';

class MyComponent extends StyledMixn(Component) {
  static is = 'my-component'
  
  static styleSheet = styles
}
const { nativeShadow } = ShadyCSS;
const $template = Symbol();
/**
* Generate a scoped style element for the given element
*
* @see https://github.com/skatejs/skatejs/issues/1027#issuecomment-277382741
* @private
* @param {Component} elem the element to generate a style for
* @param {string} css the stylesheet to scope
* @return {HTMLElement} the style elememnt to add to the component
*/
function style(elem, css) {
if (nativeShadow) {
const styleElement = document.createElement('style');
const styleContent = document.createTextNode(css);
styleElement.appendChild(styleContent);
return styleElement;
} else {
const template = elem[$template] || (elem[$template] = document.createElement('template'));
template.innerHTML = `<style>${css}</style>`;
ShadyCSS.prepareTemplate(template, elem.localName);
return template;
}
}
/**
* Mixin to add automatic styling to a Skatejs component
*
* @param {skatejs~Component} superclass the superclass to add features to
* @returns {skatejs~Component} the new class, with added features
*/
export default function StyledMixin(superclass) {
return class extends superclass {
/**
* By setting the `styleSheet` attribute on a class, a new custom
* element can be created that will automatically have the styles
* injected into the component.
*
* In browsers that have native support for the ShadowDOM, the
* stylesheet will be added such that the styles are all scoped to
* that custom element.
*
* In browsers that do not have native support for the ShadowDOM,
* ShadyCSS will be used to scope the styles to the element. Note
* that ShadyCSS can only scope `:host` and class definitions, so
* styles should only be defined that use those techniques.
*
* @property {string} styleSheet the stylesheet for this element
* @abstract
*/
static styleSheet = ''
/**
* Adds a `<style>` tag to the custom element's shadow DOM
*
* @return
*/
renderedCallback() {
super.renderedCallback();
const styleElement = style(this, this.constructor.styleSheet);
this.shadowRoot.appendChild(styleElement);
}
};
}
@bsparks
Copy link

bsparks commented Aug 6, 2018

Thank you for this, can you please give it a license so I can check a box with my managers for commercial use? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment