- 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>
240 lines
9.4 KiB
HTML
240 lines
9.4 KiB
HTML
# 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).
|