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.0.tar.gz (7.3 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.0-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: plain_elements-0.11.0.tar.gz
  • Upload date:
  • Size: 7.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","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.0.tar.gz
Algorithm Hash digest
SHA256 2839dec24d962477fd9f9b9d1f34739527dd51644153b847ede227e21b52e5be
MD5 bed7e443205345f0e4971fa3ceafeff0
BLAKE2b-256 8ae4cf584a60c2af8333c52bcfe814db20563ccb6abee1cfbbe5a21b619e21e5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plain_elements-0.11.0-py3-none-any.whl
  • Upload date:
  • Size: 8.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a1a27f555d26a6b564d1211f9a9ad06918700265efd63d2546fcdf58aac0e91
MD5 b888ae7a92f4e03ab4355e7993135828
BLAKE2b-256 f9cc9885aa00b546b072580b1058c255d6713a910681a47594b50ff6dda0f943

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