Improving pattern libraries, with Polymer.

Sam Beckham
@samdbeckham

http://nodivide.us

https://frontendne.co.uk

WTF is a pattern library?

A coded
style guide

A collection of code examples

A bit like bootstrap

A separation of concerns

(Between the front and back end)

Pretty
Freaking
Awesome.

Copy this

<ul class="pagination">
    <li>1</li>
    <li class="pagination__current-page">2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>

Get this

What's the beef then?

Lots of copying and pasting

<ul>
    <li class="field__location">
        <span class="field__location__name">Location</span>
        <div class="field__location__map">
            <div class="location__loading-indicator">
                <svg viewbox="0 0 100 100" class="icon icon__logomark animation animation--infinite animation__spin">
                    <use xlink:href="/resources/images/sprite/icon-sprite.svg#icon__logomark"></use>
                </svg>
            </div>
        </div>
        <div class="field__location__search">
            <input type="search" value="" placeholder="Enter a postcode or a place." />
        </div>
        <ul class="form-fields grid">
            <li class="column column__6-of-12">
                <label for="lat">Latitude</label>
                <input type="text" pattern="-?[0-9]{0,2}\.?[0-9]*" id="lat" name="lat" class="field__location__lat" value="54.981308">
            </li>
            <li class="column column__6-of-12">
                <label for="lon">Longitude</label>
                <input type="text" pattern="-?[0-9]{0,3}\.?[0-9]*" id="lon" name="lon" class="field__location__lon" value="-1.608489">
            </li>
        </ul>
    </li>
</ul>

Code can be hard to understand

<ul>
    <li class="field__location">
        <span class="field__location__name">Location</span>
        <div class="field__location__map">
            <div class="location__loading-indicator">
                <svg viewbox="0 0 100 100" class="icon icon__logomark animation animation--infinite animation__spin">
                    <use xlink:href="/resources/images/sprite/icon-sprite.svg#icon__logomark"></use>
                </svg>
            </div>
        </div>
        <div class="field__location__search">
            <input type="search" value="" placeholder="Enter a postcode or a place." />
        </div>
        <ul class="form-fields grid">
            <li class="column column__6-of-12">
                <label for="lat">Latitude</label>
                <input type="text" pattern="-?[0-9]{0,2}\.?[0-9]*" id="lat" name="lat" class="field__location__lat" value="54.981308">
            </li>
            <li class="column column__6-of-12">
                <label for="lon">Longitude</label>
                <input type="text" pattern="-?[0-9]{0,3}\.?[0-9]*" id="lon" name="lon" class="field__location__lon" value="-1.608489">
            </li>
        </ul>
    </li>
</ul>

They're difficult to maintain

<div class="pagination">
    <a href="#" class="button button--disabled pagination__paddle" disabled>< Prev</a>
    <input class="pagination__page" type="text" inputmode="number" pattern="[0-9]+" max="52" value="1">
    <span class="pagination__limit">52</span>
    <a href="#" class="button pagination__paddle">Next ></a>
</div>

Pagination

Component

<ul class="pagination">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li class="pagination__current-page">4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
</ul>

Pagination

Component

Markup changes funk you up

A separation of concerns?

Not quite

It's good…

…but it's not right

Enter, Polymer

WTF is Polymer?

Web component framework

A collection of Web components

WTF are web components?

"Web Components are a set of standards currently being produced by Google engineers as a W3C specification that allow for the creation of reusable widgets or components in web documents and web applications. The intention behind them is to bring component-based software engineering to the World Wide Web. The components model allows for encapsulation and interoperability of individual HTML elements."

tl:dr;

Create your own HTML elements

Contain
your styles within them

Utilise

lifecycle callbacks

A separation of concerns

Pretty
Freaking
Awesome.

Let's mix them together

<div class="pagination">
    <a href="#" class="button button--disabled pagination__paddle" disabled>< Prev</a>
    <input class="pagination__page" type="text" inputmode="number" pattern="[0-9]+" max="52" value="1">
    <span class="pagination__limit">52</span>
    <a href="#" class="button pagination__paddle">Next ></a>
</div>

Pagination

Component

<my-pagination></my-pagination>

Pagination

Component

<my-pagination
    currentpage="1"
    totalpages="52">
</my-pagination>

Pagination

Component

How it's made

<link 
  rel="import"
  href=".../polymer.html">

Import Polymer

<link 
  rel="import"
  href=".../polymer.html">

<polymer-element
  name="my-pagination">
</polymer-element>

Polymer Element

<link 
  rel="import"
  href=".../polymer.html">

<polymer-element
  name="my-pagination"
  attributes="totalpages currentpage">
</polymer-element>

Element Attributes

<link 
  rel="import"
  href=".../polymer.html">

<polymer-element
  name="my-pagination"
  attributes="totalpages currentpage">
    <template>
        <!-- Element markup goes here -->
    </template>
</polymer-element>

Element Template

<link 
  rel="import"
  href=".../polymer.html">

<polymer-element
  name="my-pagination"
  attributes="totalpages currentpage">
    <template>
        <!-- Element markup goes here -->
    </template>
    <script>
        Polymer();
    </script>
</polymer-element>

Scripts

