Patterns

A pattern in Mote is a representation of a self-contained unit of reusable interface.

Each pattern is displayed in the Mote Explorer as a resizable iframe, and can be viewed on its own page in isolation.

A pattern contains a minimal set of files.

root
└── example-pattern
    ├── element.html
    ├── data.yaml (optional)
    ├── metadata.yaml (optional)
    ├── usage.html or usage.md or usage.rst (optional)
    └── variations (optional directory)

For the sake of example, from here we will be referring to the “anchor” pattern and we’ll go through the process of creating a pattern step-by-step.

Anchor example

element.html

A pattern is written in the Mote Templating Language (MTL), a subset of the popular Jinja templating language.

{% load mote_tags %}

<a>{{ text }}</a>

data.yaml

A pattern usually needs data to be useful. The data file provides both the data structure and default values.

text: Anchor text

metadata.yaml

Information that cannot be inferred from the naming conventions resides in the metadata file.

title: A Very Simple Anchor
description: This is the simplest possible anchor.

Re-use example

A pattern may re-use any other pattern to do its rendering. This trivial example illustrates the technique.

element.html

{% load mote_tags %}

{% render "project.browser.atoms.anchor" data %}

How data.yaml works

The most powerful and difficult part of Mote is understanding how data.yaml works, and how to provide partial user-specified data to a pattern so it renders correctly.

Let’s start with a simple data file:

text: Anchor text
attrs:
    ref: /link
    ata-foo: bar

Mote interprets the data file and makes certain variables available in element.html, in this case data, text and attrs. Making the first-depth variables directly available is a concious design decision because it leads to cleaner templates.

The data structure may grow arbitrarily deep but typically they grow to maximum four levels. Anything more and the patterns themselves are probably too complex. We explore that in the pattern composition section.

In this case element.html is slightly more complex:

{% load mote_tags %}

<a href="{{ attrs.href }}" data-foo="{{ attrs.foo }}">{{ text }}</a>

If you really want to make the element handle all data variations then use a for loop:

{% load mote_tags %}

<a {% for k, v in attrs.items %} {{ k }}="{{ v }}" {% endfor %}>
    {{ text }}
</a>

The pattern renders as:

<a href="/link" data-foo="bar">Anchor text</a>

That’s not particularly useful because all links don’t go to /link, so let’s provide user-defined data to the pattern. At this stage we are not concerned with how to pass user-defined data to the pattern but with what this data looks like.

text: Google
attrs:
    href: http://www.google.com

Yields:

<a href="http://www.google.com" data-foo="bar">Google</a>

Notice how data-foo is still present even though it is not part of the user-defined data. This is because Mote performs a deep merge of data, meaning you need only declare the items you want to provide data for. This is incredibly useful if your default data is large because it would be cumbersome to have to redeclare the entire data structure in your user-defined data.

The attrs approach is also extensible by allowing you to declare items the pattern has no knowledge of, in this case a target attribute.

text: Google
attrs:
    href: http://www.google.com
    target: _blank

Yields:

<a href="http://www.google.com" data-foo="bar" target="_blank">Google</a>

Composite patterns

The major benefit of a pattern library is to provide a set of reusable patterns. This is best illustrated through an example: an anchor pattern re-using a text pattern.

The text pattern:

text: Simple text
{{ text }}

The composite anchor pattern:

children:
    text:
        id: project.browser.atoms.text
        value: Anchor text one
attrs:
    href: #
{% load mote_tags %}

<a {% for k, v in attrs.items %} {{ k }}="{{ v }}" {% endfor %}>
    {% for child in children.values %}
        {% render child %}
    {% endfor %}
</a>

The anchor pattern is now fully extensible - it takes an arbitrary number of attrs and an arbitrary number of children inside it, with the text pattern being the only child by default.

User-defined data is now a combination of the text pattern’ss data and the anchor’s data:

children:
    text:
        value: Google
attrs:
    href: http://www.google.com

Yields:

<a href="http://www.google.com" data-foo="bar">Google</a>

Note that once again only a subset of the full data needs to be considered for user-defined data.

Documenting patterns

A pattern may be documented through either HTML, markdown or restructured text. Create either a usage.html, usage.md or usage.rst file in the pattern root to surface documentation through the Mote Explorer.

Variations

A variation is a pattern that is so similar to an existing pattern that it does not warrant to be a pattern itself.

A variation has exactly the same structure and rules as a pattern. Place pattern in the variations directory of an existing pattern and it is made available as a variation, not a pattern.

Referencing a pattern or variation

Mote uses a dotted name notation to resolve patterns and variations by name. A pattern resides in the directory mote/projects/project/library/browser/atoms/anchor is named project.browser.atoms.anchor. Similarly, a variation that resides in the directory mote/projects/project/library/browser/atoms/anchor/variations/alert is named project.browser.atoms.anchor.alert.

The name of the project should nearly always be replaced by self. This reserved word resolves to the project currently in scope and is useful when basing entire pattern libraries on other pattern libraries.