Skip to content

Commit

Permalink
Add first draft of docs overhaul
Browse files Browse the repository at this point in the history
  • Loading branch information
thibaudcolas committed Oct 29, 2020
1 parent 77dc2f1 commit 453be36
Show file tree
Hide file tree
Showing 18 changed files with 507 additions and 377 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
- pip install poetry
- poetry install
script:
- cp README.md docs/README.md
- poetry run mkdocs build
deploy:
- provider: pages
Expand Down
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ npm run build
npm run start
```

### Documentation

The project’s documentation website is built with [MkDocs](https://www.mkdocs.org/).

```sh
# One-off build.
poetry run mkdocs build
# Rebuild the docs as you work on them
poetry run mkdocs serve
```

## Running the tests

To run the python tests, use the script in the root of the repo:
Expand Down
147 changes: 19 additions & 128 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,150 +1,41 @@
# Django pattern library
# [django-pattern-library](https://torchbox.github.io/django-pattern-library/)

[![PyPI](https://img.shields.io/pypi/v/django-pattern-library.svg)](https://pypi.org/project/django-pattern-library/) [![PyPI downloads](https://img.shields.io/pypi/dm/django-pattern-library.svg)](https://pypi.org/project/django-pattern-library/) [![Travis](https://travis-ci.com/torchbox/django-pattern-library.svg?branch=master)](https://travis-ci.com/torchbox/django-pattern-library) [![Total alerts](https://img.shields.io/lgtm/alerts/g/torchbox/django-pattern-library.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/torchbox/django-pattern-library/alerts/)

A module for Django that helps you to build pattern libraries.
> UI pattern libraries for Django templates
![Screenshot of the pattern library UI, with navigation, pattern rendering, and configuration](https://raw.githubusercontent.com/torchbox/django-pattern-library/master/.github/pattern-library-screenshot.webp)

## Documentation

Documentation is located on GitHub in [`docs/`](https://github.com/torchbox/django-pattern-library/tree/master/docs).

## Objective

At the moment, the main focus is to allow developers and designers
use exactly the same Django templates in a design pattern library
and in production code.

There are a lot of alternative solutions for building
pattern libraries already. Have a look at [Pattern Lab](http://patternlab.io/) and
[Astrum](http://astrum.nodividestudio.com/), for example.
But at [Torchbox](https://torchbox.com/) we mainly use Python and Django and
we find it hard to maintain layout on big projects in several places:
in a project's pattern library and in actual production code. This is our
attempt to solve this issue and reduce the amount of copy-pasted code.

To learn more about how this package can be used, have a look at our Wagtail Space 2020 talk: [Reusable UI components: A journey from React to Wagtail](https://www.youtube.com/watch?v=isrOufI7TKc)

[![Reusable UI components: A journey from React to Wagtail](https://raw.githubusercontent.com/torchbox/django-pattern-library/master/.github/pattern-library-talk-youtube.webp)](https://www.youtube.com/watch?v=isrOufI7TKc)

## Concepts
To understand how `django-pattern-library` works, the following concepts are important.

### Patterns
Any template that is displayed by the pattern library is referred to as a pattern. Patterns are divided into two categories: fragments and pages.

### Fragments
A fragment is a pattern whose markup does not include all of the resources (typically CSS and Javascript) for it to be displayed correctly on its own. This is typical for reusable component templates which depend on global stylesheets or Javascript bundles to render and behave correctly.

To enable them to be correctly displayed in the pattern library, `django-pattern-library` will inject the rendered markup of fragments into the **pattern base template** specified by `PATTERN_LIBRARY['PATTERN_BASE_TEMPLATE_NAME']`.

This template should include references to any required static files. The rendered markup of fragments will be available in the `pattern_library_rendered_pattern` context variable (see the tests for [an example](https://github.com/torchbox/django-pattern-library/blob/master/tests/templates/patterns/base.html)).

### Pages
In contrast to fragments, pages are patterns that include everything they need to be displayed correctly in their markup. Pages are defined by `PATTERN_LIBRARY['BASE_TEMPLATE_NAMES']`.

Any template in that list — or that extends a template in that list — is considered a page and will be displayed as-is when rendered in the pattern library.

It is common practice for page templates to extend the pattern base template to avoid duplicate references to stylesheets and Javascript bundles. Again, [an example](https://github.com/torchbox/django-pattern-library/blob/master/tests/templates/patterns/base_page.html) of this can be seen in the tests.
## Features

## How to install
This package automates the maintenance of UI pattern libraries or styleguides for Django projects, and allows developers to experiment with Django templates without having to create Django views and models.

First install the library:
- Create reusable patterns by creating Django templates files as usual.
- All patterns automatically show up in the pattern library’s interface.
- Define data as YAML files for the templates to render with the relevant Django context.
- Override Django templates tags as needed to mock the template’s dependencies.
- Document your patterns with Markdown.

```sh
pip install django-pattern-library
# ... or...
poetry add django-pattern-library
```


Then, in your Django settings, add `pattern_library` into your `INSTALLED_APPS`, and `pattern_library.loader_tags` to `OPTIONS['builtins']` into the `TEMPLATES` setting. For example:

```python
INSTALLED_APPS = [
# ...
'pattern_library',
# ...
]

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'builtins': ['pattern_library.loader_tags'],
},
},
]
```

Note that this module only supports the Django template backend.

### Settings

Next, set the `PATTERN_LIBRARY` setting. Here's an example showing the defaults:

```python
PATTERN_LIBRARY = {
# PATTERN_BASE_TEMPLATE_NAME is the template that fragments will be wrapped with.
# It should include any required CSS and JS and output
# `pattern_library_rendered_pattern` from context.
'PATTERN_BASE_TEMPLATE_NAME': 'patterns/base.html',
# Any template in BASE_TEMPLATE_NAMES or any template that extends a template in
# BASE_TEMPLATE_NAMES is a "page" and will be rendered as-is without being wrapped.
'BASE_TEMPLATE_NAMES': ['patterns/base_page.html'],
'TEMPLATE_SUFFIX': '.html',
# SECTIONS controls the groups of templates that appear in the navigation. The keys
# are the group titles and the values are lists of template name prefixes that will
# be searched to populate the groups.
'SECTIONS': (
('atoms', ['patterns/atoms']),
('molecules', ['patterns/molecules']),
('organisms', ['patterns/organisms']),
('templates', ['patterns/templates']),
('pages', ['patterns/pages']),
),
}

