This is a fresh start for the `artcraft` repo. The old monorepo, which included our web API gateway, job services, SRE tools, various frontends, and more has moved to `artcraft-services` You can find the full git history here: https://github.com/storytold/artcraft-services This change was motivated by the fact that the entire git history was hundreds of gigabytes in size, which is unwieldy for anyone not in the core team that doesn't care about support services outside of the core artcraft app. We wanted to keep this repo in its well-known place since we already have users and activity here. Please update your remotes to either `artcraft-services` or make a fresh clone of this repo. History can be found at the artcraft-services repo.
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).