Sunday, August 24, 2014

Crazy Theming Polymer.dart with Core-Style


I am resigned.

Resigned that the core-style element and I disagree on how it should support theming. I have no illusions that I am in the right on this one, but I will attempt to make my case anyway.

When I think of custom themes, I think of setting a few colors and maybe a few other atomic values that can be used by a widget to look more or less like it fits in with the rest of the web page. In core-style, parlance, this looks like:
      <script>
        CoreStyle.g.primaryColor = 'orange';
        CoreStyle.g.secondaryColor = 'green';
      </script>
Or, alternatively, as:
        CoreStyle.g = {
          primaryColor: 'orange',
          secondaryColor = 'green'
        };
I would think that web page trying to use a widget would set these values and the widget would then honor the values. As best I can tell, this is not how core-style works.

Instead, core-style wants these global settings defined by the containing page and it wants the containing page to define styles that will apply to the internals of the widgets being used. That is, if I know that my <lorem-dialog> custom Polymer element contains paper-button elements, then core-style would have me define the global property setting and the detailed widget styling on the containing page:
  <body>
    <h1>Play Paper</h1>
    <lorem-dialog></lorem-dialog>
    <core-style id="theme">
      :host paper-button {
        border: 5px solid {{g.primaryColor}};
        padding: 2px 5px;
      }
    </core-style>
    <script>
      CoreStyle.g.primaryColor = 'orange';
    </script>
  </body>
I cannot help but think this requires the containing page to know too much about the internal implementation of the widget (the Polymer element).

I realize that I am almost certainly making a dumb assumption here. I am probably abusing this. Or not thinking right. Knowing this does not help me. Making the problem worse usually does. If I push this further—feel more pain in coding the wrong way—then I usually figure out how to do it right.

Last night, I was able to get core-style to work like I want by making the core-style's g property available in the backing Polymer element class:
Polymer('lorem-dialog', {
  created: function() {
    this.g = CoreStyle.g;
  },
  // ...
}
I could then use this reference inside the Polymer template:
<polymer-element name="lorem-dialog">
  <template>
    <!-- ... -->
    <core-style id="theme">
      :host paper-button {
        border: 5px solid {{g.primaryColor}};
        padding: 2px 5px;
      }
    </core-style>
    <core-style ref="theme"></core-style>
  </template>
  <script>
    Polymer('lorem-dialog', { /* ... */ });
  </script>
</polymer-element>
Unfortunately, that does not work in Polymer.dart. Try as I might, there is no g property on the core-style object in Dart. But…

I know that the Dart versions of the core and paper elements are just thin wrappers around the JavaScript versions. Since I know how to get the global core-style values from JavaScript, perhaps I can use Dart's awesome JavaScript interoperability to resolve this dilemma.

So, I import the dart:js packages and define a g getter to return the value of CoreStyle.g from JavaScript:
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'dart:js';

@CustomTag('lorem-dialog')
class LoremDialog extends PolymerElement {
  LoremDialog.created(): super.created();

  get g => context['CoreStyle']['g'];
  // ...
}
And that actually works. In the template, I can define and reference a “theme” style that makes use of the global values from the web page using my Polymer element:
<polymer-element name="lorem-dialog">
  <template>
    <!-- ... -->
    <core-style ref="theme"></core-style>
    <core-style id="theme">
      paper-button {
        border: 5px solid {{g['secondaryColor']}};
        color: {{g['primaryColor']}};
        font-weight: bold;
        padding: 2px 5px;
      }
    </core-style>
  </template>
  <script type="application/dart" src="lorem_dialog.dart"></script>
</polymer-element>

I strongly doubt that I will offer this up as a solution in Patterns in Polymer, but it does work in both JavaScript and Dart. Even so, the amount of resistance that I get from the library is strongly suggesting to me that I am doing something wrong. But even pushing this hard against core-style is not suggesting to me the right way to tackle this problem. Hopefully something will come to me (or someone can point me in the right direction) over the course of the next few days...


Day #162

1 comment:

  1. I am in search for the right way to create core themes. We will need to make a polymer app use multiple color combination for a list of clients. Being able to load the desired style per client is our goal.

    ReplyDelete