Files
artcraft/docs/moodboard/DESIGN_AND_FLOW.md
T
2026-06-23 20:15:52 -07:00

228 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Artcraft Moodboard — Design & Flow
> How the moodboard looks, feels, and flows. Written through a high-end product-design lens
> (Linear/Apple-tier restraint: haptic depth, spring-physics motion, calm surfaces) and grounded
> in the shipped implementation (`@storyteller/ui-moodboard`). Companion to `DESIGN_SYSTEM.md`
> (tokens/components), `FEATURE_PLAN.md` (roadmap), and `FEATURE_BACKLOG.md` (what's next).
---
## 1. Design philosophy
Three convictions drive every decision:
1. **The board is an input to generation, not a graveyard.** Generic moodboards (Pinterest,
Milanote) are dead ends — references go in, nothing comes out. Artcraft owns the engine, so the
board is one gesture away from a generation and vice-versa. Every surface keeps that loop in
reach without ever shouting about it.
2. **Native, then elevated.** The moodboard lives *inside* Artcraft, so it speaks the app's visual
language (the `--st-*` theme tokens, Fira Sans, the `glass` material, the brand blue). Elevation
comes from *composition* — nested "double-bezel" enclosures, floating glass islands, motion with
mass — never from a louder palette. The board should feel like it was always part of the app.
3. **The imagery is the interface.** Chrome recedes; references dominate. No like-counts, no
notification noise, no decorative gradients competing with the user's work. Calm by default
(the Cosmos/Are.na lesson), dense where it counts.
The felt quality we're after: **a precise, quiet instrument** — fast, tactile, and a little bit
joyful, where heavy operations feel weightless and nothing ever teleports.
---
## 2. Visual language (the short version)
The full token/component spec is in `DESIGN_SYSTEM.md`; the design *intent* behind it:
- **Double-bezel enclosures.** Cards, the inspector, and toolbars are never flat on the canvas.
A subtle outer shell (plane-1, hairline ring, `rounded-[18px]`, `p-1`) cradles an inner core
(plane-2, concentric `rounded-[14px]`, an inset top-highlight). It reads like a glass plate
seated in a machined tray — physical, considered, expensive.
- **Floating glass islands.** The toolbar and the view switch are detached pills, not edge-glued
bars (`glass` + hairline + ambient shadow, `backdrop-blur` only on these fixed elements — never
on the scrolling grid, where blur would torch scroll performance).
- **Spring-physics motion.** Custom cubic-beziers, never `linear`/`ease-in-out`. A hover lift, a
card landing on drop with a touch of overshoot, a palette fading up. Animate only `transform`,
`opacity`, `filter` — GPU-safe. `prefers-reduced-motion` collapses springs to fades.
- **Concentric squircle radii** and **ambient, layered shadows** (never a harsh `shadow-md`).
- **One display moment.** Body/UI is Fira Sans (the app font, for zero context-switch); the only
"display" flourish is the editorial empty-state heading and presentation mode.
---
## 3. Information architecture
```
Board (durable model, localStorage today → backend later)
├── items: image · video · text · link · color (each: tags, rating, deterministic aspect)
├── sections (model-ready; UI is a near-term add)
└── rendered three ways — ALL views are projections of the same board:
├── GRID virtualized masonry — the default; scan / search / triage at volume
├── CANVAS freeform Konva stage — arrange / compare / plan spatially
└── PRESENT full-bleed deck — review & share
```
**Why grid-first.** 90% of moodboard time is scanning, searching, and triaging — the grid wins
those high-frequency jobs and stays at 60fps (canvas-only tools like Milanote lag at a few hundred
items; we virtualize from item aspect ratios so only the viewport mounts). The freeform canvas is
the *delighter* for spatial thinking, not the foundation. **The board, not the view, is what plugs
into generation** — "use as reference" works regardless of how you're looking at it.
---
## 4. Core flows
Each flow below lists the **gesture**, then the **design rationale**.
### 4.1 Capture — get references in with zero friction
The fastest path wins, so we offer every path and make the empty state *say so*.
- **Drag images** from the desktop onto the board → a dashed primary-tinted drop overlay confirms
the target; files land at the cursor.
- **Paste** — an image from the clipboard drops instantly; a **URL** becomes a link card
(hostname title today; rich OG preview is a backlog item).
- **Upload** (toolbar `↑` / empty-state CTA) → the image appears immediately from a blob, then
uploads in the background to capture a durable media token (so it becomes reference-capable).
- **From library** → the shared gallery picker (Artcraft's own `GalleryModal`), so muscle memory
transfers from the rest of the app. Not signed in? The picker now shows a **Log in** button
(not a dead "Retry"), routed per-platform via the adapter.
- **Note / Color** → a sticky note or an OS-picked swatch, one click each.
*Rationale:* friction is the enemy of collection. The empty state is an **editorial hero**
("Start collecting ideas") that doubles as the drop affordance — it teaches the gestures while
looking like a finished product, not a blank slate.
### 4.2 Organize — keep a growing board legible
- **Density** — a segmented control (Compact / Cozy / Comfortable) re-flows the masonry; the
layout is target-width-driven, so it adapts to any container (Savee's adjustable-density bar).
- **Search + tag chips** — text query over captions/tags/links; click a chip to filter.
- **Multi-select** — click, shift/⌘-click, or marquee-drag on bare canvas; a floating glass
**selection bar** rises from the bottom with the count + actions.
### 4.3 Triage — sift keepers from a batch, fast
Lightroom is the gold standard for high-volume culling, so we borrow its muscle memory:
- With items selected, **`1`–`5`** rate, **`0`** clears, **`P`** picks (5 stars). A rating badge
persists on the tile.
- The toolbar **star filter** cycles "All → 1+ … → 5+ → All" to winnow to keepers.
- The selection bar surfaces the shortcuts inline (`1–5 rate · 0 clear`) so they're *discoverable*,
not hidden lore.
- **Delete is deliberate** — `Delete`/`Backspace` only (we removed `x` as a delete alias: it sits
in the number row and the board has no undo, so a stray press must not destroy work).
*Rationale:* triage is keyboard-first because it's repetitive and high-volume; every key saves a
trip to the mouse. Destructive actions get friction; constructive ones get none.
### 4.4 The board → generate loop — the differentiator
This is the move no generic moodboard can make.
- **"Use as reference"** — on a card's hover rail, in the selection bar, or in the inspector.
Selected board images are pushed into the image-generation prompt as style references (via their
media tokens) and the user lands on the Create-Image surface, refs pre-filled. Krea/Firefly
proved board→generate; Artcraft closes it natively.
- The seam is the **adapter** (§6): desktop seeds `usePromptImageStore` + switches to the Image
tab; web seeds `useCreateImageStore` + navigates to `/create-image`. Same gesture, same result,
two platforms.
*Rationale:* the highest-leverage feature is the one that turns a passive collection into momentum.
It's always one click from any view, and it never blocks — it sends and gets out of the way.
### 4.5 Inspect — the lightbox as a workbench
Double-click or the rail's expand icon opens a full-screen **inspector**:
- Large media on a glass-blurred backdrop (blur is fine here — it's a fixed overlay), a
double-bezel side panel, `←/→` to walk the board, `Esc` to close, background scroll locked,
`role="dialog"`.
- The panel is a small workbench: **rating** stars, a **tag editor**, an **extracted palette**
(client-side color quantization — click a swatch to copy, or "add swatches to board"), and
**Use as reference**. The palette is keyed on the image src, so editing tags never re-decodes
the image or flickers.
### 4.6 Canvas — think spatially
The freeform Konva stage for arranging, comparing, and planning:
- Pan/zoom, marquee + lasso select, 8-handle transform, grouping, undo/redo, a shortcut cheatsheet,
and auto-layout helpers (pack / fit-to-grid / cluster-by-proximity) that already exist and want
better surfacing. Alignment/snapping + a background grid are the next polish (backlog).
- Drop a generation onto the canvas, set images side by side, group a coherent set, then send that
set to generation. It's the planning room; the grid is the library.
### 4.7 Present — review & share
A distraction-free, full-bleed deck: one item at a time, `←/→/space` to navigate, `Esc` to exit,
launched from the view switch as a transient overlay (never persisted, so a reload never reopens
into a slideshow). For client/team review and screen-sharing.
---
## 5. Micro-UX niceties (the details that read as "expensive")
- **Hover action rail** — a glass pill on each card fades *up* on hover (translate + opacity), with
Open / Use-as-reference / Delete. Buttons stop propagation so they never double as a select.
- **Card states choreographed** — hover lifts the shell 2px and deepens the shadow; selected swaps
to a 2px brand ring; drag scales to 1.03; drop lands with a snap-overshoot.
- **Selection check + rating** — solid scrims (not blur) inside the scrolling grid for legibility
without GPU cost.
- **Focus-visible rings everywhere** — keyboard users see where they are, not just hover users.
- **The Login button** — the gallery picker now invites action ("Log in to browse your library" +
a real primary button) instead of a confusing "Retry" link.
- **Stagger on entry** — grid items and presentation reveals come in with a short staggered
fade-up, so the board feels assembled, not dumped.
---
## 6. Cross-platform via the adapter
One library, two hosts, identical experience. The lib owns everything platform-agnostic; each app
injects a `MoodboardAdapter` for its three seams:
```ts
interface MoodboardAdapter {
uploadImage?: (file) => Promise<mediaToken | null>; // capture a durable token
sendToGeneration: (refs) => void; // board → prompt
renderLibraryPicker?: (props) => ReactNode; // the gallery picker (render-prop)
}
```
- **Desktop (Tauri):** upload via `@storyteller/api`, picker via `GalleryModal`, send → prompt
store + tab switch, login → the login modal.
- **Web (artcraft-webapp):** upload via the webapp uploader, picker via the same `GalleryModal`,
send → create-image store + `/create-image`, login → navigate `/login`.
*Rationale:* the adapter is the seam where platform reality lives, so the *experience* stays a
single, consistent design across surfaces — and the same polish ships everywhere at once.
---
## 7. Motion & performance contract
- **Curves:** spring (`cubic-bezier(0.32,0.72,0,1)`) for settle/zoom; smooth
(`cubic-bezier(0.4,0,0.2,1)`, ~200ms) for hover/selection; snap with slight overshoot on drop.
- **Only `transform`/`opacity`/`filter`** animate — never layout properties.
- **`backdrop-blur` only on fixed chrome** (toolbar, view switch, inspector/present backdrops);
the virtualized scrolling grid uses solid scrims so scrolling stays at 60fps.
- **Virtualize aggressively** — deterministic masonry from item aspects means only viewport-visible
cards mount; the grid holds thousands of items without lag (the competitor failure mode).
- **Respect `prefers-reduced-motion`** — springs become instant, fades remain.
---
## 8. Accessibility & polish checklist
- [x] Theme-correct: consumes `--st-*` only, so light/dark/gray/black/aurora themes work for free.
- [x] Focus-visible rings on interactive controls; inspector is a labelled `role="dialog"` with
scroll-lock and keyboard nav.
- [x] Color is never the only signal (drop state pairs a tint with a dashed outline + icon).
- [x] Destructive delete is deliberate (no single-printable-key delete); no silent data loss.
- [ ] Cards are not yet keyboard-focusable/selectable (pointer-first) — a known a11y gap.
- [ ] Toolbar/inspector don't yet collapse gracefully below ~768px (desktop-first) — responsive
pass pending.
---
## 9. Where the design goes next
The research-backed backlog (`FEATURE_BACKLOG.md`) extends this flow without changing its spine —
client-side ML (in-browser captioning, auto-tagging, find-similar, palette/color search) makes the
board *understand itself*; canvas snapping/alignment and a region→palette tool deepen planning; and
the generate-into-a-board / remix loop tightens the differentiator. Collaboration & sharing are
deferred behind a flag (they need the backend). The throughline stays constant: **collect with no
friction, organize effortlessly, and turn the board into the next generation — calmly.**