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.4.tar.gz (7.6 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.4-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: plain_elements-0.11.4.tar.gz
  • Upload date:
  • Size: 7.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.10 {"installer":{"name":"uv","version":"0.11.10","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.4.tar.gz
Algorithm Hash digest
SHA256 bedb4984d6a4bde44a31c33b3b2f4a426457bab2ff265478d0e8c1f24cd0af9a
MD5 73db23dc09241b8b8270c7d4796d70da
BLAKE2b-256 95b7cadfe6e2684c0481d8dacd33df8f4c644220689bf02857220d4718dcc032

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plain_elements-0.11.4-py3-none-any.whl
  • Upload date:
  • Size: 9.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.10 {"installer":{"name":"uv","version":"0.11.10","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.4-py3-none-any.whl
Algorithm Hash digest
SHA256 bd4f44738a6df97794cd4d20af500fc9a6ca5dd1d999cae988349e771f922567
MD5 63dc6ea84bc2c4378134207a19ed3baa
BLAKE2b-256 0d3ae043786d748407f196046e3b1e8525c5d08318414a6b9ac1477b96206455

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