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

6.1 KiB
Raw Blame History

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.