02Content States × 3 Viewports
Eleven states covering every combination of content presence and filter selection. Every frame renders the full page (header → Für dich → filters → timeline). Reading order per state: 320 px (mobile S) → 768 px (tablet) → 1440 px (desktop). Look for wrap behavior on filter pills at 320, and row-preview truncation on both mobile sizes.
01Default · Unreads + Rich Timeline
Happy path. 3 unread mentions in the Für dich box; timeline shows recent activity with a rollup (20 Blöcke transkribiert) and a read mention rendered in the for-you lane. "Alle gelesen" action visible in header. Default filter: Alle.
320 px · Mobile
176 px @ 55%
← Übersicht
@
Mama erwähnte dich
"schau mal, Omas Handschrift…"
14:32
@
Oma erwähnte dich
"Marcel, weißt du noch…"
11:05
↩
Anna antwortete
"ja genau, 1947 Hamburg"
gest
Alle
Für dich
Hochgeladen
Transkription
Kommentare
AR
Anna transkribierte
20 Blöcke in
Brief 42 14:02–14:32
@
MR
"schau mal, das ist Omas…"
14:32
OR
"das war bei der Hochzeit…"
18:47
768 px · Tablet
422 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
@
Mama hat dich in Brief Nr. 42 erwähnt
"schau mal, das ist Omas Handschrift von 1952"
14:32
✓
@
Oma hat dich in Brief Nr. 39 erwähnt
"Marcel, weißt du noch den Hund auf dem Foto?"
11:05
✓
↩
Anna hat auf deinen Kommentar in Brief Nr. 41 geantwortet
"ja genau, das war 1947 in Hamburg"
Gestern
✓
Alle
Für dich
Hochgeladen
Transkription
Kommentare
PR
Papa lud 3 Dokumente hoch
11:08
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
OR
"das war bei der Hochzeit von Onkel Heinrich, der hatte einen Dackel namens Bello"
18:47
1440 px · Desktop
720 px @ 55% (col)
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
@
Mama hat dich in Brief Nr. 42 erwähnt
"schau mal, das ist Omas Handschrift von 1952"
14:32
✓
@
Oma hat dich in Brief Nr. 39 erwähnt
"Marcel, weißt du noch den Hund auf dem Foto?"
11:05
✓
↩
Anna hat auf deinen Kommentar in Brief Nr. 41 geantwortet
"ja genau, das war 1947 in Hamburg"
Gestern
✓
Alle
Für dich
Hochgeladen
Transkription
Kommentare
PR
Papa lud 3 Dokumente hoch
11:08
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
OR
"das war bei der Hochzeit von Onkel Heinrich, der hatte einen Dackel namens Bello"
18:47
PR
"stimmt, das war kurz vor dem Umzug nach Köln"
Mo · 14:22
Mehr laden
Beobachtungen im Layout.
- 320 px: die fünf Filter-Pills wickeln auf zwei Zeilen — bewusst, weil keine Pill abgeschnitten werden darf. Die letzte Pill muss vollständig sichtbar sein (niemals
overflow:hidden auf diesem Row).
- 320 px: Für-Dich-Vorschau wird mit Ellipsis einzeilig abgeschnitten. Tap auf Zeile navigiert; Inhalt öffnet sich komplett auf der Zieldokument-Seite.
- 768 px & 1440 px: Vorschautexte erlauben Zeilenumbruch, max 2 Zeilen für Timeline-Rows.
- Der Dismiss-Button (✓) auf Für-Dich-Zeilen erscheint erst ab 768 px — auf 320 px wird die Zeile selbst tap-bar und markiert beim Öffnen automatisch als gelesen (Swipe-Gesture als v2).
02"Für dich" Empty · Inbox Zero + Activity Present
All personal mentions have been read. Für dich box collapses to a small reassurance card with a link to the "Für dich" filter (history view). Timeline still renders as normal. "Alle gelesen" action hidden from header.
320 px · Mobile176 px @ 55%
← Übersicht
✓
Keine neuen Erwähnungen
Ältere ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
AR
Anna transkribierte
20 Blöcke in
Brief 42 14:02
@
MR
Mama erwähnte dich
"schau mal, Omas…"
14:32
768 px · Tablet422 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
✓
Keine neuen Erwähnungen
Ältere Erwähnungen ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
PR
Papa lud 3 Dokumente hoch
11:08
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
OR
"das war bei der Hochzeit von Onkel Heinrich"
18:47
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
✓
Keine neuen Erwähnungen
Ältere Erwähnungen ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
PR
Papa lud 3 Dokumente hoch
11:08
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
OR
"das war bei der Hochzeit von Onkel Heinrich, der hatte einen Dackel namens Bello"
18:47
Mehr laden
Warum dieser Zustand wichtig ist. Eine leere Inbox ohne sichtbare Bestätigung wirkt wie ein Fehler ("wo sind meine Nachrichten?"). Die Reassurance-Karte ("✓ Keine neuen Erwähnungen · Ältere ansehen →") ist die Brücke zur Vergangenheit — Nutzer:innen wissen jederzeit, dass ihre gelesenen Erwähnungen über den Filter Für dich erreichbar sind.
03First-Run · No Activity At All
Brand-new archive or a user who hasn't been granted any document access yet. Nothing to mention, nothing to activate. Für dich box hidden entirely (not just empty). Filter pills hidden — nothing to filter. Only a warm centered empty state with a clear CTA.
320 px · Mobile176 px @ 55%
← Übersicht
📜
Noch nichts geschehen
Sobald jemand Dokumente hochlädt oder transkribiert, erscheint es hier.
Erstes Dokument hochladen
768 px · Tablet422 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
📜
Noch nichts geschehen
Sobald jemand aus der Familie Dokumente hochlädt, transkribiert oder kommentiert, erscheint es hier in der Chronik.
Erstes Dokument hochladen
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
📜
Noch nichts geschehen
Sobald jemand aus der Familie Dokumente hochlädt, transkribiert oder kommentiert, erscheint es hier in der Chronik — als Zeitstrahl aller Beiträge zum Archiv.
Erstes Dokument hochladen
Wann erscheint dieser Zustand? Neue Instanz (keine Dokumente im Archiv), oder ein Nutzer, der noch keine Leserechte auf Dokumente hat. Die CTA ist kontextabhängig: mit canWrite=true → "Erstes Dokument hochladen", ohne Schreibrechte → Link zu "/dokumente" ("Archiv durchsuchen").
04Filter · Alle (Baseline)
Same content as State 01 (the default landing state when the page opens). Shown again here so the 11-state matrix is complete and so readers can compare filter-active states side-by-side with the baseline. All 6 activity kinds visible, rollups active, for-you lane active on mentions.
320 px · Mobile176 px @ 55%
← Übersicht
@
Mama erwähnte dich
"Omas Handschrift…"
14:32
Alle
Für dich
Hochgeladen
Transkription
Kommentare
AR
Anna transkribierte 20 Blöcke
14:02
768 px · Tablet422 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
@
Mama hat dich in Brief Nr. 42 erwähnt
"schau mal, das ist Omas Handschrift"
14:32
✓
↩
Anna hat geantwortet auf Brief Nr. 41
"ja genau, das war 1947 in Hamburg"
Gestern
✓
Alle
Für dich
Hochgeladen
Transkription
Kommentare
PR
Papa lud 3 Dokumente hoch
11:08
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
OR
"das war bei der Hochzeit…"
18:47
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
@
Mama hat dich in Brief Nr. 42 erwähnt
"schau mal, das ist Omas Handschrift von 1952"
14:32
✓
↩
Anna hat auf deinen Kommentar in Brief Nr. 41 geantwortet
"ja genau, das war 1947 in Hamburg"
Gestern
✓
Alle
Für dich
Hochgeladen
Transkription
Kommentare
PR
Papa lud 3 Dokumente hoch
11:08
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
OR
"das war bei der Hochzeit von Onkel Heinrich, der hatte einen Dackel namens Bello"
18:47
05Filter · Für dich (Mention History — Read + Unread)
Timeline narrows to only mentions and replies directed at the current user — both read and unread. The Für dich box remains visible above (it still represents unreads only). Every timeline row gets the for-you lane (accent left border + tinted bg + @ marker) because every row is a personal mention/reply. Unread rows additionally show the blue dot prefix.
320 px · Mobile176 px @ 55%
← Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
@
MR
Mama erwähnte dich
"Omas Handschrift…"
14:32
768 px · Tablet422 px @ 55%
/chronik?filter=fuer-dich
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
@
Mama hat dich in Brief Nr. 42 erwähnt
"schau mal, das ist Omas Handschrift"
14:32
✓
↩
Anna hat geantwortet auf Brief Nr. 41
Gestern
✓
Alle
Für dich
Hochgeladen
Transkription
Kommentare
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
↩
AR
"ja genau, das war 1947 in Hamburg"
18:47
@
OR
"Marcel, weißt du noch den Hund auf dem Foto?"
Di · 09:41
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik?filter=fuer-dich
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
@
Mama hat dich in Brief Nr. 42 erwähnt
"schau mal, das ist Omas Handschrift von 1952"
14:32
✓
↩
Anna hat auf deinen Kommentar in Brief Nr. 41 geantwortet
"ja genau, das war 1947 in Hamburg"
Gestern
✓
Alle
Für dich
Hochgeladen
Transkription
Kommentare
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
↩
AR
"ja genau, das war 1947 in Hamburg — die Oma hat mir das damals erzählt"
18:47
@
OR
"Marcel, weißt du noch den Hund auf dem Foto? Das war Rex, er hat immer Briefträger verbellt"
Di · 09:41
@
PR
"frag mal Marcel, ob er die Handschrift von Uropa erkennt"
Mo · 14:12
Mehr laden
Dieser Filter ist der Schlüssel. Er beantwortet die Frage "Wo ist meine alte Erwähnung hin?", die sonst nach dem Markieren als gelesen aufkommen könnte. Die Für-Dich-Box zeigt nur Ungelesenes; der Filter zeigt die komplette Historie. Darum muss Für dich als Pill immer sichtbar sein — auch wenn die Box leer ist.
06Filter · Hochgeladen (FILE_UPLOADED only)
Timeline narrows to uploads. Batch uploads are rolled up (same actor within 2 h). Für dich box remains visible above.
320 px · Mobile176 px @ 55%
← Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
768 px · Tablet422 px @ 55%
/chronik?filter=hochgeladen
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
✓
Keine neuen Erwähnungen
Ältere Erwähnungen ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
PR
Papa lud 3 Dokumente hoch
11:08
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik?filter=hochgeladen
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
✓
Keine neuen Erwähnungen
Ältere Erwähnungen ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
PR
Papa lud 3 Dokumente hoch
11:08
PR
Papa lud 12 Fotos aus dem Album "Umzug Köln" hoch
Mo · 10:14–10:38
Mehr laden
07Filter · Transkription (TEXT_SAVED + BLOCK_REVIEWED + ANNOTATION_CREATED)
Three kinds combined. Rollups dominate: long transcription sessions collapse to "N Blöcke in Dokument X". Verb copy distinguishes the three activities clearly (transkribierte / überprüfte / erstellte Annotation).
320 px · Mobile176 px @ 55%
← Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
768 px · Tablet422 px @ 55%
/chronik?filter=transkription
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
✓
Keine neuen Erwähnungen
Ältere Erwähnungen ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik?filter=transkription
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
✓
Keine neuen Erwähnungen
Ältere Erwähnungen ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
Mehr laden
Rollup-Regel im Detail.
- Gleicher Akteur + gleiches Dokument + gleiche Aktionsart, innerhalb 120 min → ein Row mit Count-Badge und Zeitspanne ("14:02–14:32").
- Ein einzelner Block → kein Rollup, normaler Row ("Oma transkribierte Block in Brief 32"). Die Count-Badge erscheint erst ab 2 Events.
COMMENT_ADDED und MENTION_CREATED werden NIE rolled-up — jede Kommunikation bleibt eine eigene Zeile.
- Überschreitet das Fenster eine Tagesgrenze, wird es am Tag der Gruppe selbst gerendert (frühestes Event bestimmt das Datum).
08Filter · Kommentare (COMMENT_ADDED + MENTION_CREATED)
Conversations only. Each row shows an inline preview (~140 chars of the comment text, italic). Mentions keep the for-you lane; plain comments stay in the neutral lane even when filter is active.
320 px · Mobile176 px @ 55%
← Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
@
MR
Mama erwähnte dich
"Omas Handschrift…"
14:32
OR
Oma kommentierte Brief 39
"bei der Hochzeit…"
18:47
PR
Papa kommentierte Brief 36
"vor Umzug Köln…"
12:15
768 px · Tablet422 px @ 55%
/chronik?filter=kommentare
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
@
Mama hat dich erwähnt in Brief Nr. 42
"schau mal, das ist Omas Handschrift"
14:32
✓
Alle
Für dich
Hochgeladen
Transkription
Kommentare
@
MR
"schau mal, das ist Omas Handschrift von 1952"
14:32
OR
"das war bei der Hochzeit von Onkel Heinrich"
18:47
PR
"stimmt, das war kurz vor dem Umzug nach Köln"
12:15
AR
"ja genau, das war 1947 in Hamburg"
18:12
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik?filter=kommentare
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
@
Mama hat dich in Brief Nr. 42 erwähnt
"schau mal, das ist Omas Handschrift von 1952"
14:32
✓
Alle
Für dich
Hochgeladen
Transkription
Kommentare
@
MR
"schau mal, das ist Omas Handschrift von 1952 — ich glaube, das ist der Brief an Tante Elke"
14:32
OR
"das war bei der Hochzeit von Onkel Heinrich, der hatte einen Dackel namens Bello und immer zwei Zigaretten in der Brusttasche"
18:47
PR
"stimmt, das war kurz vor dem Umzug nach Köln — ich erinnere mich, weil Mama das Foto erst am Abend entwickelt hat"
12:15
AR
"ja genau, das war 1947 in Hamburg. Die Oma hat mir damals erzählt, dass der Dackel dabei war"
18:12
Mehr laden
09Filter Active · No Matching Results
Filter is active but no events match (shown here as "Hochgeladen" with no uploads this week). Für dich box unchanged. Pills stay visible — user can switch filters without leaving the page.
320 px · Mobile176 px @ 55%
← Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
∅
Keine Uploads
Noch nichts hochgeladen.
768 px · Tablet422 px @ 55%
/chronik?filter=hochgeladen
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
✓
Keine neuen Erwähnungen
Ältere Erwähnungen ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
∅
Keine Uploads gefunden
In diesem Zeitraum wurden keine Dokumente hochgeladen. Versuche einen anderen Filter.
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik?filter=hochgeladen
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
✓
Keine neuen Erwähnungen
Ältere Erwähnungen ansehen →
Alle
Für dich
Hochgeladen
Transkription
Kommentare
∅
Keine Uploads gefunden
In diesem Zeitraum wurden keine Dokumente hochgeladen. Wähle einen anderen Filter oder schau in der vollständigen Chronik nach.
Zu Alle wechseln
10Loading · Skeleton Placeholders
Initial page load and pagination load both use the same skeleton rows. Page header and filter pills render immediately (cheap); Für dich + timeline rows shimmer until the API resolves. prefers-reduced-motion: shimmer animation is disabled, skeleton shows as static blocks.
320 px · Mobile176 px @ 55%
← Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
768 px · Tablet422 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
11Error · API Failure with Retry
Activity or notifications endpoint returned 5xx or timed out. Page chrome (header, filter pills) still render so the user can retry a filter or leave. Amber warning card with a retry button replaces the timeline body. Never shows raw stack traces — generic German text + optional error code.
320 px · Mobile176 px @ 55%
← Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
⚠
Chronik nicht verfügbar
Bitte erneut versuchen.
Erneut laden
768 px · Tablet422 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenChronik
← Zurück zur Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
⚠
Chronik konnte nicht geladen werden
Es gab ein Problem beim Laden. Bitte versuche es in einem Moment erneut.
Erneut laden
1440 px · Desktop720 px @ 55%
familienarchiv.de/chronik
Familienarchiv
DokumentePersonenBriefwechselChronik
← Zurück zur Übersicht
Alle
Für dich
Hochgeladen
Transkription
Kommentare
⚠
Chronik konnte nicht geladen werden
Es gab ein Problem beim Laden der Aktivitäten. Bitte versuche es in einem Moment erneut. Wenn das Problem länger besteht, wende dich an einen Administrator. (Code: CHRONIK_LOAD_FAILED)
Erneut laden
Error-Copy-Regeln.
- Keine rohen Backend-Messages. Mapping durch
getErrorMessage(code) über Paraglide-Keys.
- Fehlercode optional am Ende der Body-Zeile, in Klammern — hilft Support, verschreckt Nutzer nicht.
- "Erneut laden" ist eine echte Button-Aktion, kein Reload — sie triggert nur die fehlgeschlagene Query neu.
Implementation Reference — Content Statessemantic tokens
| Element | Classes | Real | Note |
| Unread dot (Für dich) | h-2 w-2 rounded-full bg-accent (light) / bg-turquoise (dark) | 8 px | aria-hidden, redundant cue |
| For-you lane row | border-l-[3px] border-accent bg-accent-bg/60 pl-3 rounded-sm | border 3 px | Never color-only; keep @ marker |
| @ marker circle | inline-flex items-center justify-center w-5 h-5 rounded-full bg-accent-bg text-ink font-bold | 20 px | Icon fallback if no name |
| Count badge (rollup) | inline-block bg-primary text-primary-fg text-xs font-bold px-1.5 py-0.5 rounded-sm | 12 px / 700 | "20 Blöcke" etc. |
| Day header | flex items-center gap-3 mt-6 mb-2 · text-xs font-bold uppercase tracking-widest text-ink-3 · after: flex-1 h-px bg-line | 12 px | Heute / Gestern / Diese Woche / Älter |
| Empty-state icon | w-10 h-10 text-accent opacity-70 | 40 px | Scroll icon for first-run, ∅ for filter-no-result, ✓ for inbox zero |
| Skeleton row | h-[72px] flex items-start gap-3 py-3 + bg-gradient-to-r from-muted via-canvas to-muted animate-shimmer | 72 px | Disable animation at motion-reduce |
| Error card | bg-warning/10 border border-warning/40 text-warning rounded-sm p-4 flex gap-3 | AA 4.8:1 | Retry button: bg-warning text-warning-fg px-4 py-2 |
04Row Anatomy · Close-Ups at ~100% Scale
Each of the four row types rendered at approximately real pixel sizes (not scaled), with labeled parts. These are the reference renderings developers check against when implementing the ChronikRow.svelte component.
Type A · Simple activity row (upload, single annotation)
Type A — Simple RowFILE_UPLOADED, single ANNOTATION_CREATED
| Part | Classes | Real | Note |
| Row container | flex items-start gap-3 py-3 border-b border-line | 56 px min | Compact (no preview) |
| Avatar | w-10 h-10 rounded-full flex items-center justify-center text-white font-bold text-sm | 40 px | Color from actor.color |
| Text line 1 | text-[15px] leading-[1.5] text-ink with <strong> on actor | 15 px / 400+700 | Document link underlined with accent |
| Time | text-sm text-ink-3 tabular-nums whitespace-nowrap ml-auto | 14 px | Right-aligned, min-width 90 px |
Type B · Rollup row (N Blöcke, Zeitspanne)
Wann erscheint der Badge? Ab 2 Events im Rollup-Fenster. 1 Event → normales Verb ("Anna transkribierte Block in…"). Der Badge zeigt die Gesamtzahl, nie die Blocknummern einzeln.
Type B — Rollup Rowsame actor + doc, 2h window
| Part | Classes | Real | Note |
| Count badge | inline-block bg-primary text-primary-fg text-xs font-bold px-2 py-0.5 rounded-sm mr-1 tracking-tight | 12 px / 700 | "20 Blöcke", "3 Dokumente", "5 Fotos" |
| Time range | text-sm text-ink-3 tabular-nums whitespace-nowrap | 14 px | en-dash between times, never hyphen |
| Verb copy | m.rollup_text_saved({ count }) | via Paraglide | Plural forms handled by Paraglide |
Type C · Comment row (with inline preview)
OR
"das war bei der Hochzeit von Onkel Heinrich, der hatte einen Dackel namens Bello und immer zwei Zigaretten in der Brusttasche — ganz typisch für ihn"
18:47
Type C — Comment with PreviewCOMMENT_ADDED, never rolled up
| Part | Classes | Real | Note |
| Preview text | text-[13px] italic leading-relaxed text-ink-2 mt-1 line-clamp-2 | 13 px / italic | Max 2 lines at ≥640 px; 1 line with ellipsis at <640 px |
| Preview length | Truncated server-side to ~140 chars + "…" | body | Never render unbounded comment content |
| Quote marks | Literal German quotes: "…" | U+201E / U+201C | Wrap the truncated string |
Type D · For-You lane row (read or unread mention in timeline)
@
MR
"schau mal, das ist Omas Handschrift von 1952 — ich glaube, das ist der Brief an Tante Elke"
14:32
Redundante Merkmale für die For-Dich-Lane.
- Linker Rand: 3 px brand-mint (light) / turquoise (dark). Nie "nur Farbe" — immer mit @ / ↩ Marker kombiniert.
- Hintergrund:
bg-accent-bg (~12 % Opazität). Contrast ratio mit Body-Text: 13.9:1 (unverändert, weil Text-Farbe gleich bleibt).
- Der @ / ↩ Marker im Kreis ist der primäre ikonografische Hinweis; Screenreader ignorieren ihn (
aria-hidden), weil die Textzeile ("erwähnte dich") die gleiche Info semantisch transportiert.
Type D — For-You Lane RowMENTION_CREATED, COMMENT_ADDED where mentionedUserId = currentUserId
| Part | Classes | Real | Note |
| Row container | flex items-start gap-3 py-3 border-l-[3px] border-accent bg-accent-bg/60 pl-3 -ml-3 rounded-sm | border 3 px | Negative margin compensates pl to keep vertical alignment with other rows |
| @ marker | w-6 h-6 rounded-full bg-accent-bg text-ink flex items-center justify-center font-bold shrink-0 mt-1 | 24 px | Glyph: @ for MENTION, ↩ (U+21A9) for REPLY |
| Unread dot (if unread) | absolute top-2 -left-1 w-2 h-2 rounded-full bg-accent | 8 px | Adds dot next to the @ marker; aria-label "ungelesen" |
Type D · Dark mode variant
@
MR
"schau mal, das ist Omas Handschrift von 1952 — ich glaube, das ist der Brief an Tante Elke"
14:32
05Interaction States
Every interactive control at every visible state: default, hover, focus, active (pressed), and where relevant disabled. Pointer-driven states (:hover) and keyboard-driven states (:focus-visible) are shown separately because they MUST render differently — the focus ring only appears for keyboard navigation.
5.1 Filter Pills
DefaultAlleAlle
HoverAlleAlle
FocusAlleAlle
PressedAlleAlle
→ Light · Inactive = gray-sand; Active = navy / white; Hover darkens; Focus ring = 2 px navy with 2 px offset.
DefaultAlleAlle
HoverAlleAlle
FocusAlleAlle
→ Dark · Inactive = muted-navy; Active = mint / navy; Focus ring = 2 px mint (9.2:1 on canvas).
Filter Pill Statesrole="radio" within role="radiogroup"
| State | Classes | Ratio | Note |
| Default inactive | bg-muted text-ink hover:bg-line px-4 py-2 rounded-full text-sm font-medium min-h-[44px] min-w-[44px] inline-flex items-center | 44 px min | Senior-friendly touch target |
| Default active | bg-primary text-primary-fg hover:bg-primary/90 | 14.5:1 light | Unambiguous when active |
| Focus visible | focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:outline-none | 2 px ring | Never :focus — only keyboard |
| Pressed | active:translate-y-px active:bg-primary/95 | 1 px nudge | Confirms the tap |
| Disabled | Not used — pills never disable; if no events match, filter still selectable and empty-state renders instead. | n/a | Avoid dead UI |
5.2 Für dich Row · Mark-as-read Button
Default@
Mama erwähnte dich in Brief Nr. 42
✓
Btn hover@
Mama erwähnte dich in Brief Nr. 42
✓
Btn focus@
Mama erwähnte dich in Brief Nr. 42
✓
Btn pressed@
Mama erwähnte dich in Brief Nr. 42
✓
Post-click (row fades out in ~200ms, then row removed from box; count decrements)@
Mama erwähnte dich in Brief Nr. 42
✓
Dismiss Buttonaria-label="Als gelesen markieren"
| State | Classes | Real |
| Default | w-11 h-11 rounded-sm border border-line bg-surface text-ink-3 flex items-center justify-center | 44 × 44 px |
| Hover | hover:bg-muted hover:text-ink hover:border-line-2 | — |
| Focus | focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:outline-none | 2 px |
| Active | active:translate-y-px active:bg-line | 1 px |
| After click | Row animates out over 200 ms, aria-live="polite" count badge updates, then DOM element removed | 200 ms |
5.3 "Alle gelesen" Action Button (page header)
DefaultAlle gelesen
HoverAlle gelesen
FocusAlle gelesen
PressedAlle gelesen
HiddenButton is not rendered when unreadCount === 0 (never a disabled state)
5.4 Timeline Row Interaction
Default
Hover (cursor pointer)
Focus (keyboard)
Timeline Rowrendered as <a href="/documents/{id}"> — entire row is the link
| State | Classes | Real | Note |
| Default | flex items-start gap-3 p-3 -mx-3 rounded-sm | 72 px target | Negative margin so hover-bg reaches beyond text |
| Hover | hover:bg-muted transition-colors | — | 150 ms transition; disabled under motion-reduce |
| Focus | focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:outline-none focus-visible:bg-muted | 2 px ring | Ring on row, not on inner link text |
| Click target | Whole row navigates; inner doc link uses pointer-events:none so outer row handles navigation. | — | Prevents nested-link a11y issues |
07Implementation Notes for Felix
Design is locked. This section is the bridge to the implementation plan that will be written next. It captures data, routing, and state decisions that affect code structure without dictating the code itself.
7.1 Routing
Route ChangesSvelteKit routing
| Route | Behavior | Note |
/chronik | New page — renders this spec | i18n slug: de=chronik, en=chronicle, es=cronica (via Paraglide routing) |
/chronik?filter=fuer-dich | Filter state in query param | Values: fuer-dich, hochgeladen, transkription, kommentare. Missing = Alle. |
/notifications | 301 redirect to /chronik | Preserves bookmarks; add in hooks.server.ts |
| Bell dropdown footer link | Changes target from /notifications → /chronik; label: "Zur Chronik →" | No other bell behavior change |
7.2 Data
API Calls from /chronikboth existing; one new endpoint optional
| Call | Existing? | Returns |
GET /api/notifications?read=false&size=20 | ✓ existing | Für-dich Box items (unread MENTION + REPLY) |
GET /api/dashboard/activity?limit=40 | ✓ existing (currently capped at 20) | Timeline items when filter is Alle. Raise server cap to 40 for this page. |
GET /api/dashboard/activity?limit=40&kinds=FILE_UPLOADED | ⊕ new query param | Filtered timeline. Query param: kinds (CSV of AuditKind). |
GET /api/notifications?size=40 | ✓ existing | "Für dich" filter view (read + unread). |
PATCH /api/notifications/{id}/read | ✓ existing | Dismiss-button on Für-dich row. |
POST /api/notifications/read-all | ✓ existing | "Alle gelesen" action. |
7.3 Rollup (backend)
Rollup logic lives in the backend.
- Modify
AuditLogQueryRepository.findActivityFeed to group consecutive rows where actor_id, document_id, kind match AND happened_at falls within 120 min of the previous row in the same group.
- Result record shape extends
ActivityFeedRow with count (int) and happenedAtRange (start..end). For single-event rows, count = 1 and the range is happenedAt..happenedAt.
DTO: extend ActivityFeedItemDTO with count and happenedAtUntil (optional, null for singletons).
- Rollup applies to these kinds only:
TEXT_SAVED, ANNOTATION_CREATED, BLOCK_REVIEWED, FILE_UPLOADED. COMMENT_ADDED and MENTION_CREATED stream 1:1.
- Add
kinds query param to GET /api/dashboard/activity. Default: all 6 (FILE_UPLOADED, TEXT_SAVED, BLOCK_REVIEWED, ANNOTATION_CREATED, COMMENT_ADDED, MENTION_CREATED). Never include STATUS_CHANGED or METADATA_UPDATED — they remain audit-only.
7.4 Frontend Structure
New Svelte Fileseach unit is one visible region
| File | Responsibility |
src/routes/chronik/+page.svelte | Page shell: back link, title, "Alle gelesen", Für-Dich-Box, pills, timeline. Composes the components below. |
src/routes/chronik/+page.server.ts | Load: /api/notifications?read=false + /api/dashboard/activity based on query filter. Actions: mark-all. |
src/lib/components/ChronikFuerDichBox.svelte | Unread mentions card with empty-state variant. Dismiss-button per row. |
src/lib/components/ChronikFilterPills.svelte | 5 pills, role="radiogroup", navigates via goto. |
src/lib/components/ChronikTimeline.svelte | Day-grouped timeline, renders a list of ChronikRow. |
src/lib/components/ChronikRow.svelte | Single row: 4 types (simple, rollup, comment, for-you). Props: item: ActivityFeedItemDTO, currentUserId. |
src/lib/components/ChronikEmptyState.svelte | Three variants: first-run, filter-no-result, inbox-zero (Für-dich). |
src/lib/components/ChronikErrorCard.svelte | Warning card with retry button; accepts onRetry. |
7.5 i18n keys (Paraglide)
New keys in messages/de.json (mirror in en.json, es.json)use existing feed_* keys where possible
| Key | de |
chronik_page_title | Chronik |
chronik_for_you_caption | Für dich |
chronik_for_you_count | {count} neu |
chronik_mark_read_aria | Als gelesen markieren |
chronik_mark_all_read | Alle gelesen |
chronik_inbox_zero_title | Keine neuen Erwähnungen |
chronik_inbox_zero_link | Ältere Erwähnungen ansehen → |
chronik_filter_all | Alle |
chronik_filter_for_you | Für dich |
chronik_filter_uploaded | Hochgeladen |
chronik_filter_transcription | Transkription |
chronik_filter_comments | Kommentare |
chronik_day_today | Heute |
chronik_day_yesterday | Gestern |
chronik_day_this_week | Diese Woche |
chronik_day_older | Älter |
chronik_rollup_text_saved | {actor} transkribierte {count} Blöcke in {doc} |
chronik_rollup_uploaded | {actor} lud {count} Dokumente hoch |
chronik_rollup_reviewed | {actor} überprüfte {count} Blöcke in {doc} |
chronik_empty_first_run_title | Noch nichts geschehen |
chronik_empty_first_run_body | Sobald jemand aus der Familie Dokumente hochlädt, transkribiert oder kommentiert, erscheint es hier. |
chronik_empty_filter_title | Nichts in dieser Ansicht |
chronik_error_title | Chronik konnte nicht geladen werden |
chronik_error_retry | Erneut laden |
7.6 Dashboard activity feed — fix the wrong link
Fix for existing bug: DashboardActivityFeed.svelte line ~37 currently links to /documents. Change href="/documents" → href="/chronik" and update feed_show_all label text if desired (e.g., "Zur Chronik" instead of the generic "Alle anzeigen").