Skip to content

ui(accounts): account and registration row actions as icon buttons - #1608

Merged
cristim merged 3 commits into
LeanerCloud:mainfrom
IAmJSD:ui/sweep-admin-row-icons
Nov 3, 2026
Merged

cristim merged 3 commits into
LeanerCloud:mainfrom
IAmJSD:ui/sweep-admin-row-icons

Conversation

@IAmJSD

@IAmJSD IAmJSD commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

On Admin > Accounts & onboarding, each account row had four text buttons (Edit, Test, Overrides and a solid red Delete), and the registration rows stacked Approve, Reject and Delete onto two lines. On phones, where the accounts table scrolls sideways, the account buttons wrapped into a column and made each row several times taller than its content. This PR turns those actions into compact SVG icon buttons in one non-wrapping row, matching the Users, Groups and API key rows.

Part of the UI modernization sweep.

What changed

  • frontend/src/lib/row-icon-button.ts (new): a rowIconButton() helper that builds a btn btn-small icon-btn with an SVG icon, a title tooltip, an aria-label naming the row, and the short verb as sr-only text. Code and tests that find a row action by its text ("Delete", "Overrides") keep working.
  • frontend/src/icons.ts: adds the sliders and zap icons (Feather).
  • frontend/src/settings.ts, account rows: Edit (pencil), Test (zap), Overrides (sliders) and Delete (trash) are icon buttons inside a .row-actions wrapper. The aria-labels are unchanged. Delete keeps .btn-destructive as its hook but uses the subtle danger look (tinted, red icon, solid red only on hover), set slightly apart. The credentials Test reports "Testing...", "OK" or "Failed" through the hidden text and tooltip plus a short green/red tint, as the text button did through its label; the toasts are unchanged.
  • frontend/src/modules/registrations.ts, registration rows: Approve stays a small primary text button as the main action, now with an aria-label naming the registration. Reject (x-circle, warning tone) and Delete (trash) are icon buttons, all on one line.
  • frontend/src/styles/settings.css: the actions cell stays a table cell (a components.css rule made it a flex box, which pulled its bottom border out of line), plus the danger variant, the test-result tint and Approve's height matched to the icons. The icon buttons are the containing block for their sr-only text. Without that, on phones the hidden text sat at the scrolling table's far edge and widened the page (second commit).
  • Tests: a11y.test.ts checks that account row actions are icon buttons with a per-account name and tooltip; registrations.test.ts checks that Approve stays a text button and Reject/Delete are named icon buttons in one row; icons.test.ts covers the two new icons.

Why

Four text buttons per row, one of them solid red, made the danger action the loudest thing in every row and pushed the tables wider than needed. The Users, Groups and API key tables already use icon row actions, so Accounts now looks the same.

Screenshots

Before = main at 43dd618; after = this branch. Headless Chromium at 1440x900 (desktop) and 390x844 (phone) against a mocked API.

Before After
aws-accounts before aws-accounts after
Account rows: four text buttons with a solid red Delete. Edit, Test, Overrides and Delete icons in one row; Delete is the subtle danger style, set apart.
registrations before registrations after
Registrations: Approve and Reject on one line, Delete below. A small Approve button followed by Reject and Delete icons, on one line.
mobile-aws-accounts before mobile-aws-accounts after
Phone: the wrapped action buttons (scrolled out of view) make every account row very tall. Phone: rows are as tall as their content; the actions are a single icon row when scrolled into view.

Verification

