Files
familienarchiv/docs/superpowers/specs/2026-06-15-zeitstrahl-grouped-view-layout-design.md
Marcel 74bf1d864c 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
2026-06-15 14:36:35 +02:00

103 lines
6.1 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.
# 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.