{% load lucide ui %} {% comment %} allauth passes `unlabeled=True` on the entrance forms (login, signup, reset) and already sets a placeholder on each of their fields ("Email address", "Password"), so dropping the visible label loses nothing on screen. The label is still emitted sr-only inside the wrapper: a placeholder is not a label, and it disappears the moment you start typing. Fields with an icon use daisyUI's icon-in-field layout, where the `input` class goes on the *wrapping label* and the input itself carries only `grow`. Putting `input` on both draws a box inside a box. {% endcomment %} {% for field in attrs.form.hidden_fields %}{{ field }}{% endfor %} {% for error in attrs.form.non_field_errors %}
{{ error }}
{% endfor %} {% comment %} `exclude` lets a page lay a field out itself — the login page puts "remember" on the button row. It is pinned to a real variable first, and that is not cosmetic: passing `attrs.exclude` straight into a filter on a page that never set it raises VariableDoesNotExist, which Django catches for the *main* variable of an expression but not for a filter *argument*. {% if %} then swallows it and reads the condition as false — silently dropping every field on every form that doesn't pass `exclude`. {% endcomment %} {% with exclude=attrs.exclude|default:"" %} {% for field in attrs.form.visible_fields %} {% if not field|excluded:exclude %}
{% if field.field.widget.input_type == "checkbox" %} {% else %} {% if not attrs.unlabeled and not field|is_otp %} {% endif %} {% with icon=field|field_icon %} {% if field|is_otp %} {% comment %} daisyUI's otp is one input overlaid on the boxes. Child order is load-bearing: it places each box with `nth-child`, which counts *every* child, not just the spans — so the input must come LAST. Put it first and all six boxes shift one stride right, the container matches :has(>span:nth-child(7)) and grows to seven strides, and the ::after active-box marker (invisible until focus) shows up in the gap as a phantom seventh box. For the same reason the sr-only label lives outside the container: another child would throw the count off again. The overlaid input carries daisyUI's own `pointer-events: none` (it exists so clicks land on the boxes, not a naked input) — which also means a tap/click on the boxes never reaches the input directly. A
{% endif %} {% endfor %} {% endwith %}