docs(fase-5): plan mobile UX rewrite ("Monolith Editorial")
- Add plan/fase-5-mobile-ux.md with 7-chunk breakdown:
5.0 mobile tests (Playwright mobile-shell/masthead/swipe-delete + Vitest helpers)
5.1 responsive shell (MobileTopBar + BottomTabBar + MobileDrawer)
5.2 ScreenMasthead + px-4/md:px-6 pass
5.3 /lists mobile cards
5.4 /lists/[id] rows + red-zone swipe-delete
5.5 undoQueue store + UndoToast
5.6 scrollable frequency chips
5.7 tasks/notes/search shell + masthead
5.Z verify 211 + new M-series green
- Explicit gap analysis vs. current app + deliberate exclusions
(no priority badges, no voice search, no fake meta like "Dairy · Weekly")
- Index design/ directory: Stitch mockups per screen (mobile + desktop variants),
plus the "Monolith Editorial" DESIGN.md directing tonal shifts, masthead
typography, glassmorphism, and the no-line rule
- Relocate DESIGN.md under design/slate_collective/DESIGN.md (old entry point) —
the current design direction lives at design/DESIGN.md
- Reference design/ from CLAUDE.md + add Fase 5 to README phase index
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
239
design/colectivo_design_reference.html
Normal file
239
design/colectivo_design_reference.html
Normal file
@@ -0,0 +1,239 @@
|
||||
# DESIGN.md
|
||||
|
||||
Design reference for the Colectivo app. Stack: SvelteKit + shadcn-svelte + Tailwind CSS.
|
||||
|
||||
---
|
||||
|
||||
## 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 |
|
||||
|---|---|---|
|
||||
| Screen title | 20px | 600 |
|
||||
| Section header | 13px | 600, uppercase, tracked |
|
||||
| Body / list item | 16px | 400 |
|
||||
| Secondary / meta | 13px | 400 |
|
||||
| Input | 16px | 400 — prevents iOS zoom on focus |
|
||||
|
||||
Line height: 1.5 for body, 1.2 for headings. No text smaller than 13px.
|
||||
|
||||
### Spacing
|
||||
|
||||
Base unit: 4px (Tailwind default). Prefer multiples of 4. Common values:
|
||||
|
||||
- List item padding: `px-4 py-3`
|
||||
- Screen horizontal margin: `px-4` (mobile), `px-6` (desktop)
|
||||
- Section gap: `gap-6`
|
||||
- Bottom nav 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) |
|
||||
| `Dialog` | Confirmations (delete list, dissolve collective) |
|
||||
| `Popover` | Presence avatars tooltip, note color picker |
|
||||
| `Badge` | Status labels (archived, completed) |
|
||||
| `Separator` | Section dividers |
|
||||
| `Skeleton` | Loading states |
|
||||
| `Sonner` | Toast notifications (sync errors, member joined) |
|
||||
|
||||
---
|
||||
|
||||
## Layout & Navigation
|
||||
|
||||
### App Shell
|
||||
|
||||
Two-column on desktop, single-column on mobile.
|
||||
|
||||
```
|
||||
Mobile Desktop (lg+)
|
||||
┌─────────────────────┐ ┌──────────┬──────────────────────┐
|
||||
│ Header │ │ │ Header │
|
||||
├─────────────────────┤ │ ├──────────────────────┤
|
||||
│ │ │ Nav │ │
|
||||
│ Content │ │ Sidebar │ Content │
|
||||
│ │ │ │ │
|
||||
├─────────────────────┤ │ │ │
|
||||
│ Bottom Nav │ └──────────┴──────────────────────┘
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
### Navigation
|
||||
|
||||
**Mobile:** fixed bottom tab bar, 4 tabs. Respects `safe-area-inset-bottom`.
|
||||
**Desktop (`lg+`):** left sidebar, always visible.
|
||||
|
||||
| Tab | Icon | Route |
|
||||
|---|---|---|
|
||||
| Lists | `shopping-cart` | `/lists` |
|
||||
| Tasks | `check-square` | `/tasks` |
|
||||
| Notes | `file-text` | `/notes` |
|
||||
| Search | `search` | `/search` |
|
||||
|
||||
Collective switcher and user avatar live in the header (mobile) / top of sidebar (desktop).
|
||||
|
||||
### Screen Structure
|
||||
|
||||
Every screen follows the same skeleton:
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ ← Back Screen Title ⋯ │ ← Header: title + optional action menu
|
||||
├─────────────────────────────┤
|
||||
│ │
|
||||
│ Main content │ ← Scrollable
|
||||
│ │
|
||||
├─────────────────────────────┤
|
||||
│ [ + Add item... ] │ ← Sticky bottom input (list/task screens)
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
### Responsive Breakpoints
|
||||
|
||||
Use Tailwind defaults: `sm` (640), `md` (768), `lg` (1024). The sidebar appears at `lg`. Content max-width: `max-w-2xl` centered on large screens.
|
||||
|
||||
---
|
||||
|
||||
## 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 │ ← slate-800 bg, slate-100 text, 36px tall
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
Disappears immediately when connection is restored. No animation — just mounts/unmounts.
|
||||
|
||||
### Add Item Input
|
||||
|
||||
Sticky to the bottom of list and task screens. On focus, shows frequency suggestions above it:
|
||||
|
||||
```
|
||||
┌──────────────────────────────┐
|
||||
│ Milk · Bread · Eggs │ ← Frequency chips (top 5, scrollable row)
|
||||
├──────────────────────────────┤
|
||||
│ 🔍 Add item... [+] │ ← Input + confirm button
|
||||
└──────────────────────────────┘
|
||||
```
|
||||
|
||||
- Chips are horizontally scrollable, `text-sm`, `rounded-full`, `border` style
|
||||
- Tapping a chip fills the input; the user can still edit before confirming
|
||||
- While typing, chips are replaced by prefix-filtered suggestions (max 10, vertical list)
|
||||
- Confirm with the `+` button or `Enter`
|
||||
|
||||
### Swipe to Delete
|
||||
|
||||
On list items and tasks. Swipe left reveals a red destructive zone:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ ☐ Whole milk 1L ░░░░░░ │ ← item sliding left
|
||||
│ [Del] │ ← red zone, icon only
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Full swipe confirms deletion immediately (no dialog). Partial swipe snaps back. A toast with "Undo" appears for 4 seconds.
|
||||
|
||||
### Drag & Drop Reordering
|
||||
|
||||
Handle on the left side of each item (visible on long-press on mobile, always visible on desktop). Use `svelte-dnd-action`. During drag: item has `shadow-md`, others compress slightly to show insertion point.
|
||||
|
||||
### Shopping Session Mode
|
||||
|
||||
Full-screen takeover. Clean, distraction-free:
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ ✕ Compra semanal 👤👤 │ ← close + presence avatars
|
||||
├─────────────────────────────┤
|
||||
│ ☐ Whole milk 1L │
|
||||
│ ☐ Bread │ ← large tap targets (min 56px height)
|
||||
│ ☐ Eggs 12 uds │
|
||||
│ ──────── Checked ──────── │ ← divider, auto-scrolled below
|
||||
│ ☑ Butter 250g │ ← muted, struck through
|
||||
├─────────────────────────────┤
|
||||
│ Finish shopping │ ← full-width button
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
- No bottom nav, no sidebar — only the list
|
||||
- Items checked during the session slide down past the divider automatically
|
||||
- Presence avatars are `size-7`, overlap slightly if multiple members present
|
||||
|
||||
### Confirmations
|
||||
|
||||
**Destructive, hard-to-reverse actions** (delete list, remove member, dissolve collective): use a `Dialog` with explicit confirmation text. No shortcut.
|
||||
|
||||
**Soft deletions** (single item, single task): swipe with undo toast — no dialog.
|
||||
|
||||
### Empty States
|
||||
|
||||
Simple, text-only. No illustrations.
|
||||
|
||||
```
|
||||
No lists yet.
|
||||
Tap + to create one.
|
||||
```
|
||||
|
||||
Two lines max. Secondary text color. Centered in the content area.
|
||||
|
||||
### Loading States
|
||||
|
||||
Use `Skeleton` components that match the shape of the content (list rows, not spinners). Spinner only for full-screen blocking operations (login, initial data fetch).
|
||||
Reference in New Issue
Block a user