In my previous article I discussed some things about the Web Components spec and how it enabled our app to be scalable. Now we'll move into the real meat of what made up our project, the smallest part of which was what we called base-components.
Base-Components are kind of like "atoms" in Brad Frost's Atomic Design principles. Our menu boards are ultimately made up of many base-components performing small individual functions that we pull together to form the whole. Sometimes base-components can also be made of other base components, and in our system our primary example would be the base-product-table.
When looking at any menu board (or even printed menu) you will notice groupings of line listings usually paired with prices and/or caloric information. Rather than attempt to recreate that in each section of the menu board we created a Product Table. The Product Table is responsible for laying out line listings, enabling syncing, and allowing us to target them for "edit mode" in our app. The interesting thing about the component is mostly surrounding how it makes use of its Light DOM. An code example would look like the following:
<core-base-product-table overrides="[[rules.overrides]]" class$="editable [[_sizeMealNumbers(slots)]]"> <core-base-collection class="cells-wrapper" data-content="true" family="vm" interval='' blacklist='["dom-repeat","spacer"]'> <template is="dom-repeat" items="[[slots]]"> <core-base-row-meal class="editable" slot="[[item]]"></core-base-row-meal> </template> </core-base-collection> </core-base-product-table>
It is tempting to want to do everything with web components via attributes, but resist the temptation. Make use of the DOM as much as possible.
By using the Light DOM in the example above, we make our lives easier in a couple of ways. First, we are able to create different table cell styles by creating different table cell components. This allows us greater flexibility in not only how our tables appear but also with how each cell interprets the "slot" data it receives. The second benefit is that styling overrides become much simpler. If we were to have the Product Table component directly generate the table cells within its own Shadow DOM by reading data attributes directly, targeting the styling of the internal table cell can only be done by what we like to call "mixinception" or by passing it yet more data attributes to define those overrides [ Mixins ].
("Mixinception" is the use of CSS mixins that target yet another deeper child mixin)
By breaking down our menu designs into their smallest parts we keep our code DRY and gain the benefits of a cascading effect much like CSS when we need to make style or logic changes to our application. Once we have all of these created we can then begin assembling them into what we call Regions which will be discussed in my next article.