-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
77dc2f1
commit 453be36
Showing
18 changed files
with
507 additions
and
377 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 %}"> | ||
``` |
Oops, something went wrong.