Polyblocks

Bitbucket Repository

A micro-pattern for reusable, functional HTML components

This is not a framework, but a methodology for creating reusable, encapsulated Web Components for faster, more organised
frontend development.

It is important to note this is not an all problem solving framework, just a simple, lightweight methodology for solving some common problems making re-usable frontend code. With the benefit of being written within the Web Components specification, available right now in many modern browsers.

To illustrate by example, here is a simple Modal component that lives in modal.html:

<modal>
    <template>
        <div class="component__container">
            <div class="component__title">{{title}}</div>
            <div class="component__content">{{content}}</div>
            <div class="component__buttons">
                <button class="component__button action">{{buttonText}}</button>
            </div>
            <div class="component__close"></div>
        </div>
    </template>
    <style>
        //Styles are scoped to the custom element tag name, making it safe to drop into any page
        x-modal .component__container {
            /* Styles ommitted for brevity */
        }
    </style>
    <script type=text/javascript">
        class Modal extends Polyblock {
            // connectedCallback is from the Web Components spec, and is ran when an instance of the custom element is rendered on the page.
            connectedCallback() {
                super.connectedCallback();

                /*
                    By using the `this` operator, we are scoping our CSS selector to the instance of the custom element,
                    allowing us to be clean and concise.
                */
                this.querySelector('.component__close').addEventListener('click', function(){
                    this.classList.add('hidden');
                }.bind(this));
            }
        }

        //This provies a native way to set a template for our Web Component.
        Modal.prototype.template = document.currentScript.parentNode.querySelector('template').innerHTML;
        customElements.define('x-modal', Modal);
    </script>
</modal>

The Polyblock class that Modal extends from is a helper class that provides simple templating and one-way data binding, this is entirely optional and can be replaced with your own helper class.

These components can contain a HTML template, styles, and javascript. They can be included into the page using HTML imports, or included in the page. Then when you want to use it, you simply use the custom tag of the component in your page, like below:

<x-modal data-config='{
    "title": "Music",
    "content": "Are you finding it hard to close this modal? Sign up now to find out how!",
    "buttonText": "Click Me",
    "actionHref": "/some-link"
}'></x-modal>

As you can see, we are easily re-using all of our frontend code with one simple tag on the page. Extending from the Polyblock class allows us to add configuration for one-way data binding in the template, or for use in the javascript class of the custom element. If you want to create a component with no data or JS functionality, that is entirely possible.

No build pipeline is required, allowing for a lightweight deployment and development process. But transpilation of ES6 and CSS preprocessors is possible through your favourite build tools such as Gulp or Grunt, which makes scaling up to more complex projects possible.

More Examples

This repository contains a components folder which contains example components to show how they are built. The file index.html then provides some examples of how to use these components.

The Thinking

We are trying to create framework agnostic re-usable snippets of frontend code. This is already possible, but often it is dispersed across a project in opinionated frameworks or patterns and the startup cost and cognitive cost of understanding those frameworks and the tooling around them is high. The Polyblock helper class is just 25 lines long, and you could very easily replace it with your own custom functionality and still use this pattern. Complete freedom to introduce complexity to your project when you need it, rather than right from the start.

The Caveat

At the moment, some of the Web Components spec is still not implemented in all modern browsers. This means, depending on your own requirements, you may need to use a polyfill to add suport for older browsers.