origami: CustomStyleService not working for css-mixin object

According to the Custom Style guide, CustomStyleService works fine on custom css variables, but it doesn’t work for mixin objects. Here is an example:

/* my-custom-ctrl.component.ts */
import { Component, OnInit } from '@angular/core';
import { CustomStyleService } from '@codebakery/origami';
...

@Component({
  selector: 'my-custom-ctrl',
  templateUrl: 'my-custom-ctrl.component.html',
    styleUrls: ['my-custom-ctrl.component.html.css']
})
export class MyCustomCtrl implements OnInit {
  constructor(private customStyle: CustomStyleService) { }

  ngOnInit() {
    this.customStyle.updateCustomStyles();
  }
 ...
}
/* my-custom-ctrl.component.css */
...
paper-textarea {
    --paper-input-container-input: {
        color: darkgreen;
        font-size: 20px;
    };
   --paper-input-container-color: red;
   @apply --some-other-styles-mixin;
} 
...

With CustomStyleService adopted, the component style is correctly wrapped with <custom-style> element, but paper-textarea gets compiled incorrectly. It gets transpiled in the following (captured by Chrome Inspector):

paper-textarea.create-message-input[_ngcontent-c11] {
    \--paper-input-container-input: {
        color: darkgreen;
        font-size: 20px;
    }
}

As given above, --paper-input-container-color and the next @apply disappeared, they appear and work correctly as our expectation once I comment out --paper-input-container-input. However, if I move paper-textarea styles into the document-level styling, all work fine, this is somewhat weird.

Hopefully get help to solve this problem!

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 24 (12 by maintainers)

Commits related to this issue

Most upvoted comments

Looks like webpack’s css-loader is the culprit. I created a simple test webpack project.

index.js

require('./style.css')

style.css

html {
  --my-mixin: {
    color: blue;
  }
}

webpack.config.js

module.exports = {
  module: {
    loaders: [{
      test: /\.css$/,
      loader: 'css-loader'
    }]
  }
};

webpack ./index.js index.bundle.js compiles everything, and here’s what css-loader adds in the bundle:

(function(module, exports, __webpack_require__) {

exports = module.exports = __webpack_require__(1)(undefined);
// imports


// module
exports.push([module.i, "html {\n  \\--my-mixin: {\n    color: blue;\n  }\n}\n", ""]);

// exports


/***/ })

The CSS @apply proposal is still very much a rough draft and in early stages of talks across browsers. I don’t think we’d get much response or motivation filing a feature request to support it in css-loader, especially when you could use PostCSS in webpack and there’s a PostCSS @apply plugin for it.

Nor do I think we’d get anywhere asking Angular to switch from the simple css-loader to a complex PostCSS setup.

Where do we go from here?

Well, I think the best thing we can do is intercept the styles before they are added to the dom as a script tag. angular-polymer may have the right idea in a specialized SharedStylesHost.

We could intercept the raw CSS strings and fix the escaped mixin blocks. The rest of the CSS data is there, it just breaks when put after the escaped mixin. We’d also be able directly create and manage the <custom-style> elements, rather than doing a global wrap. Another benefit is that we wouldn’t have to call customStyle.updateSharedStyles() anymore.

I’ll start working on a rough draft implementation. Thanks @first87 for finding this problem!