Run on this branch's head 05f0ef65 (main 43dd618 + 3 commits), from frontend/:

  • npm run typecheck: pass. npm run lint: 0 errors (141 warnings, the same as main). npm run build: pass.
  • Jest: 175 suites; 4602 passed, 1 skipped (7 more than main, from the new cases in a11y.test.ts, registrations.test.ts and icons.test.ts).
  • Playwright (e2e-local.sh, the repo's full suite): 276 passed. The existing specs that click account and registration actions by name pass unchanged.

Notes for review

  • The sr-only verb inside each icon button is deliberate. It keeps text-based lookups (in settings.ts, jest and Playwright) working without changing the accessible names, which come from the existing aria-labels.
  • Reject uses the warning (amber) tone and Delete the danger (red) tone, like Revoke and Delete on the API key rows.
  • With only the icon, the Test progress is visible as the button's tint and tooltip, not as on-screen text. The toasts still announce the result.

Overlaps

Note for the UI owner

This changes UI code that @cristim owns. IAmJSD reviewed the before/after screenshots and asked for these PRs; any design point you disagree with can be a follow-up.

🤖 Generated with Claude Code

IAmJSD and others added 3 commits October 29, 2026 16:54
Accounts: Edit / Test / Overrides / Delete become compact SVG icon
buttons in one non-wrapping row, matching the Users rows (edit, zap,
sliders, trash). Each has a per-account aria-label (unchanged) and a
title tooltip; the short verb stays as sr-only text so code and tests
that find an action by its text still work. Delete keeps .btn-destructive
as its hook but uses the subtle danger look, set slightly apart, instead
of a solid red button. The Test check reports progress and its result
through the hidden text, tooltip and a short green/red tint, as the text
button did through its label.

Registrations: Approve stays a small primary text button (the main call
to action, now with an aria-label naming the registration); Reject and
Delete are icon buttons, and nothing stacks.

Adds the sliders and zap icons to icons.ts and a shared rowIconButton
helper; jest covers both rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow-up to the account row icon buttons. Their sr-only verb is
absolutely positioned and had no positioned ancestor, so on phones,
where the accounts table scrolls sideways, it sat at the table's far
edge and widened the page. Make the icon buttons its containing block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adapted for standalone: the table sweep PR adds clipboard-check to the
line above, and editing neighbouring lines of the same list made the two
PRs conflict. Same icons, same tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@IAmJSD
IAmJSD requested a review from cristim as a code owner October 29, 2026 21:50
@coderabbitai

coderabbitai Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 27 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
Commits

Reviewing files that changed from the base of the PR and between 43dd618 and 05f0ef6.

Files selected for processing: 8
  • frontend/src/__tests__/a11y.test.ts
  • frontend/src/__tests__/icons.test.ts
  • frontend/src/__tests__/registrations.test.ts
  • frontend/src/icons.ts
  • frontend/src/lib/row-icon-button.ts
  • frontend/src/modules/registrations.ts
  • frontend/src/settings.ts
  • frontend/src/styles/settings.css
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@cristim

cristim commented Nov 3, 2026

Copy link
Copy Markdown
Member

Merge gate record (burndown orchestrator)

Independent adversarial review (claude-opus-5-5)
#1608 @ 05f0ef6: NO CONFIRMED FINDINGS

  • Shared CSS: the new .row-actions rules apply wherever .row-actions is used; every use site checked (API keys, groups, users, accounts, registrations). No other screen has .btn-primary/.btn-destructive inside .row-actions, so the rules only reach accounts and registrations rows.
  • Specificity: .row-actions button.icon-btn.btn-destructive and its :hover outrank .btn-danger, .btn-destructive and :where(button):hover; every new token is defined in base.css.
  • Accessible names: every icon-only button has an aria-label naming its row with the visible verb inside it (label-in-name holds); the hidden verb text keeps existing e2e hasText: 'Overrides' selectors working.
  • Test-credentials state: progress goes to the hidden span and title, restore() clears data-test-result and re-enables the button; results are announced via toasts. No XSS path (textContent/setAttribute only).
  • Phone width: /admin/accounts at 390px no longer overflows (base overflowed by 10px).
  • Mutation probes: swapping the overrides icon fails the new a11y test; dropping btn-danger from Delete fails the registrations test; both pass after revert.

Local verification
Local verification on macOS @ 05f0ef6: PASS

  • Real local stack (backend + Postgres, fixture-labelled fake accounts, no purchases). npm test exit 1: 4600 passed / 2 failed / 1 skipped; the only failures are the 2 savings-history.test.ts tests failing on main since the DST change (pre-existing, fixed separately). npm run lint exit 0 (0 errors), npm run build exit 0.
  • Driven: Accounts page with 3 account rows and 2 pending registrations: all 16 icon buttons have an aria-label naming the row, a title, hidden text and an svg; no unnamed buttons. Hover/focus show a 2px outline. Buttons 28px on desktop, 44px on phone; the phone actions column is reachable by scrolling the table.
  • Screenshots at 1440x900 and 390x844 kept with the run evidence. Console: only the harness phone-context 401s seen on every PR.

Screenshots (1440x900 and 390x844) are kept with the local run evidence; not attached here.
CodeRabbit not run: the exact-SHA local verification and the Opus review above cover this SHA (repo CLAUDE.md review gate).

@cristim
cristim merged commit 9ab6a26 into LeanerCloud:main Nov 3, 2026
42 checks passed
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.

2 participants