Using @apply syntax in LitElement... for now
Published: 2019-11-07 15:53:00

If you want to watch how I did this and see examples as I talk through them here's a video (otherwise keep reading for code examples / history): [Using @apply shim inside of LitElement styles](https://youtu.be/tJ5vDFmO-b4)
While not the end all solution, we've been bitten by adopting `Polymer()` back in *V0* in a concept we got addicted to and (until now) had no way off of.

It's the proposed (and failed) *@apply* css standard. [You can read about the CSS spec that failed](http://tabatkins.github.io/specs/css-apply-rule/) for details if you care.

## Here's a simple example of how it worked
```js
class SomethingTag extends PolymerElement {
  static get template() {
    return html`
    <style>
    :host {
      font-size: var(--something-font-size, 20px);
    }
    .someDivYouCantStyleInShadows {
      @apply --something-tag-developer-things-we-didnt-think-about;
    }
    </style>`;
  }
}
```
Then in another element you could do this to style that shadow area:
```css

something-tag {
  --something-font-size: 10px;
  --something-tag-developer-things-we-didnt-think-about: {
    background-color: orange;
  };
}

```

It has [a shim in their polyfills](https://github.com/webcomponents/polyfills/tree/master/packages/shadycss#about-applyshim) but for the life of me I couldn't get it to work in LitElement. In comes another custom element from PolymerElement to shim the day (for now).

Here's the full code sample to see the context of how to use the `custom-style` tag from PolymerElement in order to get us through:
```js
import { LitElement, html, css } from "lit-element/lit-element.js";
import "@lrnwebcomponents/simple-colors/lib/simple-colors-polymer.js";
import "@polymer/paper-button/paper-button.js";
import "@polymer/paper-tooltip/paper-tooltip.js";
/**
 * @deprecatedApply - required for @apply / invoking @apply css var convention
 */
import "@polymer/polymer/lib/elements/custom-style.js";
class HaxToolbarItem extends LitElement {
  static get styles() {
    return [
      css`
        :host {
          display: flex;
          box-sizing: border-box;
          height: 36px;
          width: 36px;
        }
        :host([mini]) {
          height: unset;
          width: unset;
        }
        :host([menu]) {
          width: 100%;
          position: relative;
          display: -ms-flexbox;
          display: -webkit-flex;
          display: flex;
          -ms-flex-direction: row;
          -webkit-flex-direction: row;
          flex-direction: row;
          -webkit-justify-content: flex-start;
          justify-content: flex-start;
          -webkit-font-smoothing: antialiased;
          font-size: 16px;
          font-weight: 400;
          line-height: 24px;
        }
        :host([menu]) paper-button {
          -webkit-justify-content: flex-start;
          justify-content: flex-start;
        }
        #label {
          padding-left: 5px;
        }
        paper-button {
          display: flex;
          align-items: center;
          background-color: var(--hax-toolbar-item-bg, --hax-color-bg-accent);
          color: var(--hax-toolbar-item-color, --hax-color-text);
          min-width: 0;
          margin: 0;
          text-transform: none;
          padding: 0;
          border-radius: 0;
          font-size: 12px;
          transition: 0.3s all;
          height: 36px;
          width: 36px;
          min-width: unset;
          --paper-button-ink-color: var(
            --hax-toolbar-item-color,
            --hax-color-accent1
          );
        }
        paper-button:active,
        paper-button:hover,
        paper-button:focus {
          color: var(--hax-color-text-active);
          outline: 1px solid var(--hax-color-accent1);
        }
        :host([default]) paper-button {
          background: black;
        }
        :host([dark]) paper-button {
          background-color: var(--hax-color-text);
          color: var(--hax-color-bg-accent);
        }
        :host([dark]) paper-button:hover {
          background-color: var(--hax-color-bg-accent);
          color: var(--hax-color-text);
        }
        :host([dark]) paper-button:active {
          background: var(--hax-color-bg-accent);
          color: var(--hax-color-text);
        }
        iron-icon {
          width: 20px;
          height: 20px;
          padding: 0;
          margin: 0;
        }
        :host([mini]) iron-icon {
          width: 16px;
          height: 16px;
        }
        :host([mini]) paper-button {
          border-radius: 50%;
          width: 18px;
          height: 18px;
          padding: 1px;
          border: 1px solid var(--hax-color-border-outline);
        }
        :host([mini]) paper-button:active,
        :host([mini]) paper-button:hover,
        :host([mini]) paper-button:focus {
          outline: unset;
          border: 1px solid var(--hax-color-accent1);
        }
        :host([menu]) paper-button {
          padding: 0 8px;
          width: 100%;
          height: 36px;
        }
        :host([menu]) paper-button:hover {
          background-color: #d3d3d3;
          color: #000000;
        }
        .flip-icon {
          transform: rotateY(180deg);
        }
        paper-tooltip {
          --paper-tooltip-background: #000000;
          --paper-tooltip-opacity: 1;
          --paper-tooltip-text-color: #ffffff;
          --paper-tooltip-delay-in: 0;
        }
      `
    ];
  }
  render() {
    return html`
      <custom-style>
        <style is="custom-style">
          paper-tooltip {
            --paper-tooltip: {
              border-radius: 0;
            }
          }
        </style>
      </custom-style>
      <paper-button
        .disabled="${this.disabled}"
        id="buttoncontainer"
        tabindex="0"
        .title="${this.tooltip}"
      >
        <iron-icon
          id="button"
          icon="${this.icon}"
          .hidden="${!this.icon}"
        ></iron-icon>
        <span id="label" .hidden="${!this.label}">${this.label}</span>
        <slot></slot>
      </paper-button>
      <paper-tooltip
        id="tooltip"
        offset="10"
        position="${this.tooltipDirection}"
        animation-delay="0"
      >
        ${this.tooltip}
      </paper-tooltip>
    `;
  }
  static get tag() {
    return "hax-toolbar-item";
  }
  constructor() {
    super();
    this.corner = "";
    this.disabled = false;
    this.dark = false;
    this.menu = false;
    this.mini = false;
    this.icon = false;
    this.label = false;
    this.tooltip = "";
    this.tooltipDirection = "top";
    this.default = false;
  }
  static get properties() {
    return {
      /**
       * corner
       */
      corner: {
        type: String,
        reflect: true
      },
      /**
       * disabled state
       */
      disabled: {
        type: Boolean,
        reflect: true
      },
      /**
       * Inverted display mode
       */
      dark: {
        type: Boolean,
        reflect: true
      },
      /**
       * Style to be presented in a menu
       */
      menu: {
        type: Boolean,
        reflect: true
      },
      /**
       * Present smaller the normal but consistent
       */
      mini: {
        type: Boolean,
        reflect: true
      },
      /**
       * Icon to represent this button, required.
       */
      icon: {
        type: String
      },
      /**
       * Text applied to the button
       */
      label: {
        type: String
      },
      /**
       * Hover tip text
       */
      tooltip: {
        type: String
      },
      /**
       * Direction that the tooltip should flow
       */
      tooltipDirection: {
        type: String,
        attribute: "tooltip-direction"
      },
      default: {
        type: Boolean,
        reflect: true
      }
    };
  }
  /**
   * Life cycle callback
   */
  updated(changedProperties) {
    changedProperties.forEach((oldValue, propName) => {
      if (
        propName == "tooltip" &&
        (this[propName] == "" || this[propName] == null)
      ) {
        this.shadowRoot
          .querySelector("#tooltip")
          .setAttribute("aria-hidden", "true");
      } else {
        this.shadowRoot
          .querySelector("#tooltip")
          .setAttribute("aria-hidden", "false");
      }
    });
  }
}
window.customElements.define(HaxToolbarItem.tag, HaxToolbarItem);
export { HaxToolbarItem };
```