Skip to content

fix(a11y): let the tier button group wrap when the press adds auto - #161

Merged
guarzo merged 1 commit into
mainfrom
design-sweep/2026-08-06b-10
Aug 6, 2026
Merged

fix(a11y): let the tier button group wrap when the press adds auto#161
guarzo merged 1 commit into
mainfrom
design-sweep/2026-08-06b-10

Conversation

@guarzo

@guarzo guarzo commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Round ten of an unattended design sweep, and the last one it ran. One sentence: the press that pins an account's tier no longer pushes the control that undoes the pin off the edge of the drawer.

Based on main, independent of #160, the only other PR from this run still open. Merge in either order — #160 is copy and a className, this is globals.css and one spec, and they do not touch the same lines.

The finding

.btn-group (globals.css:2094) was display: inline-flex; gap: 2px with no flex-wrap, so it could not give width back when its contents grew. It has exactly one call site: admin/accounts/page.tsx:902, the tier control group inside a roster row's drawer.

Pressing a tier mounts the auto button beside the three tier buttons (page.tsx:968, under r.tierLocked). Measured at 320px on a seeded roster, Member 00's drawer:

before the press after
.btn-group width 251.30px 282.92px
.btn-group right edge 280.30px 311.92px
.drawer panel right edge 291px 291px

So 20.92px of the auto button sat outside the panel.

The cost it removes. An admin on a phone who pinned a tier by accident has to scroll the accounts table sideways to reach the undo. Accidental is the realistic case, not a contrived one: on an auto-tiered account r.tierLocked is false, so the tier button carrying aria-pressed="true" is fully live (page.tsx:959 disables it only once locked) while globals.css:2002-2020 paints it with --hull-hi and a leading — the same treatment the filter chips above use to mean you are already here, this does nothing. Pressing it takes that account out of the membership sync's reach for good.

This is the other half of #160, which ships the sentence telling the admin to "Press auto to unpin." Naming a control the layout then pushes off-panel is worse than not naming it.

The fix

.btn-group {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  row-gap: var(--s-1);
}

Post-fix the group is 264.53 × 60px — two rows of 28px with 4px between them — and ends flush with the drawer's control column instead of 20.9px past it.

Row-gap is 4px rather than the 2px column gap, deliberately. The comment at globals.css:2099-2102 says the 2px exists so adjacent tier buttons are "not a single smear". That reasoning does not transfer across the axis: buttons in a row share one 28px edge, but two wrapped rows meet along a whole button width — 73.17px for Testers, similar for the others — where the same 2px is a longer and more visible seam, not a smaller one. The cost of 4px is one gap in a drawer that already grows to fit.

The spec

One test, e2e/admin.spec.ts:1078, in the narrow-screen operability block. Verified to fail with only the CSS reverted:

✘ e2e/admin.spec.ts:1078 › accounts at 320px: the tier group stays in the drawer when the press adds auto

  Error: pinning a tier does not push the group past where the drawer's controls already ended
  expect(received).toBeLessThanOrEqual(expected)
  Expected: <= 294.03125
  Received:    311.921875

The bound is the control column measured before the press, not the drawer panel and not the column measured after. Both alternatives were ruled out by measurement rather than by argument:

  • Not the panel. .drawer__controls is 264.53px against a 262px panel with nothing pressed at all. Probing each child in turn, hiding the Note group drops the column to exactly 262 and hiding anything else leaves it at 264.53 — so the note field's own intrinsic minimum already overflows the panel by 2.53px whenever the drawer is open. A panel-relative assertion would be pinning that, not this.
  • Not the column after the press. The first draft asserted groupRight <= drawer__controls.right and passed with the fix reverted, 311.92 vs 311.92 — the tier group is a stretch item in that column, so an unwrapped group widens .note-form and every sibling to match itself. That draft was discarded, and it is recorded in the spec's docblock so the next person does not rewrite it.

The test guards on the auto button being visible before measuring, so a press that silently fails to land cannot make it vacuous.

