My-Weekly-ToDo-List/docs/DESIGN_NOTES.md

256 lines
14 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.

# Design Notes — todo.martin-bierschenk.de v2
> Visual reference: `Todo Calendar Redesign v2.html`
> Aesthetic: Minimal Scandinavian / TeuxDeux-style hairline editorial
> Goal: a calm, airy, paper-like weekly planner. **Restyle only — no logic, routing, data, sync, or component-API changes.**
---
## 0 · Rules of engagement (read first)
1. **Do not change behaviour.** Keep all existing hooks, server actions, NextAuth wiring, calendar sync, recurring-task logic, drag-and-drop, keyboard shortcuts, and component prop shapes exactly as they are.
2. **Touch JSX + CSS only.** New CSS variables / Tailwind tokens are fine; new state, new effects, new dependencies are not.
3. **One component per commit.** Visual restyles are easy to review (and revert) when scoped. Suggested order: tokens → layout shell → day grid → all-day strip → events → tasks (anyday) → left rail → right settings → header.
4. **Keep existing component file structure** (`WeeklyCalendarView.tsx`, `TaskList.tsx`, `CalendarEventModal.tsx`, etc.). Only edit them.
5. **Where this doc and the HTML mock disagree, the mock wins** for visuals. Where the mock and the existing code disagree on behaviour, the existing code wins.
---
## 1 · Design tokens
Add these as CSS custom properties (or extend `tailwind.config.js` `theme.extend`). All other colors should be derived from these.
### Color
keep the colors for now
**Calendar-source palette** (event chips, muted on purpose — they should not compete with the today-red):
| Source | Background | Border-left | Title color | Meta color |
|---------------|-------------|-------------|-------------|------------|
| Default/work | `#eef2f7` | `#6c87a8` | `#2b3f57` | `#6c87a8` |
| Family (`.fam`) | `#fbeef0` | `#b85a6a` | `#5a2530` | `#99536a` |
| Finance (`.fin`)| `#f6f0e2` | `#a88a3c` | `#4a3a14` | `#8a6f2a` |
| Dev/GitHub (`.dev`) | `#ecf3ed` | `#5a7a4a` | `#2c4527` | `#5a7a4a` |
| Note (`.note`) | transparent | none | `var(--ink-2)` | `var(--ink-4)` |
**All-day chip palette** (solid pills above the day headers):
| Variant | Background | Text |
|--------------|-------------|-----------|
| Default | `#b8b8b0` | `#fff` |
| Family (`.fam`) | `#e88a8a` | `#fff` |
| Special (`.special`, anniversaries, milestones) | `#f4d588` | `#6b4f10` |
### Typography
- **UI / sans**: `Geist`, fallback `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif`
- **Editorial / serif**: `Fraunces` italic — used **only** for the small quote in the header bar
- **Mono / numerals**: `Geist Mono` if needed; otherwise rely on `font-variant-numeric: tabular-nums` for any clock/date/count
Body letter-spacing: `-0.005em` baseline.
| Role | Size | Weight | LH | Other |
|-----------------------|------|--------|-------|-------|
| Section h3 | 16px | 600 | 1.2 | |
| Day name (`.dn`) | 16px | 600 | 1 | uppercase, `letter-spacing: 0.04em` |
| Day name — today | 16px | 700 | 1 | color: `--accent` |
| Day date (`.dnum`) | 11px | 400 | 1 | uppercase, `tabular-nums`, color: `--ink-4` |
| Header KW (`.wk`) | 13px | 500 | — | `letter-spacing: 0.02em` |
| Header quote | 12px | 400 | — | Fraunces italic, `--ink-4` |
| Event title | 12px | 500 | 1.25 | |
| Event note title | 11.5px | 400 | 1.25 | |
| Event meta / time | 10.5px | 400 | — | `tabular-nums` |
| All-day chip | 11px | 500 | 1.2 | |
| List heading (`h4`) | 12px | 500 | — | uppercase, `letter-spacing: 0.04em` |
| List item | 12px | 400 | 1.35 | |
| Hour label | 10px | 400 | — | `tabular-nums`, color: `--ink-5` |
| Tasks tab | 12px | 500/600 | — | active is 600 |
| Tab counter chip | 10.5px | 500 | 1.4 | `tabular-nums` |
### Spacing & geometry
- Left rail: **56px** wide, fixed
- Right settings drawer: **360px** wide, slides in from the right (`transform: translateX(100%)` → `translateX(0)`, `cubic-bezier(.2,.8,.2,1)` 250ms)
- Permanent top header: **36px** tall, white, hairline bottom
- Day grid hour-row height: **56px**
- Day grid column gap: **20px**
- Day grid horizontal padding: **24px**
- Border radius: 4px (events), 6px (corner buttons, inputs), 78px (list cards, segmented pills), 10px (tasks tab pill container)
- All shadows are tiny: `0 1px 2px rgba(0,0,0,.06)` or `0 4px 16px rgba(0,0,0,.06)`. Never bigger.
- Hover surfaces: `rgba(0,0,0,.05)` for icons, `rgba(0,0,0,.025).04` for text hits
### Motion
- All transitions: `120180ms`, `cubic-bezier(.2,.8,.2,1)` for sliding panels, plain `ease` for hover
- The right drawer is the only large transform; everything else is opacity / background swaps
---
## 2 · Layout shell
```
┌─────────────────────────── header (36px, always visible) ───┐
│ KW 19 | 410. Mai 2026 "quote…" │
├──────┬────────────────────────────────────────────────┬─────┤
│ │ all-day strip │ │
│ left │────────────────────────────────────────────────│ rt │
│ rail │ day-headers row │ drw │
│ 56px │────────────────────────────────────────────────│ 360 │
│ │ day grid (hours × columns) │ px │
│ │────────────────────────────────────────────────│ off │
│ │ tasks (anyday) — warm grey, 6 white list cards │ scr │
└──────┴────────────────────────────────────────────────┴─────┘
```
- The **toolbar is gone**. Only two floating icon buttons remain: a sidebar-toggle top-left of the header, a search top-right.
- The right drawer is hidden by default. A small `18×64px` chevron tab on the right edge toggles it; the gear icon in the left rail also toggles it.
---
## 3 · Component-by-component restyle guide
### 3.1 Top header (`header`)
- `position: sticky`/`absolute`, `top: 0`, height 36px, white, hairline bottom
- Centered: `KW WW | 410. Mai 2026` • faint Fraunces italic quote
- Text colors: KW = `--ink-2` 13px/500; quote = `--ink-4` 12px italic; ellipsize at ~480px
### 3.2 Left rail (`lside`)
Order, top to bottom:
1. **Date nav cluster**` row, "Heute" pill (uppercase, hairline border), ` »` row
2. Hairline separator
3. **View flyout** — calendar icon; on hover, flyout reveals: Einfach / Kalender / Liste / Kanban / Ziel
4. **Day-count flyout** — grid icon; flyout: 1 / 2 / 3 / 5 / 7
5. **Zeitfenster flyout** — clock icon; flyout: 15m / 20m / 30m / 60m
6. Hairline separator
7. Action icons (vertical stack): plus, calendar-pick, projects, recurring, target, focus
8. Hairline separator
9. Undo, redo, sync, download, print
10. Hairline separator
11. **Light/dark toggle** (single sun/moon icon — toggles, not two icons)
12. **User avatar** at the bottom (`margin-top: auto`)
Icons are 16px, currentColor, in 36×36 hit-targets, `border-radius: 8px`, hover background `rgba(0,0,0,.05)`. Active state uses `--accent-soft` background + `--accent` color.
Flyouts pop **right** of the rail with a subtle pointer triangle.
### 3.3 All-day strip (`allday`)
- Grid: `56px [hour gutter pad] repeat(N, 1fr)`, column gap 20px, padding `10px 24px 0`
- Per-day column: `min-height: 56px`, vertical stack of chips, gap 3px
- Chips are **solid colored pills** (see palette table). No icons, no date pips inside.
- Today's column gets `background: var(--accent-soft)` with extra horizontal padding
- Small uppercase label "GANZTAGS" 9px in left gutter
### 3.4 Day headers (`days` + `dayh`)
- Grid identical to all-day strip (same column gaps for alignment)
- Each header: small **MAI 6** date on top, large **MITTWOCH** weekday name below, both uppercase
- 2px solid `--ink` underline below each header
- **Today**: weekday in `--accent` red 700, blue-grey `--accent-soft` background, centered, padding 6px 8px, 1px ink underline
- **Weekend (Sat/Sun)**: weekday red, underline red
### 3.5 Day grid body (`body`)
- **No vertical lines** between days — the column gap (20px) is the separator. This is the TeuxDeux move.
- Horizontal hour rules only (`--line` color, 1px), one per hour
- Hour labels in the left gutter, 10px, `--ink-5`, right-aligned, sitting on the rule (background-cut)
- **Today column** gets `background: var(--accent-soft)` (full height)
- **Now-line**: 1px `--accent` red across the today column, with an 8×8 dot on the left and a small time pill (`HH:MM`) on the right with `bg: var(--bg)` for clean cutout
### 3.6 Events (`ev`)
Two visual modes:
**Timed event card** — coloured background by source, 2px left-border accent, `border-radius: 4px`, `padding: 8px 10px`. Title row has an inline 16px source icon (`.t .src`) before the text. Synced events show a small sync arrow at top-right (`.sync`, opacity .55). Meta line: `HH:MM HH:MM · Location`.
**Note event** (`.ev.note`) — for todos placed at a time but without a duration block: transparent background, no border-left, no rounding, just small inline icon + text. Used for github-source items, key/cake/car category notes, etc.
Source icon mapping (16px, currentColor SVG):
- `git` — github / dev tasks
- `money` — finance / banking
- `book` — Legasthenie / Nachhilfe
- `home` — Garde / home
- `key`, `cake`, `car` — category notes
- `bolt` — focus / quick task
- `pin`, `info` — generic
### 3.7 Anyday tasks (`tasks`)
- Section background: `--tasks-bg` (`#f4f2ee` warm light grey)
- 6-up grid of white list cards (`--paper`, 1px `--line`, 8px radius, `min-height: 200px`, padding `12px 12px 8px`)
- Card heading: 6px colored dot · uppercase project name · count chip on right
- Each item: 9×9 unchecked box (1px `--ink-5`) · text · hairline `--line-soft` underneath
- **Tabs above the grid** are a segmented-pill control:
- Container: `inline-flex`, `padding: 4px`, `bg: rgba(0,0,0,.05)`, `border-radius: 10px`
- Active tab: white pill, weight 600, shadow `0 1px 2px rgba(0,0,0,.06), 0 0 0 1px rgba(0,0,0,.04)`
- Inactive: text `--ink-3`, hover white-50 background
- Each tab has a count chip — small grey rounded-rect, tabular-nums
### 3.8 Right settings drawer (`rside`)
- 360px white panel, slides in from right edge
- Vertical icon-tab strip across the top (settings, globe, link, sync, box, user, palette, spark)
- Each row: small label (11px `--ink-3`, weight 500) + input/checkbox/segmented control
- Inputs: 1px `--line`, 6px radius, 7px 10px padding, 13px `--ink-2`
- Help text under fields: 10px `--ink-4`
- Sections separated by full-bleed `--line` `<hr>`
- Close `×` top-right; clicking the gear icon in the left rail or the edge tab toggles it
### 3.9 Floating corner buttons
- 28×28, 6px radius, `top: 8px`
- Left: sidebar-toggle. Right: search.
- These sit **on top of** the header bar.
---
## 4 · Iconography
All icons are **16px, currentColor, 1.4 stroke-width SVG**, drawn on a 20×20 viewBox, no fill (line-art). Examples: cal, list, kanban, target, grid, clock, search, plus, proj, repeat, bolt, moon, sun, setg, sync, print, user, download, sidebar, chevL/R, eye, undo, redo, refresh, sliders, globe, link, box, palette, spark, info, money, git, book, home, car, key, cake.
Hover icons go from `--ink-3``--ink`. Active state for view/filter icons goes from `--ink-3``--accent` on `--accent-soft` background.
---
## 5 · What to keep from the existing app
- All data shapes, server actions, API routes
- `next-auth` wiring, middleware
- Drag-and-drop calendar event editing
- Recurring task logic
- Calendar-sync flows (Google etc.)
- Keyboard shortcuts
- Print view (we can restyle it, but keep the print route)
---
## 6 · Suggested PR breakdown
1. **`feat(design): add tokens`** — CSS variables / tailwind extend, no markup changes
2. **`feat(design): app shell + header + corner buttons`** — top-level layout
3. **`feat(design): left rail`** — collapse old toolbar into rail with flyouts
4. **`feat(design): right settings drawer`** — slide-in panel
5. **`feat(design): day grid`** — hairline rules, no verticals, today wash, day headers
6. **`feat(design): all-day strip`** — solid chip pills
7. **`feat(design): events`** — source-coloured cards + note variant + source icons
8. **`feat(design): anyday tasks`** — segmented tabs + 6-up white cards on warm grey
9. **`chore(design): typography pass`** — Geist + Fraunces, sizes from §1
10. **`chore(design): icon set swap`** — 16px line-art set
Each PR small enough to eyeball. After step 9 the app should look like the mock; step 10 is polish.
---
## 7 · Open questions for the engineer
- Is Geist already loaded? If not, add it via `next/font` (don't pull from Google Fonts at runtime).
- Does the existing `theme` system support multiple accent colors per calendar source, or is that a new concept? If new, hold off on the per-source event colors and ship the today-red + neutral-event scheme first.
- Confirm dark mode is in scope — the mock is light-only; tokens for dark would need to be derived in a follow-up.
---
*End of notes. When in doubt, open `Todo Calendar Redesign v2.html` in a browser and copy what you see.*