```

Note that the templates in your `PATTERN_LIBRARY` settings must be available to your project's
[template loaders](https://docs.djangoproject.com/en/3.1/ref/templates/api/#loader-types).

### URLs

Include `pattern_library.urls` in your `urlpatterns`. Here's an example `urls.py`:
## Documentation

```python
from django.apps import apps
from django.conf.urls import url, include
Documentation is available at [torchbox.github.io/django-pattern-library/](https://torchbox.github.io/django-pattern-library/), with source files in the `docs` directory.

urlpatterns = [
# ... Your URLs
]
- [Getting started](https://torchbox.github.io/django-pattern-library/getting-started/)
- Guides
- Reference

if apps.is_installed('pattern_library'):
urlpatterns += [
url(r'^pattern-library/', include('pattern_library.urls')),
]
```
## Examples of usage

This package is not intended for production. It is **highly recommended** to only enable this package in testing environments for a restricted, trusted audience. One simple way to do this is to only expose its URLs if `apps.is_installed('pattern_library')`, as demonstrated above, and only have the app installed in environment-specific settings.
At [Torchbox](https://torchbox.com/), we use this package for all of the Wagtail websites we build, for example [rca.ac.uk](https://github.com/torchbox/rca-wagtail-2019).

## Contributing

See anything you like in here? Anything missing? We welcome all support, whether on bug reports, feature requests, code, design, reviews, tests, documentation, and more. Please have a look at our [contribution guidelines](https://github.com/torchbox/django-pattern-library/blob/master/CONTRIBUTING.md).

If you just want to set up the project on your own computer, the contribution guidelines also contain all of the setup commands.
If you want to set up the project on your own computer, the contribution guidelines also contain all of the setup commands.

## Credits

View the full list of [contributors](https://github.com/torchbox/django-pattern-library/graphs/contributors). [BSD](https://github.com/torchbox/django-pattern-library/blob/master/LICENSE) licensed.

Project logo from [FxEmoji](https://github.com/mozilla/fxemoji). Documentation website built with [MkDocs](https://www.mkdocs.org/), and hosted in [GitHub Pages](https://pages.github.com/).
5 changes: 5 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Documentation

This documentation is built as a website with [MkDocs](https://www.mkdocs.org/): [torchbox.github.io/django-pattern-library/](https://torchbox.github.io/django-pattern-library/).

To build locally, view the project’s `CONTRIBUTING.md`.
170 changes: 170 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# Getting started

## Installation

django-pattern-library is available [on PyPI](https://pypi.org/project/django-pattern-library/). First install it in your Django project:

```sh
# With pip,
pip install django-pattern-library
# Alternatively, with Poetry,
poetry add --dev django-pattern-library
```

### Compatibility

We support:

- Django 2.2.x, 3.0.x, 3.1.x
- Python 3.6, 3.7, 3.8
- Django Templates only, no Jinja support

## Configuration

### Django settings

In your Django settings file, add `pattern_library` to `INSTALLED_APPS`:

```python
INSTALLED_APPS = [
# ...
"pattern_library",
# ...
]
```

Also add `pattern_library.loader_tags` to `OPTIONS["builtins"]` into the `TEMPLATES` setting:

```python
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
"builtins": [
"pattern_library.loader_tags"
],
},
},
]
```

### Pattern library settings

Still in Django settings, set the `PATTERN_LIBRARY` setting. Here is an example showing the defaults:

```python
PATTERN_LIBRARY = {
# Groups of templates for the pattern library navigation. The keys
# are the group titles and the values are lists of template name prefixes that will
# be searched to populate the groups.
"SECTIONS": (
("components", ["patterns/components"]),
("pages", ["patterns/pages"]),
),

# Configure which files to detect as templates.
"TEMPLATE_SUFFIX": ".html",

# Set which template components should be rendered inside of,
# so they may use page-level component dependencies like CSS.
"PATTERN_BASE_TEMPLATE_NAME": "patterns/base.html",

# Any template in BASE_TEMPLATE_NAMES or any template that extends a template in
# BASE_TEMPLATE_NAMES is a "page" and will be rendered as-is without being wrapped.
"BASE_TEMPLATE_NAMES": ["patterns/base_page.html"],
}
```

Note the templates in your `PATTERN_LIBRARY` settings must be available to [template loaders](https://docs.djangoproject.com/en/3.1/ref/templates/api/#loader-types).

### URLs

Include `pattern_library.urls` in your `urlpatterns`. Here is an example `urls.py`:

```python
from django.apps import apps
from django.urls import include, path