The existing 1440px alignment spec (admin.spec.ts:939, which takes .btn-group's bounding box) still passes; at 1440 the group is nowhere near its wrap point.

What this round did not do

  • The 2.53px note-field overflow of the drawer panel, found while establishing the bound above. Pre-existing, different cause, and after this fix the tier group is flush with that column rather than past it — the residual is the note field alone. Named so a later sweep does not rediscover it as new.
  • The 768px re-wrap of Note and History in .drawer__controls. Same missing flex-wrap is the suspected cause and this fix plausibly relieves it, but it was not measured this round, so no claim is made.

Gates

Run on this branch's tip in the worktree by the run lead, not quoted from the implementing agent:

  • npx tsc --noEmit — exit 0, no output
  • npx eslint . — exit 0, no output
  • npx prettier --check . — "All matched files use Prettier code style!"
  • npm test77 files, 1145 tests passed
  • npx playwright test238 passed, 0 failed. 237 baseline plus exactly the one spec added.

tsconfig.json and AGENTS.md were not rewritten this round.

Not run on this branch: docker build . and scripts/check-node-version.sh — environment-bound and slow. CI runs both on this PR. Treat them as unchecked until it does.

Summary by CodeRabbit

  • Bug Fixes

    • Improved responsive control layouts so button groups wrap cleanly when space is limited.
    • Increased spacing between wrapped rows for better readability on narrow screens.
    • Fixed a mobile drawer layout issue when selecting a manual tier, preventing controls from expanding beyond the available width.
  • Tests

    • Added regression coverage for the 320px mobile layout.

Pressing a tier mounts the `auto` button beside the three tier buttons, and
`.btn-group` was `inline-flex` with no `flex-wrap`, so it could not give the
width back. Measured at 320px on a seeded roster: the group goes 251.3px ->
282.9px inside a 262px drawer panel. So the press that pins an account's tier
is the same press that pushes `auto` — the control that UNDOES the pin — past
the edge of the panel it lives in, leaving an admin who pinned a tier by
accident to scroll the accounts table sideways to reach the undo.

Row-gap is 4px rather than the 2px column gap: two wrapped rows meet along a
whole button width instead of along one 28px edge, where 2px reads as the seam
the existing gap exists to prevent.

The spec bounds the group by the drawer's control column as it stood before
the press. The panel itself is the wrong bound — the note field's intrinsic
minimum already puts that column at 264.5px against a 262px panel with nothing
pressed — and the column measured after the press is circular, since an
unwrapped group stretches its own siblings to match it.
@guarzo

guarzo commented Aug 6, 2026

Copy link
Copy Markdown
Owner Author

This is the closing report for the unattended design sweep run of 2026-08-06 (design-sweep/2026-08-06b-*). Ten rounds, nine pull requests.

The PRs, and the order they merge

No order is required. Every PR in this run is based on main and was opened standalone — this run did not use a stack, so there is no bottom-up merge constraint and no squash hazard. That is a deviation from the skill's default shape, taken because rounds cut on shared cause landed on disjoint files and a stack's cascade cost was not worth buying.

Round PR State
1 #148 — shared-component consistency merged
2 #149 — stop the 28px hit-target grade escaping the admin table rows merged
3 #151 — resume from the row just paid merged
4 #154 — arm grant the way its own opposite is armed merged
5 #155 — open the date column newest-first merged
6 #158 — pin the notes Save control to the standalone hit target merged
7 #159 — let the crew table scroll in its own region merged
8 #160 — say that a manual tier set pins the account open
9 no PR; finding retired
10 #161 — let the tier button group wrap when the press adds auto open

#150, #152, #153 and #156 merged during the same window and are not this run's work — different branches, unrelated changes.

What stopped the run

Convergence, not the round cap. The highest-ranked remaining finding cannot produce a concrete sentence naming who is harmed and what it costs them — the stopping rule's first condition. What is left is three P3s on /admin/accounts, a 2.53px overflow, and two items above the loop's ceiling. The cap was never reached, so nothing here should be read as "it was still finding real work when the budget ran out."

Round 9 published a wrong diagnosis and it was corrected

The most important thing in this report. Round 9 attributed a drawer layout defect to ConfirmGroup's notice setting its group's width. That was wrong, and a PINNED docblock plus a paragraph of #160's body had already been written asserting it and recommending a max-width that fixes nothing.

Two controlled experiments falsified it: hiding the notice after the press changes nothing, and pressing a tier on an already-locked row (where the notice is the only thing that changes) leaves the geometry byte-identical. The real causes were the tier badge's lock glyph widening a table column, and the auto button inside a group that cannot wrap.

Both artifacts were corrected in place — commit 5ba85c7 and a rewritten paragraph pushed to #160 — and round 9 was retired without a commit rather than shipping a fix aimed at the wrong cause. Round 10 is the correct fix for the half of it that was real.

What was skipped, and why

Above the loop's ceiling — these need a human:

  • The four cell-level actions redirect(), which closes every open drawer. Both reviewers found it independently and the critique says explicitly that it needs a human, not a sweep round. The fix is structural: it needs shape, which is gated behind a brief someone has to approve.
  • The aria-busy pulse dot widens the pressed button (73.17 → 91.06px, measured). Every available fix is a design decision, not a class change: reserving space on .btn widens every button in the app permanently; reserving it on .btn-group .btn adds ~54px to a group that is already tight at 320px; taking it out of flow overlaps the label on .btn--micro. It is documented app-wide behaviour and wants its own decision.

Vetoed by the direction ledger:

  • .st--ok inheriting --ink-dim — fixing it would reverse round 1. The ledger refuses a command that undoes one already applied in the same run.

On the settled list, deliberately not re-opened:

  • The Tokens badge wording, and edits to docs/settled-design-decisions.md.

Below the floor, or measured but not worth a round:

  • Three P3s on /admin/accounts: auto rendering as a fourth chip in the tier group; grant/revoke carrying no describedBy cost statement while the milder unlink does; ·no main setting the middot against the word.
  • The drawer's audit log link grade, and dead .log td.num > .stack CSS.
  • .pool-items on the payout detail page has the same latent min-width floor round 7 fixed in the accounts drawer. Not fixed because nobody has measured whether an item manifest ever exceeds the page column, so there is no evidence it currently bites. This is the one skip most likely to be rediscovered as a new finding later — it is a known gap, not a resolved item.
  • The 2.53px note-field overflow of the drawer panel, found while establishing round 10's bound.
  • The 768px re-wrap of Note and History. Round 10 plausibly relieves it; it was not measured, so no claim is made.

What the automated reviewer said, and why it mostly said nothing

CodeRabbit reviewed three of the nine PRs:

#151, #154, #155, #158, #159 and #160 have zero reviews.

The cause is rate limiting, not configuration. .coderabbit.yaml:159 correctly carries base_branches: ["design-sweep/.*"], and in any case that entry was not load-bearing this run — every PR is based on main, where automatic review fires by default. Explicit @coderabbitai review comments on #154, #155 and #158 each returned "Review rate limited."

So six of the nine PRs are unreviewed by anything but this run's own gates, including #160, which is still open. That is the single largest caveat on the whole run, and it is worth more than the sum of the skips above: a silent reviewer reads exactly like a reviewer that found nothing.

Gates

Every round ran npx tsc --noEmit, npx eslint ., npx prettier --check ., npm test and npx playwright test, quoted per PR body. Round 10's were re-run by the run lead rather than quoted from the implementing agent: tsc exit 0, eslint exit 0, prettier "All matched files use Prettier code style!", vitest 77 files / 1145 tests, Playwright 238 passed / 0 failed, exit 0, tree clean afterwards.

next build was never run locally on any branch, and was not listed as a skip in the first version of this report — a gap in the preflight gate enumeration. CI runs it as its own job. On #161 that job failed on a GitHub Actions infrastructure error ("Failed to resolve action download info: Internal Server Error / Service Unavailable") at the Prepare all required actions step, before any project code ran; it was re-run and passed, along with every other job (Next build, Typecheck, lint & format, Docker image, E2E tests, Unit tests — all success).

Also not run on any branch: docker build . and scripts/check-node-version.sh — environment-bound and slow. CI runs both.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b0fed37a-6b80-4942-9741-cd00c54744fc

📥 Commits

Reviewing files that changed from the base of the PR and between c99c942 and 03868e5.

📒 Files selected for processing (2)
  • e2e/admin.spec.ts
  • src/app/globals.css

📝 Walkthrough

Walkthrough

The change makes .btn-group wrap controls on narrow layouts and adds a 320px Playwright regression test for manual tier selection in the admin drawer.

Changes

Responsive tier controls

Layer / File(s) Summary
Wrap tier controls and verify narrow layout
src/app/globals.css, e2e/admin.spec.ts
At src/app/globals.css:2094-2106, .btn-group wraps controls and adds row spacing. At e2e/admin.spec.ts:1059-1123, the test selects Friends for Member 00 and verifies that the four-button group stays within its original column width.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • guarzo/authGD#38: Both changes update admin responsiveness in e2e/admin.spec.ts and src/app/globals.css.
  • guarzo/authGD#72: Both changes cover 320px drawer control wrapping.
  • guarzo/authGD#82: Both changes update admin drawer control layout and end-to-end coverage.

Poem

Narrow controls meet their space,
Rows now wrap with measured grace.
A manual tier adds one more,
Yet stays inside the drawer’s door.
At 320px, the test holds true.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description explains the change, rationale, verification results, skipped checks, and known out-of-scope findings, but it does not use the template headings.
Title check ✅ Passed The title follows the conventional-commit format and clearly states the user-visible effect: the tier button group can wrap after adding auto.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@guarzo, noted.

The sweep stopped on convergence, not on the round cap. The open PRs #160 and #161 are standalone changes based on main. They have no merge-order dependency.

I will not re-raise the retired Round 9 ConfirmGroup diagnosis. The measured 2.53px note-field overflow is pre-existing and outside #161. The .pool-items min-width risk remains an unmeasured known gap.

The rate-limit caveat is also recorded. Seven PRs in this run did not receive an automated review.


✏️ Learnings added
Learnt from: guarzo
URL: https://github.com/guarzo/authGD/pull/161

Timestamp: 2026-08-06T15:10:19.925Z
Learning: For the 2026-08-06b design sweep in `guarzo/authGD`, Round 9's diagnosis that `ConfirmGroup` notice content caused the admin accounts drawer width defect was falsified and retired. Do not recommend the previously proposed `max-width` fix for `ConfirmGroup` based on that diagnosis.

Learnt from: guarzo
URL: https://github.com/guarzo/authGD/pull/161

Timestamp: 2026-08-06T15:10:19.925Z
Learning: In `guarzo/authGD`, the admin accounts drawer has a measured pre-existing 2.53px panel overflow caused by the note field's intrinsic minimum width. This issue is separate from PR `#161`, which fixes the tier `.btn-group` overflow when the `auto` button appears.

Learnt from: guarzo
URL: https://github.com/guarzo/authGD/pull/161

Timestamp: 2026-08-06T15:10:19.925Z
Learning: In `guarzo/authGD`, `.pool-items` on the payout detail page has a known latent `min-width` risk similar to the accounts drawer issue fixed in design-sweep Round 7. It was not changed because no measurement shows that an item manifest currently overflows its page column.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@guarzo, recorded.

PRs #160 and #161 are independent branches from main. They can merge in either order.

Round 9’s ConfirmGroup diagnosis remains retired. I will not reintroduce that proposed max-width change.

The missing reviews on #151, #154, #155, #158, #159, and #160 resulted from rate limiting. They do not indicate that automated review found no defects.

The initial next build failure on #161 was GitHub Actions infrastructure failure at action preparation. It did not execute project code.

🐇


✏️ Learnings added
Learnt from: guarzo
URL: https://github.com/guarzo/authGD/pull/161

Timestamp: 2026-08-06T17:21:15.522Z
Learning: For the 2026-08-06b design sweep in `guarzo/authGD`, pull requests `#160` and `#161` are standalone branches based on `main`, modify disjoint areas, and have no required merge order.

Learnt from: guarzo
URL: https://github.com/guarzo/authGD/pull/161

Timestamp: 2026-08-06T17:21:15.522Z
Learning: For the 2026-08-06b design sweep in `guarzo/authGD`, CodeRabbit did not review pull requests `#151`, `#154`, `#155`, `#158`, `#159`, and `#160` because of review rate limiting. The absence of a review does not indicate that those pull requests have no defects.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

@guarzo
guarzo enabled auto-merge (squash) August 6, 2026 17:25
@guarzo
guarzo merged commit 55d2a7d into main Aug 6, 2026
11 of 12 checks passed
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@guarzo, recorded.

The sweep stopped because the remaining findings did not meet the harm-and-cost threshold. It did not stop because of the round limit.

I will treat the four redirect() actions as a structural change that requires an approved shape brief. I will also treat the aria-busy width increase as an app-wide design decision, not as a local CSS defect.

For #161, the initial Next build failure occurred before project code ran. The re-run passed, and all listed CI jobs passed.

🐇


✏️ Learnings added
Learnt from: guarzo
URL: https://github.com/guarzo/authGD/pull/161

Timestamp: 2026-08-06T17:27:32.317Z
Learning: In `guarzo/authGD`, the four cell-level `redirect()` actions that close open drawers require a structural change gated by an approved `shape` brief. Do not propose this as an unattended design-sweep CSS or local-component fix.

Learnt from: guarzo
URL: https://github.com/guarzo/authGD/pull/161

Timestamp: 2026-08-06T17:27:32.317Z
Learning: In `guarzo/authGD`, the `aria-busy` pulse widens a pressed button from 73.17px to 91.06px. The available remedies have app-wide layout or label-overlap tradeoffs, so this behavior requires a human design decision rather than an unattended design-sweep fix.

Learnt from: guarzo
URL: https://github.com/guarzo/authGD/pull/161

Timestamp: 2026-08-06T17:27:32.317Z
Learning: For `guarzo/authGD` PR `#161`, the initial GitHub Actions `Next build` failure was an infrastructure error during action preparation (`Failed to resolve action download info: Internal Server Error / Service Unavailable`) before project code ran. A re-run passed, along with the `Next build`, `Typecheck, lint & format`, `Docker image`, `E2E tests`, and `Unit tests` jobs.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant