---
target: implemented portfolio home page
total_score: 25
p0_count: 0
p1_count: 4
timestamp: 2026-07-07T16-54-50Z
slug: src-app-components-home
---
# Critique: Implemented portfolio home page (feature/home-portfolio-redesign)

Method: dual-agent (A: design review · B: detector/mechanical evidence). Target: src/app/components/home/* + src/app/home/page.tsx. Browser evidence skipped: deployed preview is auth-gated (next-auth redirect) and no browser automation in session.

## Design Health Score: 25/40 — Acceptable; solid skeleton, weak edges

| # | Heuristic | Score | Key Issue |
|---|-----------|:---:|-----------|
| 1 | Visibility of System Status | 3 | Folder create has no pending state; appears only after refetch |
| 2 | Match System / Real World | 4 | Enum→display translation, search in display language, honest "unfiled, not deleted" copy |
| 3 | User Control and Freedom | 2 | No undo; rename input discards silently on blur; menus lack Escape/outside-click close |
| 4 | Consistency and Standards | 2 | Three overlay vocabularies: Headless UI Dialog, window.confirm, bare details popovers |
| 5 | Error Prevention | 3 | Confirm exists; no duplicate-folder-name check; blur-cancel loses typed renames |
| 6 | Recognition Rather Than Recall | 3 | Folder ⋯ is opacity-0 hover-revealed — invisible on touch |
| 7 | Flexibility and Efficiency | 2 | No shortcuts, no bulk actions, no URL state, no Show-all |
| 8 | Aesthetic and Minimalist Design | 3 | Table crams folder into Updated cell |
| 9 | Error Recovery | 1 | Rollback message renders ONLY into sr-only region — sighted users see changes silently vanish; createMutation swallows errors |
| 10 | Help and Documentation | 2 | "Drag to reorder" hint hidden exactly where drag doesn't work (mobile) |

## Anti-Patterns Verdict

Not slop (A): no banned patterns, schema-honest, restrained register; failures are under-engineering (native confirm, raw details menus, hex drift), not AI over-decoration. Detector (B): zero findings on all four files — but regex mode is blind to the real issues below (false negatives, not false positives).

## Where A and B converge (highest-confidence findings)

- window.confirm at PortfolioHome.tsx:372 (A: register break; B: fact) — with B's irony: it's currently the page's most accessible dialog; the replacement must not regress focus handling.
- details/summary menus have no Esc/outside-click close, no menu semantics; two can be open at once (A heuristic 3/4; B verified no such JS exists).
- Invisible failure states: announceError feeds only the sr-only region (A P1; B verified role=status is sr-only).
- Touch gaps: folder ⋯ trigger invisible without hover (B fact; A recognition issue).

## B-only mechanical findings

- Contrast FAILs: placeholder gray-400 on white 2.54:1 (Tailwind default, never overridden); gray-500 counts on active rail bg 3.97:1 and hover 4.11:1. All 8 pills PASS (6.37–8.57). Gold star fill 1.77:1 but aria-hidden decorative with adjacent label + 17.33:1 stroke carrying state.
- Hit targets: FolderRail ⋯ 23×23 (FAIL 24px min); rail "New" ~20px tall (FAIL). CardMenu exactly 24. Star 25. Others pass.
- Table th lack scope="col"; "Your folders" header is a div not a heading; ✓/⚠ glyphs rely on aria-label-on-span/title (unreliable AT support); folder-name input has focus:outline-none with no focus state remaining.
- Hex drift: greys/blues inline (#c3ccd8 #e2e7ee #e4e9f1 #e9edf3 #f8fafc #eceefb) while brand palette exists in tailwind.config.
- Hygiene clean: no TODOs, no !important, one justified inline style, z-20 only, no unused imports.

## Priority Issues

- [P1] Replace window.confirm with inline two-step confirm in the folder menu panel ("Unfiles 12 portfolios · Remove / Cancel", red confirm, focus moves to it, Escape cancels). Chosen over dialog (over-weights a non-destructive action; modal-as-first-thought ban) and undo-toast (needs toast system + server restore API since folder recreation mints a new id).
- [P1] Make mutation failures visible: shared visible status + live region; createMutation needs error+pending handling.
- [P1] List-view CardMenu is clipped by the table's overflow-x-auto container — menu can be invisible with focus inside it. Portal/fixed/popover required.
- [P1] No bulk filing: organising 81 portfolios is one-at-a-time (~250+ clicks). Multi-select + "Move N to folder", and/or rail folders as drop targets.
- [P2] Standardise one popover primitive (Esc, outside-click, menu semantics, single-open) — heals heuristic 4.

## Persona Red Flags

Alex: no keyboard path to search/open; view/search/sort lost on refresh (no URL state); Show-more ×3 with no Show-all; cards re-sort under cursor on star.
Sam: details menus announce as disclosures not menus; clipped menu can contain focus while invisible; good: aria-pressed + live announcements on star, drag has menu fallback, focus-visible reveals hidden trigger.

## Minor

Hex drift → tokenise; "Folder order saved" announced before server confirms; star-teleport re-sort mid-scan; folder deserves own list-view column; NewPortfolioModal clashes (out of scope); no duplicate-name guard.

## Questions

- Rail folders as live drop targets — would drag-to-file make bulk-organise disappear?
- At 81 portfolios, is this a browse surface or a dispatcher (recents + starred + command palette first)?
