7.8 KiB
Moodboard — UX Change Plan
Derived from the recommendations in
DESIGN_AND_FLOW.md(the high-end design/UX doc), checked against the actual implementation. This is a design-and-UX polish plan — closing the gap between the experience the doc describes and what's shipped. (AI/ML features live separately inFEATURE_BACKLOG.md; backend-dependent work like sharing stays deferred.)
Audit — doc says vs. reality
| Recommendation (DESIGN_AND_FLOW.md) | Status today | Gap |
|---|---|---|
| §5 "Stagger on entry — items fade-up assembled" | Not built — grid renders the virtualized slice with no entry motion | Yes |
| §8 "Focus-visible rings on interactive controls" | Partial — only card action-rail + toolbar add-buttons | Yes |
| §8 "Cards not yet keyboard-focusable/selectable" | Not built — pointer-only | Yes (acknowledged) |
| §8 "Toolbar/inspector don't collapse < ~768px" | Not built — fixed horizontal island; inspector is a fixed 2-pane | Yes (acknowledged) |
| §4.2 "Sections" | Model-ready, no UI | Yes |
| §4.1 "Paste URL → link card" | Hostname-only, no OG preview | Yes (needs proxy) |
| §4.6 "Auto-layout helpers want better surfacing" | Helpers exist (pack/fitToGrid/cluster), under-exposed |
Yes |
| §5 double-bezel, glass islands, spring motion, hover rail, card states, scrims, login button, triage hint, inspector dialog | Built ✓ | — |
Everything in the bottom row is genuinely shipped; the rows above are the work.
The plan (prioritized by impact ÷ effort)
Each item: what + UX, why (design rationale), effort (S/M/L), acceptance.
P1 — Motion & accessibility foundation (do first)
1.1 Entry motion — staggered fade-up on the grid. (the doc claims it; it isn't there)
- What: as cards mount into the viewport, fade-up from
translate-y-2 opacity-0 blur-[2px]→ rest over ~320ms on--mb-ease-smooth, with an index-based delay capped at ~12 items so a full screen feels assembled, not dumped. Must be virtualization-safe: animate only on first mount, key the animation so re-renders/scroll don't re-trigger; respectprefers-reduced-motion. - Why: the single biggest "expensive feel" lever the doc names; the board currently pops in flatly.
- Effort: S–M. Acceptance: opening a board / switching density plays one clean stagger; scrolling does not re-animate; reduced-motion shows instant.
1.2 Keyboard-navigable cards.
- What: card root becomes focusable (
tabIndex=0,role="button",aria-label);Enter/Spaceopens the inspector,X/Deletedeletes the focused card (with the same deliberate-delete rule), and arrow keys move focus across the masonry (geometry-aware: left/right within a row, up/down to the nearest card). Selection follows focus withSpace;Shift+arrows extends. - Why: the doc's headline a11y gap; also a power-user speed win (no mouse round-trips during triage).
- Effort: M. Acceptance: a keyboard-only user can tab into the grid, move with arrows, open/rate/delete, and select — with a visible focus ring on each card.
1.3 Complete focus-visible coverage.
- What: add focus-visible rings to every remaining interactive control —
SelectionBarbuttons,SmartSearchBarinput + clear + tag chips, density segmented control, rating-filter toggle, the view switch, and allItemInspectorcontrols (rating stars, tag input, palette swatches, actions). - Why: §8 says "everywhere"; today it's two components.
- Effort: S. Acceptance: tabbing through the whole moodboard always shows where focus is.
P2 — Responsive & micro-UX completeness
2.1 Responsive toolbar.
- What: below
md, the floating island stops being one wide row — it becomes a compact glass bar: board name + a+-menu (collapsing the 4 add-buttons), density, rating, and a search icon that expands into a sheet; the whole thingoverflow-x-autoas a last resort so it never breaks the layout. - Why: §8 gap; the webapp can be viewed narrow, and today the island overflows.
- Effort: M. Acceptance: at 375px wide the toolbar is usable and doesn't clip; at ≥
mdit's unchanged.
2.2 Responsive inspector.
- What: below
md, the inspector stacks (media on top, the panel as a bottom sheet) instead of the fixed media-left / 320px-panel split;h-[100dvh]; nav arrows move to the corners. - Why: §8 gap; the current side-by-side is unusable on phones.
- Effort: S–M. Acceptance: inspector is fully usable at 375px.
2.3 Sections UI.
- What: group items into named, collapsible sections in the grid (the model already supports
sections+sectionId). A section header row with a name (inline-rename), count, collapse toggle, and "new section"; drag a selection into a section; an "Ungrouped" default lane. - Why: §4.2 calls it a near-term add; big boards spiral without it (Pinterest Sections / MJ folder-groups).
- Effort: M. Acceptance: create/rename/collapse sections; assign items; persists.
2.4 Surface canvas auto-layout helpers.
- What: a one-click Tidy / Arrange menu on the canvas toolbar exposing the already-built
pack(justified rows),fitToGrid, andcluster-by-proximity, plus "align selection." - Why: §4.6 — the logic exists but is hidden; cheap, high-delight.
- Effort: S. Acceptance: the three layouts run from a visible menu; undoable.
2.5 "Button-in-button" primary CTAs.
- What: apply the doc's nested trailing-icon pattern (already in the empty-state CTA) to the primary actions — "Use as reference" and the inspector's primary button — with the magnetic hover physics (icon translates diagonally + scales on hover, button
active:scale-[0.98]). - Why: §5 haptic consistency; makes the differentiator action feel premium.
- Effort: S. Acceptance: primary CTAs share one polished button anatomy.
P3 — Larger canvas & capture polish
2.6 Canvas alignment + snapping + background grid.
- What: snap a dragged node to other nodes' edges/centers with guide lines (DIY on Konva
dragmove), plus a toggleable background grid + snap-to-grid. - Why: §4.6/§9 — makes the freeform canvas feel professional (PureRef 2.1).
- Effort: M. (also tracked in
FEATURE_BACKLOG.md3.1/3.2.) Acceptance: dragging shows guides + snaps; grid toggles.
2.7 Rich URL preview (link cards).
- What: paste a URL → fetch OG title + image for a real preview card (vs hostname today).
- Why: §4.1 — link cards look unfinished without a thumbnail.
- Effort: S (client) / M (proxy). Dependency: OG fetch needs a CORS unfurl proxy → flag as backend-dependent / defer the image; ship title now.
2.8 Drag-from-library onto the board.
- What: let a gallery item be dragged directly onto the grid/canvas (not only picked via the modal), reusing Artcraft's existing gallery-drag event.
- Why: §4.1 — the lowest-friction capture path for already-owned media.
- Effort: M. Acceptance: drag a library thumbnail onto the board → it lands as a tokened item.
Sequencing
- Sprint 1 (feel + a11y): 1.1 entry motion, 1.2 keyboard cards, 1.3 focus coverage. One cohesive "the board feels finished and is fully keyboard-able" release.
- Sprint 2 (responsive + organize): 2.1 toolbar, 2.2 inspector, 2.3 sections, 2.5 CTAs.
- Sprint 3 (canvas + capture): 2.4 surface auto-layout, 2.6 snapping/grid, 2.8 drag-from-library, 2.7 link previews (title now, image when a proxy exists).
Recommended first move
Sprint 1 — it's the highest "expensive feel ÷ effort" and closes the doc's two explicit a11y gaps + the one motion claim that isn't yet true. All client-side, no backend, fits the shared lib cleanly, and verifiable headlessly (focus order, reduced-motion, DOM-on-mount).