<link 
  rel="import"
  href=".../polymer.html">

<polymer-element
  name="my-pagination"
  attributes="totalpages currentpage"
  noscript>
    <template>
        <!-- Element markup goes here -->
    </template>
</polymer-element>

Noscript

<template>
    <!-- Element markup goes here -->
</template>

Template

<template>
    <div class="pagination">
        <a class="pagination__paddle">Prev</a>
        <input
          class="pagination__page"
          type="text"
          max="52"
          value="1">
        <span class="pagination__limit">52</span>
        <a href="#" class="pagination__paddle">Next</a>
    </div>
</template>

Static HTML

<template>
    <link rel="stylesheet" href="my-pagination.css">
    <div class="pagination">
        <a class="pagination__paddle">Prev</a>
        <input
          class="pagination__page"
          type="text"
          max="52"
          value="1">
        <span class="pagination__limit">52</span>
        <a href="#" class="pagination__paddle">Next</a>
    </div>
</template>

Styles

<template>
    <link rel="stylesheet" href="my-pagination.css">
    <div class="pagination">
        <a class="pagination__paddle">Prev</a>
        <input
          class="pagination__page"
          type="text"
          max="{{ totalpages }}"
          value="{{ currentpage }}">
        <span class="pagination__limit">{{ totalpages }}</span>
        <a href="#" class="pagination__paddle">Next</a>
    </div>
</template>

Attribute injection

<template>
    ...
    <template
      if="{{ currentpage == 1 }}">
        <a class="pagination__paddle disabled">Prev</a>
    </template>

    <template
      if="{{ currentpage != 1 }}">
        <a class="pagination__paddle">Prev</a>
    </template>
    ...
</template>

Inline logic

<html>
    <head>
        <link 
          rel="import"
          href=".../my-pagination.html">
    </head>
    <body>
        <!-- Content goes here -->
    </body>
</html>

Import it

<html>
    <head>
        <link 
          rel="import"
          href=".../my-pagination.html">
    </head>
    <body>
        <my-pagination
          currentpage="1"
          totalpages="52">
        </my-pagination>
    </body>
</html>

Use it

That's it

What does this solve?

Lots of copying and pasting

<ul>
    <li class="field__location">
        <span class="field__location__name">Location</span>
        <div class="field__location__map">
            <div class="location__loading-indicator">
                <svg viewbox="0 0 100 100" class="icon icon__logomark animation animation--infinite animation__spin">
                    <use xlink:href="/resources/images/sprite/icon-sprite.svg#icon__logomark"></use>
                </svg>
            </div>
        </div>
        <div class="field__location__search">
            <input type="search" value="" placeholder="Enter a postcode or a place." />
        </div>
        <ul class="form-fields grid">
            <li class="column column__6-of-12">
                <label for="lat">Latitude</label>
                <input type="text" pattern="-?[0-9]{0,2}\.?[0-9]*" id="lat" name="lat" class="field__location__lat" value="54.981308">
            </li>
            <li class="column column__6-of-12">
                <label for="lon">Longitude</label>
                <input type="text" pattern="-?[0-9]{0,3}\.?[0-9]*" id="lon" name="lon" class="field__location__lon" value="-1.608489">
            </li>
        </ul>
    </li>
</ul>
<location-field
  lon="-1.608489"
  lat="54.981308">
</location-field>

Some copying and pasting

Code can be hard to understand

<ul>
    <li class="field__location">
        <span class="field__location__name">Location</span>
        <div class="field__location__map">
            <div class="location__loading-indicator">
                <svg viewbox="0 0 100 100" class="icon icon__logomark animation animation--infinite animation__spin">
                    <use xlink:href="/resources/images/sprite/icon-sprite.svg#icon__logomark"></use>
                </svg>
            </div>
        </div>
        <div class="field__location__search">
            <input type="search" value="" placeholder="Enter a postcode or a place." />
        </div>
        <ul class="form-fields grid">
            <li class="column column__6-of-12">
                <label for="lat">Latitude</label>
                <input type="text" pattern="-?[0-9]{0,2}\.?[0-9]*" id="lat" name="lat" class="field__location__lat" value="54.981308">
            </li>
            <li class="column column__6-of-12">
                <label for="lon">Longitude</label>
                <input type="text" pattern="-?[0-9]{0,3}\.?[0-9]*" id="lon" name="lon" class="field__location__lon" value="-1.608489">
            </li>
        </ul>
    </li>
</ul>
<location-field
  lon="-1.608489"
  lat="54.981308">
</location-field>

Code is super easy to understand

It's difficult to maintain

<my-pagination
    totalpages="7"
    currentpage="4">
</my-pagination>

Pagination

Component

<my-pagination
    currentpage="1"
    totalpages="52">
</my-pagination>

Pagination

Component

It's easy to maintain

A TRUE separation of concerns

Pretty
Freaking
Awesome.

Can I use
it now?

YES!

(kind of)

Polyfills

Use it where you can

Things can only get better

Moar
Stuff

https://github.com/samdbeckham/polymer-pattern-library-example

http://polymer-project.org

http://webcomponents.org

http://reddit.com/r/polymerjs

Thanks!

Sam Beckham
@samdbeckham