{# Reusable UI macros adapted from vendored Penguin UI components. These are OUR adaptation layer; the byte-for-byte upstream sources live under assets/views/penguinui/. Tailwind sees the full literal class strings here (assets/css/app.css has @source "../views"), so every branch must spell its classes out in full — never build class names by concatenation. Usage: {% import "macros/ui.html" as ui %} {{ ui::button(label=t(key="save", lang=lang)) }} {# default primary #} {{ ui::button(label="Add", attrs='hx-post="/x"' | safe) }} {{ ui::button(label="Cancel", variant="outline-secondary", href="/back") }} {{ ui::button(label="Send", size="px-6 py-2.5 text-sm") }} {# keep a non-default size #} {{ ui::badge(label="Published", variant="success") }} Notes: - Macros can't see template context vars (e.g. `lang`); pass already-translated strings as `label`. - `attrs` is injected raw (caller must pass it through `| safe`); use it for htmx / name / value / @click / :disabled etc. For buttons whose attrs carry nested quotes (e.g. hx-on with toast(...)), keep them inline instead. - `pad` is the size (default Penguin "px-4 py-2"); override to preserve an existing size rather than normalizing it. - The button class strings are the **verbatim** Penguin variants from penguinui/buttons/{default,outline,ghost}-button.html (only `inline-flex items-center justify-center` is added so and w-full render correctly, and the upstream `text-onDanger`/`text-onSuccess`… token typos are fixed to our real `text-on-*` tokens). `variant` selects a Penguin variant: solid : primary (default) | secondary | danger | success | warning | info outline : outline-primary | outline-secondary | outline-alternate | outline-danger ghost : ghost-primary | ghost-secondary | ghost-danger #} {% macro button(label, variant="primary", type="button", href="", attrs="", extra="", icon="", size="px-4 py-2 text-sm") -%} {%- if variant == "secondary" -%}{% set cls = "border border-secondary bg-secondary text-on-secondary focus-visible:outline-secondary dark:border-secondary-dark dark:bg-secondary-dark dark:text-on-secondary-dark dark:focus-visible:outline-secondary-dark" -%} {%- elif variant == "danger" -%}{% set cls = "border border-danger bg-danger text-on-danger focus-visible:outline-danger dark:bg-danger dark:border-danger dark:text-on-danger dark:focus-visible:outline-danger" -%} {%- elif variant == "success" -%}{% set cls = "border border-success bg-success text-on-success focus-visible:outline-success dark:bg-success dark:border-success dark:text-on-success dark:focus-visible:outline-success" -%} {%- elif variant == "warning" -%}{% set cls = "border border-warning bg-warning text-on-warning focus-visible:outline-warning dark:bg-warning dark:border-warning dark:text-on-warning dark:focus-visible:outline-warning" -%} {%- elif variant == "info" -%}{% set cls = "border border-info bg-info text-on-info focus-visible:outline-info dark:bg-info dark:border-info dark:text-on-info dark:focus-visible:outline-info" -%} {%- elif variant == "outline-primary" -%}{% set cls = "border border-primary bg-transparent text-primary focus-visible:outline-primary dark:border-primary-dark dark:text-primary-dark dark:focus-visible:outline-primary-dark" -%} {%- elif variant == "outline-secondary" -%}{% set cls = "border border-secondary bg-transparent text-secondary focus-visible:outline-secondary dark:border-secondary-dark dark:text-secondary-dark dark:focus-visible:outline-secondary-dark" -%} {%- elif variant == "outline-alternate" -%}{% set cls = "border border-outline bg-transparent text-outline focus-visible:outline-outline dark:border-outline-dark dark:text-outline-dark dark:focus-visible:outline-outline-dark" -%} {%- elif variant == "outline-danger" -%}{% set cls = "border border-danger bg-transparent text-danger focus-visible:outline-danger dark:border-danger dark:text-danger dark:focus-visible:outline-danger" -%} {%- elif variant == "ghost-primary" -%}{% set cls = "bg-transparent text-primary focus-visible:outline-primary dark:text-primary-dark dark:focus-visible:outline-primary-dark" -%} {%- elif variant == "ghost-secondary" -%}{% set cls = "bg-transparent text-secondary focus-visible:outline-secondary dark:text-secondary-dark dark:focus-visible:outline-secondary-dark" -%} {%- elif variant == "ghost-danger" -%}{% set cls = "bg-transparent text-danger focus-visible:outline-danger dark:text-danger dark:focus-visible:outline-danger" -%} {%- else -%}{% set cls = "border border-primary bg-primary text-on-primary focus-visible:outline-primary dark:border-primary-dark dark:bg-primary-dark dark:text-on-primary-dark dark:focus-visible:outline-primary-dark" -%} {%- endif -%} {% if href %}{{ icon | safe }}{{ label }} {%- endmacro button %} {# Icon-only button (square). Penguin ghost treatment (bg-transparent, hover:opacity-75); pass the raw as `icon`, an accessible name via `aria_label`/`sr`, and any Alpine/htmx via `attrs` (raw). variant ∈ ghost-secondary (default) | ghost-primary | ghost-danger | ghost-alternate. #} {% macro icon_button(icon, variant="ghost-secondary", type="button", href="", attrs="", extra="", aria_label="", sr="", size="size-9") -%} {%- if variant == "ghost-primary" -%}{% set cls = "text-primary focus-visible:outline-primary dark:text-primary-dark dark:focus-visible:outline-primary-dark" -%} {%- elif variant == "ghost-danger" -%}{% set cls = "text-danger focus-visible:outline-danger dark:text-danger dark:focus-visible:outline-danger" -%} {%- elif variant == "ghost-alternate" -%}{% set cls = "text-outline focus-visible:outline-outline dark:text-outline-dark dark:focus-visible:outline-outline-dark" -%} {%- else -%}{% set cls = "text-secondary focus-visible:outline-secondary dark:text-secondary-dark dark:focus-visible:outline-secondary-dark" -%} {%- endif -%} {% if href %}{{ icon | safe }}{% if sr %}{{ sr }}{% endif %} {%- endmacro icon_button %} {# Compact danger alert (form/inline errors). Adapted from penguinui/alert/default-alert.html (danger variant), trimmed to a single line with the danger icon. #} {% macro alert_danger(message, extra="") -%} {%- endmacro alert_danger %} {# Soft-color badge. variant ∈ success | danger | warning | info | primary | neutral #} {% macro badge(label, variant="neutral") -%} {% if variant == "success" -%} {{ label }} {%- elif variant == "danger" -%} {{ label }} {%- elif variant == "warning" -%} {{ label }} {%- elif variant == "info" -%} {{ label }} {%- elif variant == "primary" -%} {{ label }} {%- else -%} {{ label }} {%- endif %} {%- endmacro badge %}