Usage

Wellcome Web Components should be accessible and easy to use whether you’re a designer, developer or another kind of web practitioner. This guide describes how the component library should be used for:

  • Documentation
  • Design
  • Development

Structure

The library is a static site generated by Fractal from the Wellcome.ac.uk Git repository. It is linked directly to the website code, and its hierarchy is reflected in the directory structures of the repository. To make any changes to the library, one has to edit Markdown and HTML/JS/CSS code directly in the repository. This ensures that the component library stays in sync with the site at all times, and is therefore a living pattern library.

Fractal recognizes two different kinds of entities: Docs, which are Markdown pages such as this one, and Components.

Docs

In our codebase, Docs are located in the pattern-library directory, along with our tweaks to the default Fractal theme and the build folder where Fractal generates the site. They should be used for documentation that applies sitewide, as opposed to component-specific documentation. Examples include branding philosophy, complex layout systems and colour palettes.

The full path to the directory is:

www/sites/all/themes/corp_base/pattern-library/docs/

If you have access to the repo in github, you can edit the files in the documents folder and open a pull request to merge them back in to the pattern library itself.

Components

Due to the nature/history of the codebase, we’re gradually concentrating all components in the corp_markup Drupal module, located at:

www/sites/all/modules/custom/corp_markup/theme

Components are often logically grouped into Collections, such as paragraphs. All templates used by Drupal which are not integrated with Fractal yet should be in the undocumented collection, which is hidden from Fractal.

Each component is contained in a folder which must be named exactly the same as the Drupal template file, i.e. info_box.tpl.php. This is the only way Fractal can handle the double file extension without breaking the component’s display.

To edit the notes for a specific component, you will need to find the readme.md file in the component’s specific folder within the git repo.


Developing with Fractal

Assuming you have installed our npm dependencies with npm install, you can:

  • start a hot-reloading local build of the component library with npm run watch:fractal
  • run the static build of the library into pattern-library/build with npm run build:fractal
  • deploy the component library with npm run deploy:fractal

Building Components

A Fractal component consists of a template file (in our case, a PHP file ending with .tpl.php), a configuration file and a number of resources, such as CSS, JS and notes. As a rule, we use JavaScript config files as opposed to YAML or JSON, because it allows us to specify component metadata in a more dynamic and readable way.

In the repository, a typical component might look like this:

├── info_box.tpl.php
│   ├── README.md
│   ├── info-box.scss -> ../../../../../../themes/corp_base/assets/css/site/includes/_include-info-box.scss
│   ├── info_box.tpl.config.js
│   └── info_box.tpl.php

Let’s break it down – the above file tree contains:

  • the template file
  • the config file
  • a README.md file which is picked up by Fractal as component notes
  • a Sass stylesheet, which is picked up as a resource, but isn’t actually in the directory – rather it is symlinked from the theme folder. This may change in the future, but it enables us to keep our frontend assets separate from Drupal.

Note that beside the config and readme files, any other resources can (and often should) be symlinked to the component directory.

In order to create a Component, we create a folder like the one above with the necessary files and place it in the components directory specified above.

In Fractal, Sass and JS resources will appear in their respective tabs for each component, and all other assets will be grouped in the Assets tab.

Configuration

The component config file is a node.js script which exports an Object containing component metadata. The naming convention is <component_name>.tpl.config.js – the ‘tpl’ is needed for Fractal to associate the config with the template file.

Here’s an example component config:

const sampleImgPath = '/assets/images/pattern-library/trooper.jpg';
const sampleImg = `<img class="person__photo promo__photo lazyautosizes lazyloaded" src="${sampleImgPath}" />`;

module.exports = {
  'name': 'Person',
  'status': 'ready',
  'context': {
    'name': 'Joe Bloggs',
    'job_title': 'Software Developer',
    'institution': 'Wellcome',
    'date_of_appointment': '<strong>Date of appointment: </strong>29 March 2017',
    'short_biography': 'Stormtroopers were the assault troops of the Galactic Empire. Dissenting citizens referred to them as bucketheads, a derogatory nickname inspired by the bucket-shaped helmets of stormtroopers.',
    'image': sampleImg
  }
};

Preview Layouts

To present each component in its ‘natural habitat’, we’re using a feature of Fractal called Preview Layouts. These are HTML wrappers which can import assets and provide page context for individual components. Using these layouts we can place the component in different parts of the layout, surround it with text or apply different CSS bundles.

To use a specific preview layout with a component, we just add something like this to the config file:

{
  'preview': '@preview_in_text.tpl'
}

Again, the ‘tpl’ is needed so Fractal picks up the file. The file should be located in the components root, i.e. corp_markup/theme/preview_in_text.tpl.php.

Fractal-specific assets

Preview layouts are also used to load the CSS and JavaScript bundles from the codebase. We’ve had to come up with a way to tell the Adapter to resolve their paths into relative ones. It would be cumbersome to use PHP syntax here, and unnecessary because this will never be used by Drupal. We’ve chosen to just use a Handlebars-style helper syntax which is relatively easy to parse with regex.

Note that the {} are escaped here so that the parser doesn’t capture them.

<script defer type="text/javascript" src="\{\{ path /assets/js/site/site.min.js \}\}"></script>