React.js-based Patternlab.io

It’s an idea and all about components, patterns and composability

This morning, I was thinking of two things I wanted to try out when I got some free time (and a bit of inspiration): React.js and Pattern Lab. But I don’t want to experiment with them separately—because with a bit of imagination, they fit together perfectly.

What are those?

React is a JavaScript library (by Facebook) to easily create UI components, which can be combined and nested. Technically fascinating is the implementation of the Virtual DOM that abstracts away to rendering of regular HTML elements to the browser’s DOM. This allows React to quickly re-render a whole tree of nested components when data changes and only update those parts of the view that are affected by the change. Additionally, this makes it possible to render React components on a server and use the rendered markup on the client.

Pattern Lab, on the other hand, is a system (mainly for web frontend developers) to take components written as mustache templates and display them in fashion of atomic web design. You should explore the demo to see how it works (try the eye icon on the top right to display the markup and overlay annotations).

Atomic Web Design (as coined by Brad Frost) describes how the parts of a web page can divided into several levels of abstraction, called atoms, molecules, organisms, templates and pages. Combining several small things forms a new larger thing. Two links and an image (i.e. three atoms) can make up a new molecule (e.g. a headline). Templates are full layouts, with dummy data. Pages are instances of templates, with useful content and maybe special elements only visible in certain cases.

How is it the same?

Let’s take a look at some example code from Pattern Lab (from the demo):

<div class="page">
{{> organisms-header }}
<section role="main">
<h1 class="section-title">Our Outdoor Blog</h1>
<div class="l-main">
{{> organisms-latest-posts }}
{{> molecules-pagination }}
</div>
<aside class="l-sidebar">
{{> organisms-recent-tweets }}
</aside>
</section>
{{> organisms-footer }}
</div>

The organisms-header, included in the second line, is a partial (a snippet of code that gets injected) that may looks like this:

<header>
{{> atoms-logo }}
{{> molecules-primary-nav }}
{{> molecules-search }}
</header>

As you can see, the prefixes of the partial names match the naming conventions of atomic design. The nesting of partials allows a developer to build complex parts (e.g. organisms-latest-posts) using already defined (and designed) smaller elements (i.e. atoms and molecules in this case).

Now, compare this code to the following view in React:

/** @jsx React.DOM */
var React = require('react');
var Logo = require('../atoms/logo');
var PrimaryNav = require('../molecules/primary-nav');
var Search = require('../molecules/search');
var OrganismsHeader = React.createClass({
render: function () {
return
<header>
<Logo/>
<PrimaryNav/>
<Search/>
</header>
;
}
});
module.exports = OrganismsHeader;

Even though this is using the React-specific JSX, I believe it’s not that hard to see this results in the same markup as the mustache template above. Instead of using {{> atoms-logo }} we use the Logo component loaded in line four and render it as first child of the <header> element.

(JSX is a JavaScript preprocessor replacing the HTML tags with actual code. I don’t really like it. You can also write the same render function in plain JS, using methods like React.DOM.div, or in a quite different way like here, in CoffeeScript.)

Data

That was a nice discovery to make, but what’s a bunch of markup without any content? Where does the data come from?

Pattern Lab can use data defined in .json files existing next to your .mustache files to add content to your templates (see the documentation). Using this, one might be able to use it as a static site generator, with the added benefit of also having access to an overview of all the patterns used on your final pages.

React components have two ways of containing data: props that are set when the component is instantiated, and state, that may change when the user interacts with the component (e.g. when a button is toggled).

The most straight-forward way to integrate these systems would be to load the JSON data in the top-most React component and use that to set the properties (props) of all nested components.

Random Data

When defining React components, one can also add custom validations for all possible properties (using PropTypes). That means, instead of using fixed content written once, we could use a library like Faker.js to dynamically create new data for each component rendered.

This way, the demonstration of components would not just show the cases the developers thought of (regular names, short texts), but also the edge-cases (extremely long headlines, badly formatted texts). And just for the fn of it, there could also be a Shuffle button next to each component example to generate new content.

Update (21 Jul 2014): I recently implemented a small JS module called ReactPropSchema, which implements most of these aspects: Validating that a given data structure matches a schema and generating fake data using the the same schema and Faker.js. It can also be easily used to describe propTypes in React components. You can find it on GitHub and npm.

Showing Dependencies

One of the nicest features of Pattern Lab is that it explicitly lists the places where each partial is used and which other partials it includes. In the demo, the header organism includes:

The organisms-header pattern contains the following patterns: atoms-logo, molecules-primary-nav, molecules-search
The organisms-header pattern is included in the following patterns: templates-homepage, templates-blog, templates-article, pages-blog

To recreate such a behavior in a React-based application, one might have to build a dependency graph using the require() calls in each component file (assuming one uses CommonJS modules and each React component is in one file). It is probably possible to leverage some of the processing browserify already does.

What about CSS?

Good question. I haven’t found a good solution for handling stylesheets on a component based level. I would like to use SCSS and be able to handle the imports of other stylesheets similar to how a component might require another component it embeds. At the same time, the SCSS file would also need access to global variables like colors and to mixin libraries like burbon.

For now, I’ll be happy if I can get a workflow where I can edit my SCSS using Chrome’s Inspector as described here.

Conclusion

As of now (6 April 2014), this is all theoretical. I’m not sure if or when I might implement (some of) this as I need to find a project for which this is a good fit (Web application based on React, design based on patterns, possible without using Photoshop first).

Do you think this would work? Would it be useful? Would you do it differently? It’d love to hear from you.