Evidence — icon-only language trigger and a compact, positive menu (#406, PR #431)¶
Before/after for T-038: the navbar trigger loses its EN label and caret, and the menu stops rendering "not available" as a wall of disabled, greyed-out rows.
Before / after¶
| Before | After | |
|---|---|---|
| Trigger size | 88 × 19 px | 38 × 38 px |
| Trigger visible text | EN |
(none) |
Caret (dropdown-toggle) |
present, ::after inline-block |
absent, ::after: none |
| Trigger accessible name | title="Language" |
title="Language: English" |
| Menu width | 243 px | 144 px |
| Widest row | 241 px | 142 px |
Disabled / aria-disabled rows |
2 | 0 |
Bootstrap .active primary fill |
1 | 0 |
| Untranslated rows that are real links | 0 | 2 |
auto chips on machine translations |
0 | 1 |
| Per-row "Not yet translated" strings | 2 | 1 (the single footnote) |

The panel variant is captured too (01-before-panel-variant.png, 02-after-panel-variant.png) — the include renders two markups and this change touches both.
Against the issue's acceptance criteria¶
- Menu shows no disabled rows — 2 → 0. Español and Deutsch are now
<a>elements to the source page, so the existingzer0-langpreference handler (which matchesa[data-lang]) fires on the fallback path too; it could never fire on the oldspan.disabled. - Widest row ≤ 220px — 241px → 142px, measured with
getBoundingClientRect(). PR #431 originally shipped this criterion as a static assertion on the CSS rule with an explicit caveat that nothing had measured it in a browser. This closes that gap: the old menu genuinely exceeded the cap, the new one is 78px inside it. - Current language visually distinct without a primary fill — Bootstrap's
.dropdown-item.activecount is 1 → 0, replaced by.is-current(tint +bi-check2) whilearia-current="true"is retained. - Trigger is icon-only at all widths with an accessible name — the
ENspan and the caret are gone, the button is a 38px square, andaria-label/titleare the only accessible name — sotitlenow names the language being read rather than just "Language". - One footnote instead of per-row text — 2 per-row strings → 1 footnote
under a divider, referenced by each marked row via
aria-describedby.
How this was measured — and the caveat¶
No Jekyll site was served. The agent sandbox has no bundler and could not install one, so bundle exec jekyll build and the usual evidence-kit.mjs run against localhost:4000 were both impossible.
Instead the include is rendered with liquidjs against a fixture and styled by the real assets/css/main.scss compiled with Dart Sass plus the repo's vendored Bootstrap CSS and JS, then measured in real Chromium via Playwright. "Before" is origin/main, "after" is this branch — same harness, same browser, same fixture, same viewport.
Two honest limits:
- The fixture declares three target languages (
frtranslated,es/denot) where_config.ymlships only[fr]. That is deliberate — with a single, translated target none of the untranslated / chip / footnote states would render at all — but the absolute row counts above are the fixture's, not production's. - These are component crops, not full-page screenshots of the built site, so
they do not show the toggle in the real navbar cluster at every viewport.
test/visual/features/language-toggle.spec.jsruns against the real built site inTest Suite (Ruby 3.3)and remains the authoritative check.