Skip to contentWolf-Rayet

Decision records

ADR-0133 The grouped nine read their tiers

Accepted2026-09-24Phase 7

Completes the list ADR-0131 opened. Wires the nine grouped components it left, lands the check it deferred, and closes a gap in the proof app that made ADR-0132's proof movement mean something other than what it said.

#Context

ADR-0131 named eleven components whose stylesheets read none of the tokens the generator writes for them, wired button-group, and sequenced the rest one per unit because each is a record decision with an appearance attached. ADR-0132 wired page-header and supplied the method: where a component and its record disagree, the side that speaks the system's roles wins, and a record's own note outranks both.

Nine were left: empty-state, tooltip, link, pagination, modal, accordion, checkbox, meter and button. Measured before this record, eight read none of their tier and three (meter, accordion, button) read only the two motion names ADR-0125 wired.

Wiring them surfaced a second gap. apps/proof/app/layout.tsx imported the tier of every operational component and of none of the grouped ones, while its screens render page headers, button groups, tabs, buttons, meters, checkboxes and links. The proof fixtures are captured from that app, so in all ten proof scenes the page header's title read --wr-page-header-title-size and found nothing. ADR-0132's movement in scenes 67 and 74 was partly that: a title with no size, not a title at the size the system grants it. Storybook imported no token file at all.

#Decision

Each component reads its tier for every property the record gives a role to. Properties the record has no role for stay on the flat surface, and are listed below rather than invented. Where the component and the record disagreed, the record won, with two exceptions that are the record's to correct.

  • empty-state. Pad space-stack, gap space-stack-tight, radius radius-surface; subject in text-primary, reason in text-secondary, both at text-caption. The reason had been drawn in text-subtle, which the record's $textNote names as the failure this component exists to prevent. The props keep the header, description and action names the site's Atlassian structure uses; the record's subject and reason are what they draw.
  • tooltip. A raised surface in primary ink at text-caption, pad and gap space-inline-tight, radius radius-surface, in place of an inverse dark chip. The overlay shadow is kept so a raised surface still separates from the one under it.
  • link. Primary ink rather than the link hue. The stylesheet's own comment already held that the underline is the link's edge and colour is not, and the record agrees. Hover thickens by border-heavy; the focus ring is the tier's. Size stays inherited, because a link sits inside running text.
  • pagination. Target target-min, gap and pad space-inline, radius radius-control, figures in the mono family at text-caption; page numbers in text-primary, the ellipsis in text-secondary.
  • modal. Sheet surface-raised with the stacking tier's overlay shadow, radius radius-surface, pad space-stack, the lead in the display family at text-lead, support text in text-secondary at text-caption.
  • accordion. Header and expanded panel on surface-raised, hover and press on the surface roles, the label through the heading voice, the count in text-secondary, rules in border-subtle.
  • checkbox (.wr-choice, shared with the radio the register retired). Label, control fill, hover, press, target and focus ring from the tier.
  • meter. Label text-secondary, reading text-primary in the mono family, track surface-inset, and the three status fills and glyphs from status-positive-bold, status-caution-bold and status-critical-bold.
  • button. Height target-min, pad space-inline and gap space-inline-tight resolve to the pixels they replaced. The default fill moves from the translucent neutral to surface-raised with a border-subtle outline, the label to text-caption, primary to accent-bold and danger to status-critical-bold, both inked text-on-bold.

The two exceptions. checkbox keeps an 8px gap against its tier's space-inline-tight, 4px: the stylesheet measured 4px and recorded that the mark and its first letter read as one smudge, which is an observation the record never answered. link keeps an inherited size against its tier's text-caption. Both are the record's to change, not the stylesheet's to keep forever.

Every app that renders these components imports their tiers. The proof app gains the twelve grouped tiers, Storybook gains the whole token surface and a dependency on @wolf-rayet/tokens, and the docs list is complete.

The check ADR-0131 deferred lands, as pnpm tiers:check in the budget workflow and the battery. For every component with a selector in component.config.json it fails when the component's rules read none of its tier, and when they read a --wr-<component>-* name that neither the tier nor a stylesheet or inline style declares. Both failure modes were proved by mutation before it was committed.

#Consequences

34 unthemed scenes moved and darwin was re-recorded. No verdict changed: 75 of 75 unthemed and 188 of 188 themed PASS and FAIL lines are identical before and after, and the themed comparison is exact in all four themes against the new record. linux-x64 is stale by these values until one CI run supplies its receipts, and is transplanted from that run the way every earlier linux record was.

What still reads the flat surface, by component:

ComponentFlat names still read
empty-statefont-weight-semibold
tooltipline-small, shadow-overlay
linkpurple-bold (visited), text, text-subtle (the subtle variant)
paginationfont-weight-medium, line, neutral-subtle-hovered, selected, text-selected, text-disabled
modalfont-weight-semibold, text-danger
accordionline
checkboxborder, border-subtle, brand-bold, disabled, text-disabled, line, space-100
meterbrand-bold (the unclassified fill), line
buttonthe warning, discovery, link and selected appearances, the hover and press shades of the bold fills, disabled, the compact height, the icon circle, weight and line height

These are roles the records do not declare, not wiring left undone. The check's third clause, that a record-holding component reads no flat name at all, waits for the records to carry them.

Tooltip and popup still have no collision handling. With the example card no longer clipping, a tooltip centred on a trigger near the window's edge runs past it. That is its own record.

#Rejected

Hold each component to a separate unit, as ADR-0131 sequenced. The maintainer asked for the whole list in one pass. ADR-0131's objection was to eleven undiscussed visual changes under one re-record, and each change here is a separate commit with its decision stated above, so the part of the objection that mattered holds.

Rename the empty state's props to the record's parts. It would break every caller for words the reader never sees, and the Atlassian structure the site follows names them the way the component already does.

Invent tier roles for the flat residue. A role written to fit what a stylesheet draws describes it rather than constrains it, which is ADR-0131's second rejection.