urlpatterns = [
# … Your URLs
]

if apps.is_installed("pattern_library"):
urlpatterns += [
path("pattern-library/", include("pattern_library.urls")),
]
```

!!! warning "Security"

This package isn’t intended for production usage, and hasn’t received extensive security scrutiny.

It is **highly recommended** to only enable this package in testing environments, for a restricted, trusted audience. One way to do this is to only expose its URLs if `apps.is_installed("pattern_library")`, as demonstrated above, and only have the app installed in environment-specific settings.

---

Alright, now that we got this far, we can navigate to `http://localhost:8000/pattern-library/` to see our pattern library! But if we tried to do this now, we would likely get a `PatternLibraryEmpty` error – this is expected, as we haven’t added any patterns yet.

![Screenshot of the PatternLibraryEmpty error message from Django](images/getting-started/PatternLibraryEmpty.png)

Now let’s look at adding our first template!

## First pattern

Now we’ve done all of the configuration – let’s create a UI component. We’ll use `quote-block` as an example, and place it at `patterns/components/quote_block/quote_block.html` inside one of our Django apps:

```html
<blockquote class="quote-block block--spacing">
<div class="quote-block__text">
<p class="quote-block__quote">{{ quote }}</p>
{% if attribution %}
<p class="quote-block__attribution">{{ attribution }}</p>
{% endif %}
</div>
</blockquote>
```

### Base template

We additionally need to customize a base template, so the standalone component can be rendered within a page with CSS. This is what the `PATTERN_BASE_TEMPLATE_NAME` setting is for. As a separate template in `patterns/base.html`:

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Base</title>
</head>
<body>
{% block content %}
{# pattern_library_rendered_pattern is where the pattern library will inject the rendered pattern. #}
{{ pattern_library_rendered_pattern }}
{% endblock %}
</body>
</html>
```

`quote_block` should now appear in the pattern library UI menu! But the template doesn’t display anything – we additionally need to provide it with test data.

### Component data

We can provide context and tags overrides for our new component by creating a `quote_block.yaml` YAML file alongside the HTML, at `patterns/components/quote_block/quote_block.yaml` in our example.

```yaml
context:
quote: What is love?
attribution: Haddaway
```
And that’s it! Our `quote_block` should finally appear in the pattern library, along with its rendering with this mock data.

![Screenshot of the quote_block template](images/getting-started/getting-started-complete.png)
23 changes: 23 additions & 0 deletions docs/guides/customizing-template-rendering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Customizing template rendering

## Customizing the patterns’ surroundings

All patterns that are not pages are rendered within a base page template. The pattern library will render patterns inside the `content` block, which you can tweak to change how patterns are displayed.

You can for example add a theme wrapper around the components:

```html
{% block content %}
{% if pattern_library_rendered_pattern %}
<div class="pattern-library bg bg--light">
{{ pattern_library_rendered_pattern }}
</div>
{% endif %}
{% endblock %}
```

`pattern_library_rendered_pattern` can also be used to do other modifications on the page for the pattern library only, for example adding an extra class to `<body>`:

```html
<body class="{% block body_class %}{% endblock %}{% if pattern_library_rendered_pattern %} pattern-library-template{% endif %}">
```
Loading

0 comments on commit 453be36

Please sign in to comment.