Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/agent-memory/ux-designer/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@
- Cannot `gh pr review --request-changes` **or** `--approve` on your own PRs (GraphQL rejects both, not just request-changes) — post via `gh api repos/.../issues/{N}/comments` with an explicit "Verdict: APPROVED/CHANGES_REQUIRED" line in the body instead.
- `Intl.NumberFormat` enables thousands-grouping by default; `toFixed()`/manual string-building never did. When a PR swaps a `toFixed()` call for a locale formatter, script-verify the _old vs new_ output isn't just per-locale-correct but also identical for large values (≥1000) — grouping separators are an easy-to-miss 3rd English-output regression beyond whatever the PR explicitly discloses. See PR #1845 in [pr-review-findings.md](pr-review-findings.md).
- `formatDateForAria`-style aria-labels that interpolate localized weekday/month into a hardcoded English sentence order (`"{weekday}, {month} {day}, {year}"`) render grammatically odd in German (`"Dienstag, Februar 24, 2026"` vs correct `"Dienstag, 24. Februar 2026"`) — this is an accepted, deferred, non-blocking gap across the app, not a new bug to flag each time.
- When a PR claims a Badge/shared-component consolidation is "zero visual delta," build a before/after table (padding/font-size/weight) per migrated component — the shared base class is usually extracted from only a subset of sources, so other migrated components can silently inherit a different size than they had. See PR #1848 in [pr-review-findings.md](pr-review-findings.md).
10 changes: 10 additions & 0 deletions .claude/agent-memory/ux-designer/pr-review-findings.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ Full remediation of 370 latent stylelint violations, plus wiring `stylelint` int

Verification method worth reusing: `awk '/^\+/ && !/^\+\+\+/' <diff> | grep -Ei '#[0-9a-fA-F]{3,6}|rgba?\('` and equivalent greps for `z-index:\s*[0-9]`/`font-weight:\s*[0-9]` against the full diff (excluding `tokens.css`) — fast way to confirm zero hardcoded-value regressions slipped past stylelint across a large multi-file remediation PR, rather than spot-checking a handful of files.

## PR #1848 — Modal focus trap + Badge consolidation (Issue #1816) (APPROVED via --comment, Medium finding non-blocking)

Reviewed `Modal.tsx`'s new Tab-cycling focus trap (`getFocusableElements()` re-queried per keypress against `contentRef.current`, which wraps header+body+footer) across all 18 consumers, plus 4 components (`BudgetHealthIndicator`, `CriticalPathCard`, `UpcomingMilestonesCard`, `SubsidyPipelineCard`) migrated from hand-rolled badge spans to shared `Badge` + `BadgeVariantMap`. Zero/single/mid-list focusable-element edge cases all correctly handled and test-covered (6 new `Modal.test.tsx` cases). `KeyboardShortcutsHelp` correctly inherits portal/Escape/focus-trap/dialog semantics by switching to `<Modal>`.

**RECURRING PATTERN TO CHECK: "Badge consolidation = zero visual delta" claims need script/table verification, not eyeballing.** When N pre-existing hand-rolled badge implementations get unified onto one shared `.badge` base class, each source component's own `padding`/`font-size`/`font-weight` gets silently overridden by whatever the *first* group of components (the ones the base class was originally extracted from) happened to use — even though every value on both sides is already a valid design token. Build a before/after table (padding v/h, font-size, font-weight) for every migrated component, not just the ones the author explicitly compared. In PR #1848: `SubsidyPipelineCard` and `CriticalPathCard`/`UpcomingMilestonesCard` only drifted ±2px padding (harmless), but `BudgetHealthIndicator` dropped from 14px/semibold/12px-h-padding to 12px/medium/10px-h-padding — a real, visible size/weight downgrade on an important status badge, not disclosed in the PR description. No WCAG contrast issue (colors unchanged), so Medium/non-blocking, not Critical — but worth flagging explicitly rather than trusting a "ported verbatim" claim.

Also confirmed: dark mode routes correctly for all new Badge variant classes (checked every consumed token has a `[data-theme='dark']` override); `CriticalPathCard`'s div→span tag swap is a genuine no-op (both sides compute to `display: inline-flex`, div's default block was already being overridden); `BudgetHealthIndicator`'s `<span role="status"><Badge/></span>` wrapper correctly preserves live-region semantics on change without double-applying `role`/`aria-live`. Token-snap acceptable: `KeyboardShortcutsHelp`'s `td` padding 0.875rem(14px)→`var(--spacing-4)`(16px) — no 14px spacing token exists in `tokens.css` (only `--spacing-3`=12px/`--spacing-4`=16px), so rounding up to the nearest token is correct under a token-only system.

Informational, not blocking: migrating a component off its own local aria-label (e.g. `KeyboardShortcutsHelp`'s old `keyboardShortcuts.closeAriaLabel`) in favor of a shared component's built-in one (`common:aria.closeDialog`) orphans the old i18n key in both locale files — worth a follow-up i18n-orphan sweep, not a per-PR blocker.

## Process notes

- Cannot `--request-changes` on your own PRs — use `--comment` instead, and note this in the review body
Expand Down
Loading