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.1.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.1-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: plain_elements-0.11.1.tar.gz
  • Upload date:
  • Size: 7.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","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.1.tar.gz
Algorithm Hash digest
SHA256 609e0af2f39554ab3d64334ee7477fea56e916f73d934e4336112205f7bae95d
MD5 2c644cbc069514adb22fe641110c2261
BLAKE2b-256 6faf708a1db1947c4dc39decade133f7df19ece394a00be85df73d7b2d7566df

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plain_elements-0.11.1-py3-none-any.whl
  • Upload date:
  • Size: 9.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c552014eeb41bdfe3bda26e236a6e0b838187989ad217aeffb56085a6bae28a6
MD5 16935fdb2b1bb61124dfe570426c2a2e
BLAKE2b-256 60ee49a553f894e08270a19d0b5ce8f7dbbac54972d18c9840762799b63c2f71

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