{# mirrorwall/components.html — the component macros three applications share (spec §4). Every macro is keyword-driven with defaults that make sense for any application: nothing here has a required parameter shaped by one product's data model, which is the specific failure mode this extraction exists to avoid. Accessibility is not a later pass. Each macro emits the ARIA its pattern requires — a labelled table, a `role="status"` toast region, a `aria-modal` dialog with a heading it is labelled by — and the accessibility tests assert those attributes rather than trusting them. #} {% macro button(label, variant="default", type="button", name=None, value=None, disabled=False, aria_label=None, extra="") -%} {%- endmacro %} {% macro badge(label, tone="neutral", title=None) -%} {{ label }} {%- endmacro %} {% macro input(name, label, value="", type="text", hint=None, error=None, required=False, placeholder=None) -%} {% set field_id = "mw-field-" ~ name %}
{% if error %}

{{ error }}

{% elif hint %}

{{ hint }}

{% endif %}
{%- endmacro %} {% macro select(name, label, options, selected=None, hint=None) -%} {% set field_id = "mw-field-" ~ name %}
{% if hint %}

{{ hint }}

{% endif %}
{%- endmacro %} {% macro checkbox(name, label, checked=False, kind="checkbox") -%} {% set field_id = "mw-field-" ~ name %}
{%- endmacro %} {% macro switch(name, label, checked=False) -%} {% set field_id = "mw-field-" ~ name %}
{%- endmacro %} {% macro card(label, value, note=None) -%}
  • {{ label }} {{ value }} {% if note %}{{ note }}{% endif %}
  • {%- endmacro %} {% macro table(columns, rows, caption=None, table_id=None, sortable=False, complete=True, row_count=None) -%} {# `columns` is a sequence of mappings with a required `label` and an optional `numeric`; `rows` is a sequence of already-rendered cell values. The `numeric` key is tested with `is defined` rather than read directly, because the environment uses StrictUndefined and an omitted optional key is an ordinary column, not a mistake. `complete` is not decoration. UI standards §5: a client-side sort must apply to the whole dataset, so a table holding one page of a longer result set declares `complete=False` and the table module refuses to wire a sort control onto it. #}
    {% if caption %}{{ caption }}{% endif %} {% for column in columns %} {{ column.label }} {% endfor %} {% for row in rows %} {% for cell in row %} {{ cell }} {% endfor %} {% endfor %}
    {% if row_count is not none %}

    {{ row_count }} row{{ '' if row_count == 1 else 's' }}

    {% endif %} {%- endmacro %} {% macro empty_state(message, action_label=None, action_href=None) -%}

    {{ message }}

    {% if action_label and action_href %}

    {{ action_label }}

    {% endif %}
    {%- endmacro %} {% macro filter_bar(action="", method="get") -%} {%- endmacro %} {% macro kv_list(items) -%} {#- An item may carry an optional `href`, making its value an anchor. The value and label stay escaped text either way — never HTML — and the href goes through `safe_href`, which refuses javascript: and every other unsafe scheme; a refused href renders as the plain value. -#}
    {% for item in items %}
    {{ item.label }}
    {% set resolved_href = (item.href | safe_href) if (item.href is defined and item.href) else none %} {% if resolved_href is not none %}
    {{ item.value }}
    {% else %}
    {{ item.value }}
    {% endif %} {% endfor %}
    {%- endmacro %} {% macro json_viewer(payload, label="Details", open=False) -%} {{ label }}
    {{ payload | json_pretty }}
    {%- endmacro %} {% macro progress(value, maximum=100, label="Progress") -%} {{ value }} / {{ maximum }} {%- endmacro %} {% macro tabs(items, selected=None, label="Sections") -%}
    {% for item in items %} {% endfor %}
    {%- endmacro %} {% macro drawer(drawer_id, title, open=False) -%} {%- endmacro %} {% macro dialog(dialog_id, title) -%}

    {{ title }}

    {{ caller() }}
    {%- endmacro %} {% macro toast_region() -%}
    {%- endmacro %} {% macro tooltip(text, description) -%} {{ text }} {%- endmacro %} {% macro pagination(previous_href=None, next_href=None, summary=None) -%} {%- endmacro %} {% macro chart_container(chart_id, title, description) -%} {# The chart is decoration; the caller's table alternative carries the same figures, so a reader who cannot see the chart loses nothing (UI standards §5, §7). #}
    {{ title }}

    {{ description }}

    {{ caller() }}
    {%- endmacro %} {% macro telemetry_bar(stream_url="") -%} {% with telemetry_stream_url = stream_url %}{% include "mirrorwall/telemetry_bar.html" %}{% endwith %} {%- endmacro %}