Add planning docs, design system, and Stitch mockups
- CLAUDE.md: project guidance (stack, domain model, auth, i18n, gotchas) - DESIGN.md: full design system spec derived from Stitch mockups (slate monochrome, Inter, shadcn-svelte, screen patterns for all 5 views) - README.md: development plan with Justfile commands - analysis/: functional spec (domain model, use cases, business rules) - plan/: phase-by-phase implementation plans (Fase 0–4) - .stitch/designs/: generated mockups (lists, shopping session, notes, tasks, list detail with frequency chips) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
442
DESIGN.md
Normal file
442
DESIGN.md
Normal file
@@ -0,0 +1,442 @@
|
||||
# DESIGN.md
|
||||
|
||||
Design reference for the Colectivo app. Stack: SvelteKit + shadcn-svelte + Tailwind CSS.
|
||||
|
||||
Generated mockups are in `.stitch/designs/`. Stitch project ID: `10316144241804324155`.
|
||||
|
||||
---
|
||||
|
||||
## Visual Style
|
||||
|
||||
### Direction
|
||||
|
||||
Clean and minimal. Content is the UI — no decorative elements, no gradients, no shadows unless they carry meaning. Generous whitespace. Every element earns its place.
|
||||
|
||||
### Color
|
||||
|
||||
Monochromatic slate palette. No accent color — contrast and weight carry hierarchy.
|
||||
|
||||
```
|
||||
--background: slate-50 / slate-950
|
||||
--surface: white / slate-900
|
||||
--surface-raised: slate-100 / slate-800
|
||||
--border: slate-200 / slate-700
|
||||
--text-primary: slate-900 / slate-50
|
||||
--text-secondary: slate-500 / slate-400
|
||||
--text-disabled: slate-300 / slate-600
|
||||
--destructive: red-500 / red-400 ← only color in the UI
|
||||
```
|
||||
|
||||
Interactive elements (buttons, checkboxes, active states) use `slate-900` on light and `slate-50` on dark — inverting the surface. The only true color is destructive red.
|
||||
|
||||
### Typography
|
||||
|
||||
Font: **Inter** (or `system-ui` as fallback — acceptable on iOS/macOS).
|
||||
|
||||
| Role | Size | Weight | Notes |
|
||||
|---|---|---|---|
|
||||
| Screen title | 20px | 600 | |
|
||||
| Section label | 13px | 600 | Uppercase, `letter-spacing: 0.05em` |
|
||||
| Body / list item | 16px | 400 | |
|
||||
| Meta / secondary | 13px | 400 | `text-slate-500` |
|
||||
| Badge / tag | 11px | 500 | Uppercase, `rounded-full` |
|
||||
| Input | 16px | 400 | Min 16px prevents iOS zoom on focus |
|
||||
|
||||
Line height: 1.5 for body, 1.2 for headings. No text smaller than 11px.
|
||||
|
||||
### Spacing
|
||||
|
||||
Base unit: 4px (Tailwind default). Prefer multiples of 4. Common values:
|
||||
|
||||
- List item padding: `px-4 py-3` (min 48px touch target)
|
||||
- Screen horizontal margin: `px-4` (mobile), `px-6` (desktop)
|
||||
- Section gap: `gap-6`
|
||||
- Between section label and content: `mt-2`
|
||||
- Bottom nav / sticky input safe area: always account for `env(safe-area-inset-bottom)`
|
||||
|
||||
### Iconography
|
||||
|
||||
**Lucide** (ships with shadcn-svelte). Size `20px` inline, `24px` for nav and primary actions. Stroke width `1.5`. Never fill icons.
|
||||
|
||||
### Dark Mode
|
||||
|
||||
Class-based (`dark` on `<html>`). Respect `prefers-color-scheme` on first load, then persist user preference in `localStorage`. shadcn-svelte's CSS variable system handles theming — no additional setup needed per component.
|
||||
|
||||
---
|
||||
|
||||
## Component Library
|
||||
|
||||
**shadcn-svelte** — copy-paste components built on bits-ui + Tailwind. No runtime dependency, full ownership of component code.
|
||||
|
||||
### Conventions
|
||||
|
||||
- Copy components into `apps/web/src/lib/components/ui/` (shadcn-svelte default)
|
||||
- App-specific compositions go in `apps/web/src/lib/components/` (e.g. `ItemRow.svelte`, `ListCard.svelte`)
|
||||
- Never modify shadcn-svelte primitives directly — compose or wrap them
|
||||
- Use shadcn-svelte's `cn()` utility for conditional classes
|
||||
|
||||
### Key components to install
|
||||
|
||||
| Component | Used for |
|
||||
|---|---|
|
||||
| `Button` | All actions |
|
||||
| `Input` | Add item, search, forms |
|
||||
| `Checkbox` | Shopping items, tasks |
|
||||
| `Sheet` | Mobile bottom drawers (item edit, member invite, avatar picker) |
|
||||
| `Dialog` | Confirmations (delete list, dissolve collective) |
|
||||
| `Popover` | Presence avatars tooltip |
|
||||
| `Badge` | Priority tags (TODAY, URGENT), status labels (DRAFT, HIGH PRIORITY) |
|
||||
| `Skeleton` | Loading states |
|
||||
| `Sonner` | Toast notifications (sync errors, member joined, undo delete) |
|
||||
|
||||
---
|
||||
|
||||
## Layout & Navigation
|
||||
|
||||
### App Shell
|
||||
|
||||
Two-column on desktop, single-column on mobile.
|
||||
|
||||
```
|
||||
Mobile Desktop (lg+)
|
||||
┌─────────────────────┐ ┌──────────┬──────────────────────┐
|
||||
│ Header │ │ │ Breadcrumb / Title │
|
||||
├─────────────────────┤ │ Sidebar │──────────────────────┤
|
||||
│ │ │ │ │
|
||||
│ Content │ │ │ Content │
|
||||
│ │ │ │ │
|
||||
├─────────────────────┤ │ User │ │
|
||||
│ Bottom Nav │ │ Info │ │
|
||||
└─────────────────────┘ └──────────┴──────────────────────┘
|
||||
```
|
||||
|
||||
### Sidebar (desktop)
|
||||
|
||||
Fixed left sidebar, `surface-raised` background (vs `surface` main area — tonal shift, no border line).
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ Colectivo │ ← collective name, 14px/600
|
||||
├──────────────┤
|
||||
│ 🛒 Lists │ ← active item: slate-900 bg, white text
|
||||
│ ✓ Tasks │ ← inactive: slate-500 text
|
||||
│ 📄 Notes │
|
||||
│ 🔍 Search │
|
||||
│ │
|
||||
│ (spacer) │
|
||||
│ │
|
||||
│ ┌──┐ Name │ ← user avatar + display name
|
||||
│ │AG│ Role │ ⚙ ← settings gear icon
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
- Collective name at top, 14px/600
|
||||
- 4 nav items: Lists, Tasks, Notes, Search
|
||||
- User avatar + display name + settings gear at bottom
|
||||
- Width: `w-56` (`224px`)
|
||||
|
||||
### Navigation (mobile)
|
||||
|
||||
Fixed bottom tab bar, 4 tabs. Icons only — no text labels. Active icon: `slate-900`. Inactive: `slate-400`. Glassmorphism background: `backdrop-blur-md bg-white/80`. Respects `safe-area-inset-bottom`.
|
||||
|
||||
| Tab | Icon | Route |
|
||||
|---|---|---|
|
||||
| Lists | `shopping-cart` | `/lists` |
|
||||
| Tasks | `check-square` | `/tasks` |
|
||||
| Notes | `file-text` | `/notes` |
|
||||
| Search | `search` | `/search` |
|
||||
|
||||
### Page Headers
|
||||
|
||||
Desktop: breadcrumb-style context path above the title, in uppercase 11px/500 `text-slate-400`:
|
||||
|
||||
```
|
||||
WORKSPACE OVERVIEW
|
||||
Shared Lists
|
||||
```
|
||||
|
||||
```
|
||||
PROJECT ATLAS / Tasks
|
||||
```
|
||||
|
||||
Mobile: plain title with optional back arrow and overflow `⋯` menu on the right.
|
||||
|
||||
### Responsive Breakpoints
|
||||
|
||||
Tailwind defaults: `sm` (640), `md` (768), `lg` (1024). Sidebar appears at `lg`. Content max-width: `max-w-2xl` centered on large screens.
|
||||
|
||||
---
|
||||
|
||||
## Screen Patterns
|
||||
|
||||
### Lists View (`/lists`)
|
||||
|
||||
Featured card for the primary/active list (full width, larger), secondary lists in a 2-column grid below.
|
||||
|
||||
```
|
||||
WORKSPACE OVERVIEW
|
||||
Shared Lists
|
||||
┌─────────────────────────────────────┐
|
||||
│ Home 👤👤 │ ← featured card
|
||||
│ 12 items · Updated 2h ago │
|
||||
│ [GROCERIES] [HOUSEHOLD] │ ← category tags, rounded-full
|
||||
└─────────────────────────────────────┘
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ Office │ │ Party │
|
||||
│ 5 items │ │ 26 items │
|
||||
│ 🗂 │ │ HIGH PRTY │ ← badge
|
||||
└──────────────┘ └──────────────┘
|
||||
┌─────────────────────────────────────┐
|
||||
│ + Create a new shared list... [Create] │ ← sticky bottom input
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- Category tags on list cards: `rounded-full text-xs font-medium bg-slate-100 px-2 py-0.5`
|
||||
- Presence avatars overlap on cards with active members
|
||||
|
||||
### List Detail (`/lists/[id]`)
|
||||
|
||||
Normal (non-session) view. Items with quantity controls.
|
||||
|
||||
```
|
||||
ACTIVE LIST
|
||||
Grocery List ⋯
|
||||
┌─────────────────────────────────────┐
|
||||
│ ☐ Honeycrisp Apples 6 + │
|
||||
│ ☐ Organic Baby Spinach 2 + │
|
||||
│ ☐ Whole milk 1L 2 + │
|
||||
│ ☐ Salted Butter 1 + │
|
||||
└─────────────────────────────────────┘
|
||||
|
||||
[MILK] [BREAD] [EGGS] [COFFEE] [APPLES] ← frequency chips
|
||||
┌─────────────────────────────────────┐
|
||||
│ Add item (e.g. Greek Yogurt 500g) [+] │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- Quantity controls: `−` count `+` inline at the right of each row
|
||||
- Frequency chips always visible above the input (not just on focus); active chip: `bg-slate-900 text-white`; inactive: `bg-slate-100 text-slate-700`
|
||||
|
||||
### Shopping Session Mode (`/lists/[id]/session`)
|
||||
|
||||
Full-screen takeover. No sidebar, no bottom nav.
|
||||
|
||||
```
|
||||
✕ Compra semanal 👤👤
|
||||
─────────────────────────────────────
|
||||
TO BUY
|
||||
☐ Whole milk 1L
|
||||
☐ Bread
|
||||
☐ Eggs 12 uds
|
||||
☐ Avocados
|
||||
|
||||
CHECKED
|
||||
☑ Butter 250g (muted, struck through)
|
||||
☑ Olive Oil 1L
|
||||
|
||||
─────────────────────────────────────
|
||||
[ Finish shopping ● ]
|
||||
```
|
||||
|
||||
- `TO BUY` and `CHECKED` are uppercase section labels, not divider lines
|
||||
- Items slide from TO BUY to CHECKED on tap — no page scroll
|
||||
- Minimum tap target: `min-h-[56px]`
|
||||
- Presence avatars: `size-6 rounded-full`, overlapping, top-right of header
|
||||
- "Finish shopping" button: full-width, `bg-slate-900 text-white`, with a subtle pulse indicator dot (●)
|
||||
|
||||
### Tasks View (`/tasks`)
|
||||
|
||||
Tasks grouped into named sections. Filter pills at the bottom.
|
||||
|
||||
```
|
||||
PROJECT ATLAS / Tasks 👤👤
|
||||
─────────────────────────────────────
|
||||
HIGH PRIORITY
|
||||
☐ Finalize Q4 strategy deck TODAY
|
||||
☐ Coordinate with design on monolith tokens URGENT
|
||||
|
||||
PRODUCT DEVELOPMENT
|
||||
☐ Core API Integration
|
||||
☐ Review documentation for Auth endpoints (indented sub-item)
|
||||
☑ Map database schema to editorial structure (completed)
|
||||
☐ User testing: Editorial workflow
|
||||
|
||||
BACKLOG
|
||||
☐ Update dependency libraries
|
||||
|
||||
─────────────────────────────────────
|
||||
[DAILY] [WEEKLY] [URGENT] ← filter pills
|
||||
┌─────────────────────────────────────┐
|
||||
│ Add task to Tasks... [Save] │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- Section names are user-defined (not system-fixed)
|
||||
- Priority badges on individual tasks: `text-xs uppercase text-slate-400` (TODAY, URGENT)
|
||||
- Filter pills: same style as frequency chips; filter the visible tasks
|
||||
|
||||
### Notes View (`/notes`)
|
||||
|
||||
Notes displayed as cards in a masonry-style grid, grouped by user-defined categories.
|
||||
|
||||
```
|
||||
WORKSPACE / NOTES 🔔 ⊞ 👤
|
||||
─────────────────────────────────────
|
||||
CATEGORY
|
||||
Meeting Notes
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ Q4 Product │ │ Sprint Retro: │
|
||||
│ Roadmap... │ │ Project Apollo │
|
||||
│ Oct 24, 2023 │ │ Oct 22, 2023 │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
|
||||
CATEGORY
|
||||
Project Ideas
|
||||
┌─────────────────┐
|
||||
│ Minimalist │
|
||||
│ Portfolio... │
|
||||
└─────────────────┘
|
||||
|
||||
─────────────────────────────────────
|
||||
│ Capture a new thought... # @ [SAVE] │
|
||||
```
|
||||
|
||||
- Cards: `bg-white rounded-md` on `surface-raised` background (tonal lift, no shadow)
|
||||
- Category labels: uppercase section labels above each group
|
||||
- Inline new-note input at the bottom (not a separate screen)
|
||||
|
||||
---
|
||||
|
||||
## UX Patterns
|
||||
|
||||
### Optimistic Updates
|
||||
|
||||
All mutations update the local store immediately before the server responds. On error, revert and show a toast. Never block the UI waiting for a network response.
|
||||
|
||||
### Offline Indicator
|
||||
|
||||
A slim bar at the top of the content area (not the header) when offline:
|
||||
|
||||
```
|
||||
No connection · Saving locally
|
||||
```
|
||||
|
||||
`bg-slate-800 text-slate-100`, 36px tall. Mounts/unmounts immediately — no animation.
|
||||
|
||||
### Frequency Chips (Add Item Input)
|
||||
|
||||
Sticky input area at the bottom of list and task screens. Frequency chips are **always visible** above the input, not conditional on focus.
|
||||
|
||||
```
|
||||
[MILK] [BREAD ●] [EGGS] [COFFEE] [APPLES] ← scrollable row
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ Add item (e.g. Greek Yogurt 500g) [+] │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- Chips: `rounded-full text-xs font-medium px-3 py-1 bg-slate-100` (inactive) / `bg-slate-900 text-white` (active/selected)
|
||||
- Tapping a chip fills the input; user can still edit before confirming
|
||||
- While typing, chips switch to prefix-filtered suggestions (max 10, same pill style)
|
||||
- Confirm with `+` button or `Enter`
|
||||
|
||||
### Swipe to Delete
|
||||
|
||||
On list items and tasks. Swipe left reveals a red destructive zone:
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────┐
|
||||
│ ☐ Whole milk 1L ░░░░░░ │ ← item sliding left
|
||||
│ [🗑] │ ← red-500 zone, trash icon only
|
||||
└────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Full swipe: immediate deletion + Sonner toast "Deleted · Undo" (4 seconds). Partial swipe: snaps back. No confirmation dialog for single items.
|
||||
|
||||
### Drag & Drop Reordering
|
||||
|
||||
Handle (`grip-vertical` Lucide icon) on the left — always visible on desktop, revealed on long-press on mobile. Use `svelte-dnd-action`. During drag: lifted item has `shadow-md bg-white`, others compress to show insertion point.
|
||||
|
||||
### Confirmations
|
||||
|
||||
**Destructive, hard-to-reverse actions** (delete list, remove member, dissolve collective): `Dialog` with explicit description text. No shortcut.
|
||||
|
||||
**Soft deletions** (single item, single task): swipe + Sonner undo. No dialog.
|
||||
|
||||
### Avatar Component
|
||||
|
||||
Three mutually exclusive states, all `rounded-full`.
|
||||
|
||||
| State | Appearance | Size tokens |
|
||||
|---|---|---|
|
||||
| `initials` | Initials on `slate-700` bg, white 600-weight text | `size-6` presence, `size-8` lists, `size-16` settings |
|
||||
| `emoji` | Emoji centered on `slate-700` bg | same |
|
||||
| `upload` | `<img object-cover>`, fallback to initials on error | same |
|
||||
|
||||
Initials rule: first letter of first + last word in `display_name` ("Ana García" → "AG", "Borja" → "B").
|
||||
|
||||
### User Settings Screen (`/settings`)
|
||||
|
||||
In the desktop sidebar shell. Content area:
|
||||
|
||||
```
|
||||
← Settings
|
||||
|
||||
┌──────┐
|
||||
│ AG │ ← size-16 avatar
|
||||
└──────┘
|
||||
Change avatar ›
|
||||
|
||||
DISPLAY NAME
|
||||
┌────────────────────────────────┐
|
||||
│ Ana García │ ← auto-save, 500ms debounce
|
||||
└────────────────────────────────┘
|
||||
Changes saved automatically ← slate-400 hint
|
||||
|
||||
LANGUAGE
|
||||
[ English ] [ Español ] ← pill segmented control
|
||||
English selected: slate-900/white. Instant effect, no reload.
|
||||
|
||||
ACCOUNT ← background shift (no line)
|
||||
Email & password → ← external link to Keycloak
|
||||
Managed in Keycloak ← slate-400
|
||||
|
||||
DANGER ZONE ← section label in red-500
|
||||
[ Delete account ] ← ghost red button
|
||||
```
|
||||
|
||||
**Avatar sheet** — `Sheet` (bottom on mobile, dialog on desktop):
|
||||
|
||||
- Segmented tabs: Initials | Emoji | Photo
|
||||
- Emoji grid: 8 columns, ~40 emoji (🐸 🐼 🦊 🐨 🦁 🐯 🐻 🦋 🌵 🌻 🍀 🌈 ⭐ 🔥 💎 🎯 🎸 🎹 🎨 📚 ✈️ 🏔️ 🌊 🎭 🍕 🍜 🍣 ☕ 🍎 🥑 🍓 🎂 🏠 🚲 🛹 ⚽ 🏄 🧘 🎮 🤿)
|
||||
- Photo upload: file picker → 1:1 crop in-browser → preview → confirm. Max 2MB. JPG/PNG/WebP.
|
||||
|
||||
### Empty States
|
||||
|
||||
Text-only, no illustrations. `text-slate-500`, centered in content area.
|
||||
|
||||
```
|
||||
No lists yet.
|
||||
Tap + to create one.
|
||||
```
|
||||
|
||||
Two lines max.
|
||||
|
||||
### Loading States
|
||||
|
||||
`Skeleton` components matching the shape of the content (list rows, card grids). Spinner only for full-screen blocking operations (login, initial data fetch).
|
||||
|
||||
---
|
||||
|
||||
## Stitch Mockup Inventory
|
||||
|
||||
Screens in `.stitch/designs/` — project `10316144241804324155`:
|
||||
|
||||
| File | Screen | Status |
|
||||
|---|---|---|
|
||||
| `01-lists-view.png` | Lists View | ✅ |
|
||||
| `02-shopping-session.png` | Shopping Session | ✅ |
|
||||
| `03-notes-view.png` | Notes View | ✅ |
|
||||
| `04-tasks-view.png` | Tasks View | ✅ |
|
||||
| `05-list-detail.png` | List Detail with frequency chips | ✅ |
|
||||
| — | User Settings | ⏳ pending generation |
|
||||
| — | Collective Management | ⏳ pending generation |
|
||||
Reference in New Issue
Block a user