The plan was delivered as wp-suite-implementation-spec.zip and lived only in Downloads, so every "read CLAUDE.md first" instruction in it pointed at a file the repo did not have. Bring it in unchanged: CLAUDE.md, IMPLEMENTATION.md, and docs/waves/wave-0 through wave-9 plus backlog.md. UX-REVIEW-2026-08-14.md is committed alongside it. It is the review that produced F1-F6, S1-S13 and the A/B/C assessments, and item IDs throughout the wave files cite it, so it belongs under version control rather than sitting untracked in the working tree. No application code changes here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.9 KiB
UX Review — Work Package Suite
Date: 2026-08-14 · Branch: users/directory-super-user · Scope: html/ — 6 pages, 4 stylesheets, ~11.9k lines
Full write-up with screenshots: https://claude.ai/code/artifact/09d89aa1-54b9-41db-9e09-e1fc8fb55852
Method. Two passes. A full read of the frontend, then the app run locally
(uvicorn server.app:app, throwaway SQLite DB) and driven in Chrome through the real
first-run flow: sign in → create project → SOP wizard → creator → directory → field view
at 390px. Section 1 below is browser-verified; section 2 is read from source.
Incidental find:
server/seed_demo.pyno longer authenticates, so it can't seed a running instance — every/api/route requires a session and the script sends none. It predates the commit that taught the smoke test to sign in.
1. Rendering defects (browser-verified, reproducible today)
No design decisions needed for any of these.
| # | Defect | Severity |
|---|---|---|
| F1 | Header project switcher is stale on every page. Hero, picker and create-user card show the active project; the app bar still reads "Select a project". Two sources of truth, global one loses. | High |
| F2 | App bar breaks at 390px — on Field View. Nav wraps to 3 rows and clips: "Sign out" cut in half, search truncated. This is the gloved-hands surface. | High |
| F3 | Logo/project-name collision in the SOP header. .header-left and the injected chrome fight for the same run of the bar. |
Medium |
| F4 | Comments drawer renders off-screen over the header in the standalone creator. | Medium |
| F5 | SOP wizard fields read as read-only — #f4f4f4 fill, #e0e0e0 border. Cause: the wizard redeclares its own tokens and never sees --cds-field: #ffffff. |
Medium |
| F6 | The creator is one ~4,700px form — 11 cards rendered at once, jump links standing in for structure. | Medium |
F1 and F2 are prerequisites for the proposed chrome work.
2. Structural findings (from source)
Costs users work
- Validation is
alert()-only, covering 3 of 10 wizard steps. 79 native dialogs app-wide, 43 in the creator.wp-creation-app.js:1144says "Subject and WP Type are required" without naming, highlighting or scrolling to the field — on a form ten cards deep.validateStepguards only steps 1, 5, 6 while the markup marks required fields throughout. - No autosave, no unsaved-work guard. The only
beforeunloadlistener is analytics dwell tracking (work-package-suite-app.js:326). - Nothing is linkable. No
pushStateanywhere. Tab switches, dashboard views and package selections change no URL — can't send someone a link to WP07; refresh loses your place. - No global nav on the two pages people live in. Drawer + app bar ship on
admin,field,users. The SOP wizard has its own header and no drawer; the creator has neither, plus a different brand treatment (mono wordmark vs. logo chip).
Costs consistency
- Four parallel token systems.
#0f62feis declared 4× (--cds-interactive-01,--primary,--accenttwice). Already caused a bug — see the comment atwork-package-suite-styles.css:336about.field-hintrendering unstyled. - Icon set is mixed emoji + dingbats (⤓ ⤒ 👁 ★ 📊 ⧉ 🕘 💬 ▤ ⚙ 🔒 ⚡ ⎙ ◔ ▦).
▤is used for two different things on the same page. - Four sample-data affordances under three names. One sits a click from live project data with no confirm and no undo.
Costs accessibility (and the field case)
- Hover-only tooltips carry load-bearing instructions. 15
.help-tipbadges,<span>s with notabindex— so the:focushalf of their CSS rule is dead code and there's no touch path. - SOP step rail not keyboard-reachable. All 10 steps are
<div onclick>; 12<div>+ 2<span>click handlers app-wide. - Zero
aria-liveregions. Both toast systems and every admin banner announce nothing.login.htmlgets this right withrole="alert"/role="status"; the pattern never spread. - Helper text at ~2.9:1 (
--text-dim: #8d8d8dat 12px).console.css:85-87already diagnosed and fixed this; the other two sheets didn't follow. - Wizard removes the focus ring —
outline: noneplus a pale 3px glow (work-package-suite-styles.css:322-328).
3. Assessment of the proposed change list
Strong work — nearly every item maps to something verifiable, and two rank above anything in this review's own findings. 9 endorsed, 7 need adjustment, 6 gaps.
Endorse as proposed
| ID | Item | Note |
|---|---|---|
| A1 | Guarded status transitions | Best item on the list. But: Issue (Hold) is a branch from several states, and there's a deliberate logged-override path for predecessors (wp-creation-app.js:1962-1972). "One legal next action" is too narrow — model as primary-next + audited override. |
| A2 | De-duplicate constraint warning | Triplication confirmed. Caveat: the top banner is the only one visible without scrolling, so the tab count badge must carry that weight. |
| A3 | Fields that look editable | Confirmed (F5). Pair with token consolidation or it drifts back. |
| A4 | Vertical stepper + progress | Also retires the orphaned "1 / 10" counter. Make the steps real <button>s while rebuilding. |
| A5 | One button system, no green/blue mix | Real: green Save & View + green SOP Complete vs blue elsewhere. Scope "sentence case" to buttons/field labels — the uppercase card-header idiom in console.css is deliberate and works. |
| A6 | Sidebar triage data + inline hold reason | Cheap — hold reason is already captured by the hold modal. |
| A7 | Card status lines · footer clarity · Language & time | Localization is a real shipped feature (admin.js:484-517), so keeping it is correct. |
Right diagnosis, adjust the prescription
| ID | Item | Adjustment |
|---|---|---|
| B1 | Collapse the 8-item nav | Don't build a new avatar menu — ship the drawer you already have. It's the best chrome in the app and already holds the whole nav; it's just on 3 pages of 6 while a flat strip duplicates it. Put it everywhere, delete the strip. Fixes F2. |
| B2 | Un-truncate the switcher | Fix correctness (F1) first. "Micron EUV Cleanroom Enable · 2667008" won't fit 280px, and existing rules narrow it to 150px under 900px — needs a breakpoint plan. |
| B3 | Remove the project-picker card | The first-run empty state lives inside that card. A header dropdown is the wrong home for "create your first project" — the launcher needs an explicit empty state. |
| B4 | 4-cell pipeline strip | Hard data dependency: launcher SOP status reads localStorage, and the creator's dashboard admits it "reads local data now; wires to SQL in Phase 2". Per-browser numbers that look authoritative are worse than none. Server aggregates first. |
| B5 | Autosave status text | Must ship with actual autosave + dirty guard. A "✓ All changes saved" toast already appears (that's the sync outbox, not your draft), so the app arguably implies this today. |
| B6 | Wizard actions beside the fields | On Constraints/Sequence steps that means scrolling to save. Prefer sticky — the creator's sticky save bar already solves it. |
| B7 | Toolbar into the tab row | Unstated prerequisite: tab row is in the parent, toolbar in the iframe child. This requires dissolving the iframe — the largest engineering item on the list. Name and schedule it. |
Not addressed
| ID | Gap |
|---|---|
| C1 | Accessibility — and the redesign touches every broken part. The step rail being rebuilt is 10 <div onclick>s; the status pills being replaced are the moment for a real radio group; the tooltips are unreachable on the tablet Field View targets. Skipping these means paying for the same components twice. |
| C2 | Mobile — no item on the list, and it's where the worst rendering is (F2). |
| C3 | Token consolidation — without it, "one button system" gets implemented four times and drifts, exactly as .field-hint did. |
| C4 | URL state · icon system · unsaved-changes guard · sample-data sprawl — none addressed. |
4. Recommended sequence
Ordered by dependency, not preference.
- The six rendering defects. No design decisions; F1/F2 unblock the chrome work.
- Drawer everywhere, flat strip deleted. Reuses the best existing component, fixes phone-width collapse, settles global nav before anything is redrawn.
- Token consolidation. One source of truth, page sheets aliasing to it. Every later visual item lands once instead of four times.
- Launcher + SOP wizard. Pipeline strip (after server aggregates), empty-state ownership, vertical stepper, editable fields, autosave + guard. Make the 10 steps buttons while rebuilding.
- The creator. Guarded transitions, de-duplicated warnings, section tabs, triage data. Decide the iframe question up front — most of this depends on it.
Dependencies: B1 resolves F2 · B2 depends on F1 · A3 depends on C3 · B7 gates most of step 5.