{# ── S-146 shared help / tooltip macros ─────────────────────────────────── Consolidates the per-field tooltip mechanism that S-123 originally bolted onto ``spec_row.html`` and ``studio/method_picker.html`` into a single, reusable Jinja macros file. Templates importing this file get consistent tooltip + step-help rendering across the wizard and the Studio — same ``title=`` semantics, same ``aria-describedby`` shape, same ``sr-only`` description span. Public macros: * ``tooltip(label, body, id_prefix="tip")`` — wraps ``label`` in a ```` carrying ``title=""`` and ``aria-describedby="..."``. A sibling ``sr-only`` ```` carries the same description for screen readers / focus-based assistive tech that don't surface ``title=``. The ``id_prefix`` argument keeps ids unique inside a render loop (e.g. one tooltip per column in the spec grid). * ``step_help(step_n, step_label, blurb, generators)`` — renders a ``
``/```` collapsible popover with a ``?`` trigger, a one-paragraph blurb, and a list of relevant generators (each ``(provider, method)`` tuple). Native ``
`` semantics give keyboard accessibility for free — ``summary`` is focusable, Enter / Space toggles, and ``Escape`` is wired at the rail level (closes the active popover without trapping focus). Why no JS: Both macros lean on native ``title=`` + ``
`` so they degrade cleanly when Alpine fails to mount. The keyboard-accessible Escape handler on the wizard rail is a single global listener; nothing in this file binds Alpine state, which keeps the macros usable from any template (including server-rendered HTMX fragments). #} {# Tiny helper macro — slugify a label for use as part of an id. Pure Jinja (no extension) so it works in the FastAPI runtime + test envs. #} {% macro _slug(value) -%} {{- (value | string | lower | replace(' ', '-') | replace('_', '-') | replace('.', '-'))[:32] -}} {%- endmacro %} {# ── tooltip ────────────────────────────────────────────────────────────── Renders the label as the visible text, with the body surfaced as the ``title`` attribute (for hover tooltips) and as a sibling sr-only span referenced by ``aria-describedby`` (for screen readers + focus-based UA tooltips). Args: label: visible text wrapped in the outer span. body: tooltip body — surfaced as ``title=`` and sr-only description. id_prefix: short string namespacing the generated id so multiple tooltips on the same page don't collide. Defaults to ``"tip"``. #} {% macro tooltip(label, body, id_prefix="tip") %} {%- set _tip_id = id_prefix ~ "-" ~ _slug(label) -%} {{ label }}{{ body }} {%- endmacro %} {# ── step_help ──────────────────────────────────────────────────────────── Renders a ``?`` trigger that expands a popover with a one-paragraph orientation + a list of relevant generators. Used on the wizard left rail so users can self-onboard without leaving the wizard. Args: step_n: 1-indexed step number (used in the stable ``data-help-step`` hook + the accessible aria-label). step_label: human label of the step (``"Connect"`` etc.) — surfaced in the aria-label so screen readers say "Help for step 3: Configure". blurb: one-paragraph orientation. HTML-escaped — caller passes raw text. generators: iterable of ``(provider, method)`` tuples. Empty list is OK; the macro renders only the blurb. #} {% macro step_help(step_n, step_label, blurb, generators) %}
?

{{ blurb }}

{% if generators %}

Relevant generators:

    {% for provider, method in generators %}
  • {{ provider }}.{{ method }}
  • {% endfor %}
{% endif %}
{%- endmacro %}