Skip to main content

Use HTML tags to include HTML template components.

Project description

plain.elements

Build reusable HTML components using a tag-based syntax.

Overview

Elements give you a component-like syntax for HTML templates. Instead of using Jinja {% include %} or macros, you write components as .html files and use them with capitalized HTML tags like <Button> or <Card>.

To create an element, add a template in templates/elements/. The filename becomes the tag name.

<!-- templates/elements/Button.html -->
<button type="button" class="btn btn-primary">
    {{ children }}
</button>

To use elements in a template, add {% use_elements %} at the top. Then use your element with its capitalized tag name.

{% use_elements %}

<div class="actions">
    <Button>Click me</Button>
</div>

The output will be:

<div class="actions">
    <button type="button" class="btn btn-primary">
        Click me
    </button>
</div>

Passing attributes

You can pass attributes to elements in two ways: as strings or as Python expressions.

String attributes use standard HTML syntax:

{% use_elements %}

<Button type="submit">Save</Button>

Python expressions use single braces {}:

{% use_elements %}

<FormInput field={form.email} label="Email address" />

Inside the element template, attributes become template variables:

<!-- templates/elements/FormInput.html -->
<label for="{{ field.html_id }}">{{ label }}</label>
<input
    id="{{ field.html_id }}"
    type="{{ type|default('text') }}"
    name="{{ field.html_name }}"
    value="{{ field.value() or '' }}"
    {% if field.field.required %}required{% endif %}
/>

By default, Plain raises an error for undefined variables. Use the |default filter or is defined test for optional attributes.

Nested content with children

Content between opening and closing tags is available as the children variable.

<!-- templates/elements/Card.html -->
<div class="card">
    <div class="card-body">
        {{ children }}
    </div>
</div>
{% use_elements %}

<Card>
    <h2>Welcome</h2>
    <p>This content appears inside the card body.</p>
</Card>

Self-closing elements don't have children:

{% use_elements %}

<Divider />

Namespaced elements

You can organize elements into subdirectories. This is particularly useful for reusable packages or grouping related components.

Put the element template in a subdirectory of templates/elements/:

<!-- templates/elements/forms/Input.html -->
<input type="text" class="form-input" />

Use the dot-separated path as the tag name:

{% use_elements %}

<forms.Input />

FAQs

Can I nest the same element inside itself?

No. Elements cannot be nested inside themselves to prevent infinite recursion. If you need recursive structures, split them into separate element types.

Why use capitalized tag names?

Capitalized names like <Button> distinguish your elements from built-in HTML tags like <button>. This prevents conflicts and makes it clear which tags are custom components.

How does this compare to Jinja macros?

Elements are simpler for component-style usage. Macros require import statements and use function-call syntax. Elements look like HTML and feel more natural when building UIs. Use macros when you need complex logic or multiple return values.

Can I use elements without {% use_elements %}?

No. The {% use_elements %} tag enables element processing for that template. Without it, capitalized tags will be treated as literal text.

Installation

Install the plain.elements package:

uv add plain.elements

Add it to your INSTALLED_PACKAGES:

# app/settings.py
INSTALLED_PACKAGES = [
    # ...
    "plain.elements",
]

Create your first element template:

<!-- templates/elements/Alert.html -->
<div class="alert alert-{{ type|default('info') }}">
    {{ children }}
</div>

Use it in any template:

{% use_elements %}

<Alert type="success">
    Your changes have been saved.
</Alert>

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

plain_elements-0.11.2.tar.gz (7.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

plain_elements-0.11.2-py3-none-any.whl (9.1 kB view details)

Uploaded Python 3

File details

Details for the file plain_elements-0.11.2.tar.gz.

File metadata

  • Download URL: plain_elements-0.11.2.tar.gz
  • Upload date:
  • Size: 7.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for plain_elements-0.11.2.tar.gz
Algorithm Hash digest
SHA256 20f6c3e65d722dc91d62b979f0e2fd9d12a90d127ced47378819ff6b948db451
MD5 bd94302e4095762e2dd7300078a0a5be
BLAKE2b-256 ae06394306fd1be4e5dad1764197fa327b389601af6e2fba4f045a5db358f92c

See more details on using hashes here.

File details

Details for the file plain_elements-0.11.2-py3-none-any.whl.

File metadata

  • Download URL: plain_elements-0.11.2-py3-none-any.whl
  • Upload date:
  • Size: 9.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for plain_elements-0.11.2-py3-none-any.whl
Algorithm Hash digest
SHA256 bda86af9549bcbd8c96d1e77b1b72b5c6fa74fe4efedc658db7a57efa5beb401
MD5 abc12b82269e6d27dc6ca7188ebb782b
BLAKE2b-256 e55731d269717e801cd17d89afd06efd0fd0129e697bf0874aa12e0f4969b8e9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page