docs(timeline): design doc for the grouped-view contained-card layout

Records the visual-brainstorm outcome for #827's grouped view: a cluster becomes one
contained card (event/tag as header, first 5 letters + show-more), the leftover bin
collapses to a count-only drawer, derived/world fixtures stay plain, and REQ-001/003/014/020
are amended. Mockups under .superpowers/brainstorm/ (gitignored).

Refs #827 #847
This commit is contained in:
Marcel
2026-06-15 14:36:35 +02:00
parent ce6afd3bd0
commit 74bf1d864c

View File

@@ -0,0 +1,102 @@
# Zeitstrahl grouped-view layout redesign
**Date:** 2026-06-15
**Feature:** #827 (regroup `/zeitstrahl` by Ereignis/Thema) — layout follow-up on PR #847
**Status:** Approved (brainstorm), pending implementation plan
> The REQ contract for #827 lives in the Gitea issue body (and the amendment comment of
> 2026-06-15). This document records the **layout/visual design** agreed in the visual
> brainstorm and the REQ deltas it implies. Mockups: `.superpowers/brainstorm/*/content/`.
## Problem
The first grouped-view implementation (PR #847) fixed the flood and the duplicate event title,
but two issues remained on review of the live view:
1. **Weak belonging.** A clustered event's letters dropped below its centered pill as a
full-width block with only a thin left rail. The connection between an event and its letters
read weakly — the eye couldn't tell the letters belonged to the pill above.
2. **Layout inconsistency.** In Datum mode letters alternate left/right of the centered spine
(events/density centered). In grouped mode the letters became full-width, breaking that
rhythm with no clear reason.
## Decision: a cluster is one contained card
A clustered event (Ereignis) or root tag (Thema) renders as **one bordered card** whose header
is the event/tag itself and whose body holds that cluster's letters. Belonging becomes
structural (a single container), not positional guesswork. This replaces the full-width block.
### Ereignis mode, per year band
1. **Derived life-events** (Geburt/Tod/Heirat, `abgeleitet`) never cluster — they carry no
document links, so they are always **plain axis fixtures, unchanged from Datum mode**. A
**world-band** (`historisch`) is normally letterless and stays a plain band; on the rare
occasion a historical event has linked letters it follows rule 2 (becomes a card).
2. **A curated event (PERSONAL or HISTORICAL) with letters in this band** → one mint-bordered card:
- **Header** = the event's glyph + title + date + `kuratiert` + edit-✎ + count (the pill's
content, laid out as a header bar). This *replaces* the separate floating pill for that
event in this band — killing the duplicate title.
- **Body** = the cluster's letters, **first 5 shown, then a "+ N weitere Briefe anzeigen"
toggle** that expands/collapses the rest. Letters use the compact `LetterCard` variant.
3. **A curated event with no letters in this band** → stays a plain centered pill (no empty card).
4. **A curated event whose letters fall in a different year than its pill** → those letters form a
labeled card in *their* year (header = event name as text, no ✎/pill since the pill lives
elsewhere); the pill stays in its own band. No adjacent duplication.
5. **Leftover letters** (linked to no surviving curated event) → a collapsed neutral, dashed
**"✉ N Briefe ohne Ereignis · anzeigen "** drawer. Clicking expands to the same first-5 +
show-more list. No preview letters until opened.
### Thema mode
Identical shape. Each card's header is the **tinted root-tag chip** (`● Krieg · 24`,
`BucketHeaderChip`, fixed-ink label per the contrast fix) instead of an event pill; there is no
axis pill for a tag, so every tag cluster is a standalone card. The per-letter `TagChip` stays
suppressed inside its own card (REQ-017). The leftover drawer reads **"Ohne Thema"**.
### Layout / spine
- Cluster cards are **centered on the spine** (like events already are), not full-width-flush —
consistent with how grouped units (events) relate to the axis. Individual chronological
letters keep alternating left/right only in **Datum** mode.
- Each card carries a colour left rail: **mint** for an Ereignis cluster, the **tag colour** for
a Thema cluster, **neutral dashed** for the leftover drawer.
## Components affected
- `LetterBucket.svelte` — becomes the contained card: header slot (pill-content / tag chip /
drawer label / cross-year text label) + body with the first-5 cap and the show-more toggle.
Drop the `YearLetterStrip` (sparkline) branch from grouped mode.
- `YearBand.svelte` — in Ereignis mode, a same-year curated event renders *as* the card header
(merge pill into the card) instead of pill-then-nested-bucket; derived/world/letterless events
stay plain; cross-year clusters and the leftover drawer render after the axis entries.
- `LetterCard.svelte` — compact variant already exists (PR #847); reused inside cards.
- `BucketHeaderChip.svelte` — reused as the Thema card header (contrast fix already shipped).
- `timelineGrouping.ts` — the first-visible cap (`CLUSTER_PREVIEW = 5`) replaces
`BUCKET_DENSE_THRESHOLD`; helpers unchanged otherwise.
- Possibly a small `ClusterCard`/header sub-component if `LetterBucket` grows too large.
## REQ deltas (to fold into issue #827)
- **REQ-001 (amended):** derived life-events, world-bands, and *letterless* curated event pills
render identically across modes; a curated event **that has letters** renders as its cluster
card's header in grouped mode (no longer byte-identical to its Datum pill). Every event keeps
its spine position (year).
- **REQ-003 / REQ-014 (amended):** event-clustered letters live inside a contained card; the
header is the event (same-year) or a text label (cross-year). First 5 shown + show-more.
- **REQ-020 (amended):** grouped clusters are contained colour-railed cards with a first-5
preview + show-more toggle; the leftover bin is a collapsed count-only drawer. The
month-density `YearLetterStrip` is **no longer used in grouped mode** (still used in Datum
dense years).
## Out of scope
- Datum mode (untouched — keeps the alternating-axis zigzag and the >12 sparkline strip).
- Backend / DTO (`linkedEventId` and root-tag fields already shipped; no change).
- New i18n beyond a show-more / drawer label string set.
## Testing approach
TDD per component, mirroring PR #847: `LetterBucket` (card header variants, first-5 cap,
show-more expand/collapse, drawer collapsed-by-default, colour rail), `YearBand` (same-year merge
= no duplicate title; cross-year keeps a label; derived/world pills unchanged), and the route
spec for the assembled view. Run targeted `--project=client` / `--project=server` specs only.