{# Showing and hiding, through the two mechanisms the browser already has. `collapsible` and `accordion` are both `
`/``: open state, keyboard operation, the disclosure role and the announcement come from the element. Basecoat styles the element directly — `collapsible.css` declares no class — so these macros contribute structure and the closed vocabulary, not behaviour. `tooltip` is the same idea one level down: upstream draws it from a `[data-tooltip]` attribute and CSS `content()`, so there is no JavaScript and no second element to keep in sync. #} {% from "ui/attrs.html" import attrs %} {% from "ui/icon.html" import icon %} {# collapsible(summary, open) — one disclosure. A `
`: the open state needs no JS and no server state, and the browser gives the summary a button role plus Enter/Space. Basecoat animates `::details-content` and needs nothing from here. The chevron sits inside the summary and rotates from the parent's `[open]`, so marker and state have one source and cannot disagree. `list-none` and Basecoat's `::-webkit-details-marker` rule remove the browser's own triangle; without them a summary shows two markers. #} {% macro collapsible(summary, open=false, icon_name=none) -%}
{%- if icon_name %}{{ icon(icon_name, 16) }}{% endif %} {{ summary }} {# aria-hidden, because the summary already announces its own expanded state. A chevron that is also read aloud says "collapsed" twice. #}
{{ caller() }}
{%- endmacro %} {# accordion(multiple) — a stack of collapsibles, at most one open by default. Basecoat's JS closes the siblings: it finds `.accordion` and reads `:scope > details[open]`. `multiple` withholds that class, so a group that allows several open panels ships no JS behaviour rather than JS asked to do nothing. The children are `collapsible` calls. There is no `accordion_item`: a second macro rendering the same `
` would be a second place for the summary markup to drift. #} {% macro accordion(multiple=false, label=none) -%}
{{- caller() -}}
{%- endmacro %} {# tooltip(text, side, align) — a hint on hover and on keyboard focus. Upstream draws this from `[data-tooltip]` alone: the text is CSS `content: attr(data-tooltip)`, so there is no second element, no JavaScript and nothing to position. `side` and `align` are Basecoat's own closed attribute vocabulary. Two limits, both inherited from that mechanism: * The text is not in the accessibility tree; `content()` never is. A tooltip is a hint, never the only label. Give the control an `aria-label` when the tooltip is the only text it has. * It holds no markup. A tooltip that needs a heading is a popover. #} {% macro tooltip(text, side="top", align="center") -%} {{- caller() -}} {%- endmacro %}