Visual design specs for Milestone #14: - zeitstrahl-global-concepts.html — A/B/C exploration of the global timeline - zeitstrahl-final-spec.html — canonical Concept A (global + per-person Lebensweg) - zeitstrahl-event-editor-spec.html — curator event editor + document quick-action Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
419 lines
33 KiB
HTML
419 lines
33 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Zeitstrahl — Ereignis-Editor & Brief-Gruppierung · Quick-Action im Dokument · Familienarchiv</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=Tinos:ital,wght@0,400;0,700;1,400&family=Montserrat:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||
<style>
|
||
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
||
body{font-family:'Montserrat',system-ui,sans-serif;background:#ECEAE4;color:#1A1A1A;line-height:1.5;font-size:13px}
|
||
.page{max-width:1320px;margin:0 auto;padding:48px 32px 120px}
|
||
|
||
.mh{padding-bottom:24px;border-bottom:3px solid #012851;margin-bottom:48px}
|
||
.mh h1{font-size:23px;font-weight:900;color:#012851;letter-spacing:-.4px}
|
||
.mh p{font-size:13px;color:#555;max-width:790px;line-height:1.75;margin-top:8px}
|
||
.mh .byline{font-size:9px;color:#999;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;margin-top:10px}
|
||
.tag-row{display:flex;gap:6px;margin-top:12px;flex-wrap:wrap}
|
||
.tg{background:#012851;color:#a1dcd8;padding:2px 8px;border-radius:2px;font-size:8px;font-weight:700;letter-spacing:.8px;text-transform:uppercase}
|
||
.tg.mint{background:#a1dcd8;color:#012851}
|
||
.tg.slate{background:#607080;color:#e8edf2}
|
||
|
||
.sh{margin:60px 0 22px;padding-bottom:12px;border-bottom:2px solid #E0DDD6}
|
||
.sh h2{font-size:17px;font-weight:900;color:#012851}
|
||
.sh p{font-size:12.5px;color:#666;margin-top:5px;max-width:790px;line-height:1.65}
|
||
|
||
.callout{padding:13px 17px;border-radius:4px;font-size:12px;line-height:1.65;margin-bottom:18px}
|
||
.callout.navy{background:rgba(1,40,81,.06);border-left:3px solid #012851;color:#333}
|
||
.callout.mint{background:rgba(161,220,216,.18);border-left:3px solid #00c7b1;color:#1f3a3a}
|
||
.callout code{font-family:'Courier New',monospace;font-size:11px;background:#fff;padding:1px 4px;border-radius:2px}
|
||
.callout strong{font-weight:800;color:#012851}
|
||
|
||
/* desktop chrome */
|
||
.dchrome{background:#F0EFE9;border:1.5px solid #C4C0BA;border-radius:9px;overflow:hidden;box-shadow:0 8px 30px rgba(0,0,0,.12)}
|
||
.dbar{height:22px;background:#E2DFD8;border-bottom:1px solid #C4C0BA;display:flex;align-items:center;gap:4px;padding:0 9px}
|
||
.ddot{width:7px;height:7px;border-radius:50%;background:#C4BFB8}
|
||
.durl{flex:1;height:10px;background:#D2CEC8;border-radius:5px;margin:0 8px;max-width:360px}
|
||
.dnav{height:32px;background:#012851;display:flex;align-items:center;gap:13px;padding:0 16px}
|
||
.dnav .nlogo{font-family:'Tinos',serif;font-size:10px;color:#fff;font-weight:700}
|
||
.dnav .nlink{font-size:7.5px;color:rgba(255,255,255,.5);font-weight:700;text-transform:uppercase;letter-spacing:.4px}
|
||
.dnav .nlink.on{color:#fff;border-bottom:2px solid #a1dcd8;padding-bottom:9px}
|
||
.dnav .av{margin-left:auto;width:18px;height:18px;border-radius:50%;background:rgba(255,255,255,.12);display:flex;align-items:center;justify-content:center;font-size:6px;font-weight:800;color:rgba(255,255,255,.55)}
|
||
.dcanvas{background:#f0efe9;padding:20px 26px 26px}
|
||
|
||
/* form atoms (mirror real Tailwind look) */
|
||
.lbl{font-size:8.5px;font-weight:800;letter-spacing:1.2px;text-transform:uppercase;color:#6b7280;margin-bottom:6px}
|
||
.inp{border:1px solid #e4e2d7;border-radius:4px;background:#fff;padding:8px 11px;font-size:12px;color:#012851}
|
||
.inp.title{font-family:'Tinos',serif;font-size:22px;font-weight:700;padding:11px 13px}
|
||
.card{border:1px solid #e4e2d7;border-radius:6px;background:#fff;padding:15px;box-shadow:0 1px 3px rgba(0,0,0,.04)}
|
||
.card h3{font-size:8.5px;font-weight:800;letter-spacing:1.2px;text-transform:uppercase;color:#6b7280;margin-bottom:3px}
|
||
.card .hint{font-size:9.5px;color:#9a9a96;margin-bottom:9px}
|
||
.seg{display:inline-flex;border:1px solid #012851;border-radius:5px;overflow:hidden}
|
||
.seg span{font-size:10px;font-weight:700;padding:5px 13px;color:#012851}
|
||
.seg span.on{background:#012851;color:#fff}
|
||
.seg span+span{border-left:1px solid #012851}
|
||
.chips{border:1px solid #e4e2d7;border-radius:5px;background:#fff;padding:7px;display:flex;flex-wrap:wrap;gap:6px;align-items:center}
|
||
.chip-sel{display:inline-flex;align-items:center;gap:4px;background:#f5f4ef;border-radius:4px;padding:3px 8px;font-size:10px;color:#012851}
|
||
.chip-sel .x{color:#012851;opacity:.45;font-size:11px}
|
||
.chip-in{flex:1;min-width:90px;font-size:10.5px;color:#9a9a96;padding:3px 4px}
|
||
.btn{display:inline-flex;align-items:center;gap:6px;height:38px;padding:0 16px;border-radius:5px;font-size:12px;font-weight:600}
|
||
.btn.primary{background:#012851;color:#fff}
|
||
.btn.ghost{background:#fff;border:1px solid #e4e2d7;color:#012851}
|
||
.btn.danger{background:#fff;border:1px solid #e7c9c4;color:#c0392b}
|
||
.tagchip{display:inline-flex;align-items:center;gap:3px;font-size:8px;border-radius:9px;padding:2px 7px;color:#a0522d;background:#f6ece6}
|
||
.tagchip i{width:6px;height:6px;border-radius:2px;background:#a0522d;display:inline-block}
|
||
|
||
/* annotation callouts on mockups */
|
||
.anno{display:flex;gap:9px;align-items:flex-start;font-size:11.5px;color:#4a4a46;line-height:1.55;margin-bottom:7px}
|
||
.anno .n{flex-shrink:0;width:18px;height:18px;border-radius:50%;background:#012851;color:#a1dcd8;font-size:9px;font-weight:800;display:flex;align-items:center;justify-content:center;margin-top:1px}
|
||
.anno b{color:#012851}
|
||
.anno code{font-size:10px;background:#F0EFE9;padding:1px 4px;border-radius:2px}
|
||
.annogrid{display:grid;grid-template-columns:1fr 1fr;gap:6px 26px;margin-top:14px}
|
||
|
||
/* dropdown */
|
||
.dd{border:1px solid #e4e2d7;border-radius:6px;background:#fff;box-shadow:0 6px 18px rgba(0,0,0,.12);overflow:hidden;margin-top:3px}
|
||
.dd .opt{padding:7px 11px;font-size:11px;color:#012851;border-bottom:1px solid #f3f1ea;cursor:pointer}
|
||
.dd .opt:hover,.dd .opt.hl{background:#f5f4ef}
|
||
.dd .opt:last-child{border-bottom:none}
|
||
.dd .opt .d{font-size:8.5px;color:#9a9a96}
|
||
|
||
/* states grid */
|
||
.states{display:grid;grid-template-columns:repeat(2,1fr);gap:18px}
|
||
.state{border:1px solid #E0DDD6;border-radius:8px;background:#fff;overflow:hidden}
|
||
.state .sh2{background:#F4F2EC;border-bottom:1px solid #E0DDD6;padding:7px 12px;font-size:8.5px;font-weight:800;letter-spacing:.8px;text-transform:uppercase;color:#012851;display:flex;justify-content:space-between}
|
||
.state .sb{padding:13px}
|
||
.cap{font-size:11px;color:#888;font-style:italic;line-height:1.55;margin-top:8px}
|
||
|
||
/* impl-ref */
|
||
.impl-ref{background:#fff;border:1px solid #E0DDD6;border-radius:7px;overflow:hidden;margin-top:8px}
|
||
.impl-ref table{width:100%;border-collapse:collapse}
|
||
.impl-ref th{background:#012851;color:#fff;padding:8px 13px;text-align:left;font-size:8px;font-weight:800;letter-spacing:.6px;text-transform:uppercase}
|
||
.impl-ref td{padding:8px 13px;border-bottom:1px solid #F0EEE8;vertical-align:top;font-size:11px;color:#444;line-height:1.55}
|
||
.impl-ref tr:nth-child(even) td{background:#FAFAF7}
|
||
.impl-ref td:first-child{font-weight:700;color:#012851;white-space:nowrap;width:185px}
|
||
.impl-ref td code{font-size:9.5px;background:#F0EFE9;padding:1px 4px;border-radius:2px;font-family:'Courier New',monospace;color:#333}
|
||
hr{border:none;border-top:2px dashed #C8C4BE;margin:52px 0}
|
||
.note{font-size:11px;color:#888;font-style:italic;margin-top:10px;line-height:1.6}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="page">
|
||
|
||
<!-- ══ MASTHEAD ══ -->
|
||
<div class="mh">
|
||
<h1>Ereignis-Editor & Brief-Gruppierung · Quick-Action im Dokument</h1>
|
||
<p>Wie kuratierte Zeitstrahl-Ereignisse entstehen und wie Briefe gruppiert werden — von zwei Seiten in ein Datenmodell (<code style="font-family:monospace;font-size:12px">TimelineEvent.documents</code>): der <strong>Ereignis-Editor</strong> unter <code style="font-family:monospace;font-size:12px">/zeitstrahl/events/[id]/edit</code> (Kurator baut, verlinkt viele Briefe) und die <strong>Quick-Action im Dokument-Detail</strong> (beim Lesen schnell zuordnen). Beide bauen auf bereits ausgelieferten Komponenten auf.</p>
|
||
<div class="tag-row">
|
||
<span class="tg">Milestone #14 · Zeitstrahl</span>
|
||
<span class="tg mint">Reuse: GeschichteEditor · DocumentMultiSelect · PersonMultiSelect</span>
|
||
<span class="tg slate">WRITE_ALL</span>
|
||
</div>
|
||
<div class="byline">Familienarchiv · 2026-06-08 · Leonie Voss, UX Lead · gegründet auf Code: GeschichteEditor.svelte · DocumentMetadataDrawer.svelte · DocumentMultiSelect.svelte</div>
|
||
</div>
|
||
|
||
|
||
<!-- ══ 1 · TWO ENTRY POINTS ══ -->
|
||
<div class="sh">
|
||
<h2>1 · Zwei Einstiegspunkte, ein Datenmodell</h2>
|
||
<p>Manuelle Gruppierung = ein <code>TimelineEvent</code> mit verknüpften Dokumenten. Kuratoren arbeiten in beide Richtungen — wir bauen beide, statt eine zu erzwingen.</p>
|
||
</div>
|
||
<div class="states" style="grid-template-columns:1fr 1fr">
|
||
<div class="callout navy" style="margin:0">
|
||
<strong>A · Ereignis-zuerst</strong> — der Kurator baut den Zeitstrahl. <code>/zeitstrahl/events/new · [id]/edit</code> mit Dokument-Mehrfach-Picker = <b>Bulk-Linking</b> vieler Briefe auf einmal. Spiegelt 1:1 den <code>GeschichteEditor</code> (gleiche zwei-Spalten-Form, Sidebar-Picker, Sticky-Save-Bar).
|
||
</div>
|
||
<div class="callout mint" style="margin:0">
|
||
<strong>B · Dokument-zuerst</strong> — beim Lesen eines Briefs. Quick-Action im Dokument-Detail: bestehendes Ereignis wählen <i>oder</i> neu anlegen, verlinkt diesen einen Brief. Spiegelt die bestehende <b>Geschichten-Spalte</b> im Details-Drawer (<code>DocumentMetadataDrawer.svelte</code>).
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ══ 2 · EVENT EDITOR ══ -->
|
||
<div class="sh">
|
||
<h2>2 · Ereignis-Editor — <code style="font-size:14px">/zeitstrahl/events/[id]/edit</code></h2>
|
||
<p>Form-Actions-Muster, gegated mit <code>WRITE_ALL</code>. Layout & Verhalten 1:1 vom <code>GeschichteEditor</code> übernommen: Hauptspalte + Sidebar (<code>lg:grid-cols-[2fr_1fr]</code>), Sticky-Save-Bar, <code>beforeNavigate</code>-Warnung bei ungespeicherten Änderungen.</p>
|
||
</div>
|
||
|
||
<div class="dchrome" style="margin-bottom:16px">
|
||
<div class="dbar"><div class="ddot"></div><div class="ddot"></div><div class="ddot"></div><div class="durl"></div></div>
|
||
<div class="dnav"><span class="nlogo">Familienarchiv</span><span class="nlink">Dokumente</span><span class="nlink">Personen</span><span class="nlink on">Zeitstrahl</span><span class="nlink">Stammbaum</span><span class="av">KR</span></div>
|
||
<div class="dcanvas">
|
||
<div style="font-size:8px;font-weight:800;letter-spacing:1px;text-transform:uppercase;color:#8a8a86;margin-bottom:10px">‹ Zurück zum Zeitstrahl</div>
|
||
<div style="font-family:'Tinos',serif;font-size:18px;font-weight:700;color:#012851;margin-bottom:16px">Ereignis bearbeiten</div>
|
||
|
||
<div style="display:grid;grid-template-columns:2fr 1fr;gap:22px">
|
||
<!-- MAIN COLUMN -->
|
||
<div style="display:flex;flex-direction:column;gap:16px">
|
||
<!-- ① title -->
|
||
<div>
|
||
<div class="inp title" style="width:100%">Briefe von der Front</div>
|
||
</div>
|
||
<!-- ② type + ③ date/precision -->
|
||
<div style="display:flex;gap:22px;flex-wrap:wrap">
|
||
<div>
|
||
<div class="lbl">② Typ</div>
|
||
<div class="seg"><span class="on">Persönlich</span><span>Historisch</span></div>
|
||
</div>
|
||
<div>
|
||
<div class="lbl">③ Datum · Präzision</div>
|
||
<div style="display:flex;gap:6px;align-items:center">
|
||
<div class="inp" style="width:120px">1915</div>
|
||
<div class="inp" style="display:flex;align-items:center;gap:18px;color:#6b7280">Jahr <span style="font-size:8px">▾</span></div>
|
||
</div>
|
||
<div style="font-size:9px;color:#9a9a96;margin-top:5px;font-style:italic">Bei „Zeitspanne" erscheint ein zweites End-Datum-Feld. Bei „ca." / „Saison" passt sich nur das Label an.</div>
|
||
</div>
|
||
</div>
|
||
<!-- ④ description -->
|
||
<div>
|
||
<div class="lbl">④ Beschreibung <span style="color:#bbb;font-weight:600">· optional</span></div>
|
||
<div class="inp" style="width:100%;min-height:96px;color:#4a4a46;font-family:'Tinos',serif;line-height:1.6">Karls Feldpost von der Westfront, 1915 — wöchentliche Briefe an Elfriede und den neugeborenen Hans. Eine zusammenhängende Korrespondenz, die hier als Cluster gebündelt wird …</div>
|
||
<div style="font-size:9px;color:#9a9a96;margin-top:5px;font-style:italic">Schlichtes Textfeld (kein Rich-Text wie Geschichten) — Ereignisse sind kurze Notizen, keine Langform.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- SIDEBAR -->
|
||
<aside style="display:flex;flex-direction:column;gap:16px">
|
||
<!-- ⑤ linked letters = grouping -->
|
||
<div class="card" style="border-color:#a1dcd8;box-shadow:0 2px 10px rgba(161,220,216,.3)">
|
||
<h3 style="color:#012851">⑤ Verknüpfte Briefe · 24</h3>
|
||
<div class="hint">Diese Briefe bilden den Cluster. <code style="font-size:9px">DocumentMultiSelect</code></div>
|
||
<div class="chips">
|
||
<span class="chip-sel">✉ Westfront-Brief · Mär 1915 <span class="x">×</span></span>
|
||
<span class="chip-sel">✉ Feldpost Verdun · Jul 1915 <span class="x">×</span></span>
|
||
<span class="chip-sel">✉ Brief an Elfriede · Sep 1915 <span class="x">×</span></span>
|
||
<span class="chip-in">Brief suchen …</span>
|
||
</div>
|
||
</div>
|
||
<!-- ⑥ persons -->
|
||
<div class="card">
|
||
<h3>⑥ Beteiligte Personen</h3>
|
||
<div class="hint">Treibt die Lebensweg-Ansicht & Filter. <code style="font-size:9px">PersonMultiSelect</code></div>
|
||
<div class="chips">
|
||
<span class="chip-sel">Karl Raddatz <span class="x">×</span></span>
|
||
<span class="chip-sel">Elfriede Raddatz <span class="x">×</span></span>
|
||
<span class="chip-sel">Hans Raddatz <span class="x">×</span></span>
|
||
<span class="chip-in">Person suchen …</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
|
||
<!-- ⑦ sticky save bar -->
|
||
<div style="margin:18px -26px -26px;border-top:1px solid #e4e2d7;background:#fff;box-shadow:0 -2px 8px rgba(0,0,0,.05);padding:13px 26px;display:flex;align-items:center;justify-content:space-between">
|
||
<span style="font-size:10px;color:#9a9a96">Änderungen werden erst beim Speichern übernommen.</span>
|
||
<div style="display:flex;gap:8px">
|
||
<span class="btn danger">Löschen</span>
|
||
<span class="btn ghost">Abbrechen</span>
|
||
<span class="btn primary">Speichern</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="annogrid">
|
||
<div class="anno"><span class="n">①</span><span><b>Titel</b> — großes Serifen-Feld, wie der Geschichten-Titel. Pflichtfeld (Validierung bei Blur).</span></div>
|
||
<div class="anno"><span class="n">②</span><span><b>Typ</b> — <code>PERSONAL</code> / <code>HISTORICAL</code> Segmented-Control. Steuert Rendering (Mint-Pille vs. Welt-Band).</span></div>
|
||
<div class="anno"><span class="n">③</span><span><b>Datum + Präzision</b> — geteilte <code>DatePrecisionInput</code> (gleiche Logik wie Dokument-Datum, <code>metaDatePrecision</code>). „Zeitspanne" blendet End-Datum ein.</span></div>
|
||
<div class="anno"><span class="n">④</span><span><b>Beschreibung</b> — optionales Textfeld (<code>TEXT</code>), bewusst schlicht.</span></div>
|
||
<div class="anno"><span class="n">⑤</span><span><b>Verknüpfte Briefe</b> — <b>hier wird gruppiert.</b> Wiederverwendung von <code>DocumentMultiSelect</code> (Typeahead, Chips, Hidden-Inputs).</span></div>
|
||
<div class="anno"><span class="n">⑥</span><span><b>Beteiligte Personen</b> — <code>PersonMultiSelect</code>. Bestimmt, in welchem „Lebensweg" das Ereignis auftaucht.</span></div>
|
||
<div class="anno"><span class="n">⑦</span><span><b>Sticky-Save-Bar</b> — Speichern primär, Abbrechen sekundär, Löschen nur im Edit-Modus (mit Bestätigung).</span></div>
|
||
<div class="anno"><span class="n">+</span><span><b>/new</b> — leeres Formular. Mit <code>?documentId=…</code> ist Feld ⑤ vorbefüllt (aus der Quick-Action, §4-D).</span></div>
|
||
</div>
|
||
|
||
|
||
<!-- ══ 3 · GROUPING / DOCUMENT PICKER ══ -->
|
||
<div class="sh">
|
||
<h2>3 · Brief-Gruppierung im Editor — der Dokument-Picker</h2>
|
||
<p>Feld ⑤ ist der unveränderte <code>DocumentMultiSelect</code>: Tippen sucht über <code>/api/documents/search?q=…</code> (debounced 300 ms), Treffer mit ehrlichem Datums-Label, bereits gewählte werden gefiltert. Jeder Klick fügt einen Brief zum Cluster.</p>
|
||
</div>
|
||
|
||
<div class="states">
|
||
<div class="state">
|
||
<div class="sh2"><span>Suche aktiv — Dropdown</span><span style="color:#9a9a96">DocumentMultiSelect</span></div>
|
||
<div class="sb">
|
||
<div class="chips" style="margin-bottom:0">
|
||
<span class="chip-sel">✉ Westfront-Brief · Mär 1915 <span class="x">×</span></span>
|
||
<span class="chip-sel">✉ Feldpost Verdun · Jul 1915 <span class="x">×</span></span>
|
||
<span class="chip-in" style="color:#012851">Verdun▏</span>
|
||
</div>
|
||
<div class="dd">
|
||
<div class="opt hl">Feldpost aus Verdun <span class="d">· Brief · Juli 1915</span></div>
|
||
<div class="opt">Brief aus dem Verdun-Lazarett <span class="d">· Brief · August 1916</span></div>
|
||
<div class="opt">Rückkehr aus Verdun <span class="d">· Brief · ca. 1917</span></div>
|
||
</div>
|
||
<div class="cap">Label = <code style="font-size:10px">title · formatDocumentDate(precision)</code>. Bereits verknüpfte Briefe erscheinen nicht in den Treffern (Dedup).</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="state">
|
||
<div class="sh2"><span>Inline „+ Ereignis" am Jahres-Band</span><span style="color:#9a9a96">Zeitstrahl</span></div>
|
||
<div class="sb">
|
||
<div style="position:relative;padding-left:20px">
|
||
<div style="position:absolute;left:6px;top:2px;bottom:2px;width:2px;background:linear-gradient(#a1dcd8,#012851)"></div>
|
||
<div style="font-family:'Tinos',serif;font-size:13px;font-weight:700;color:#012851;margin-bottom:8px">1915</div>
|
||
<div style="background:#FAF9F5;border:1px solid #eeede8;border-radius:4px;padding:7px 9px;margin-bottom:8px"><div style="font-size:9.5px;font-weight:700;color:#012851">✉ 24 Briefe</div><div style="font-size:8px;color:#9a9a96">Monats-Dichte ▾</div></div>
|
||
<button style="display:inline-flex;align-items:center;gap:5px;border:1px dashed #a1dcd8;background:#fff;border-radius:6px;padding:5px 11px;font-size:10px;font-weight:600;color:#012851">+ Ereignis aus diesem Jahr anlegen</button>
|
||
</div>
|
||
<div class="cap">Kuratoren können auch direkt im Zeitstrahl ein Ereignis anlegen — öffnet denselben Editor, Jahr & Briefe des Bandes vorbefüllt.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<hr>
|
||
|
||
<!-- ══ 4 · QUICK ACTION IN DOCUMENT DETAIL ══ -->
|
||
<div class="sh">
|
||
<h2>4 · Quick-Action im Dokument-Detail — wo sie lebt</h2>
|
||
<p>Die Dokument-Detailseite ist ein <b>vollflächiger Viewer ohne Sidebar</b> (<code>fixed inset</code>). Aktions-Flächen gibt es nur zwei: die <code>DocumentTopBar</code> und den aufklappbaren <b>Details-Drawer</b>. Die Quick-Action lebt an beiden — primär als <b>„Zeitstrahl"-Spalte im Drawer</b> (spiegelt die Geschichten-Spalte), plus ein <b>Top-Bar-Button</b> für den Ein-Klick-Weg.</p>
|
||
</div>
|
||
|
||
<div class="callout navy"><strong>Warum der Details-Drawer der richtige Ort ist:</strong> Er zeigt heute schon, <i>wozu ein Brief gehört</i> — Personen, Schlagwörter und <b>Geschichten</b> (mit „Zuordnen"-Aktion, gegated über <code>canBlogWrite</code>, <code>DocumentMetadataDrawer.svelte:210</code>). Zeitstrahl-Ereignisse sind strukturell identisch („dieser Brief gehört zu diesen Ereignissen") und bekommen daher eine gleichwertige vierte/fünfte Spalte. Konsistent & auffindbar dort, wo Nutzer ohnehin „Zugehörigkeit" suchen.</div>
|
||
|
||
<div class="dchrome" style="margin-bottom:16px">
|
||
<div class="dbar"><div class="ddot"></div><div class="ddot"></div><div class="ddot"></div><div class="durl"></div></div>
|
||
<!-- document topbar -->
|
||
<div style="background:#fff;border-bottom:1px solid #e4e2d7;box-shadow:0 1px 3px rgba(0,0,0,.05);display:flex;align-items:center;height:54px">
|
||
<div style="width:3px;height:100%;background:#012851"></div>
|
||
<div style="width:34px;display:flex;justify-content:center;color:#6b7280;font-size:14px">‹</div>
|
||
<div style="width:1px;height:22px;background:#e4e2d7;margin:0 6px"></div>
|
||
<div style="flex:0 1 auto;min-width:0;padding-right:10px">
|
||
<div style="font-family:'Tinos',serif;font-size:13px;font-weight:700;color:#012851;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">Brief über die Lage an der Westfront</div>
|
||
<div style="font-size:8.5px;color:#6b7280">März 1915</div>
|
||
</div>
|
||
<div style="display:flex;gap:3px;margin-left:6px"><span style="width:20px;height:20px;border-radius:50%;background:#012851;color:#fff;font-size:7px;display:flex;align-items:center;justify-content:center">KR</span><span style="font-size:9px;color:#9a9a96;align-self:center">→</span><span style="width:20px;height:20px;border-radius:50%;background:#5a8a6a;color:#fff;font-size:7px;display:flex;align-items:center;justify-content:center">ER</span></div>
|
||
<div style="margin-left:auto;display:flex;align-items:center;gap:7px;padding-right:14px">
|
||
<!-- Details toggle (active) -->
|
||
<span style="display:inline-flex;align-items:center;gap:5px;background:#012851;color:#fff;border-radius:5px;font-size:10px;font-weight:600;padding:6px 11px">Details ▴</span>
|
||
<div style="width:1px;height:22px;background:#e4e2d7"></div>
|
||
<!-- action buttons -->
|
||
<span style="display:inline-flex;align-items:center;gap:4px;border:1px solid #e4e2d7;border-radius:5px;font-size:10px;font-weight:600;color:#012851;padding:6px 11px">✎ Transkribieren</span>
|
||
<!-- NEW: Zeitstrahl quick button -->
|
||
<span style="display:inline-flex;align-items:center;gap:4px;background:#a1dcd8;color:#012851;border-radius:5px;font-size:10px;font-weight:700;padding:6px 11px">⊕ Zeitstrahl</span>
|
||
<span style="display:inline-flex;align-items:center;gap:4px;border:1px solid #e4e2d7;border-radius:5px;font-size:10px;color:#012851;padding:6px 9px">⤓</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- metadata drawer (opened) -->
|
||
<div style="background:#fff;border-bottom:1px solid #e4e2d7;padding:20px 24px">
|
||
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:24px">
|
||
<!-- Details -->
|
||
<div>
|
||
<div class="lbl">Details</div>
|
||
<div style="font-size:8px;font-weight:600;color:#9a9a96;margin-bottom:1px">Datum</div><div style="font-family:'Tinos',serif;font-size:12px;color:#012851;margin-bottom:8px">März 1915</div>
|
||
<div style="font-size:8px;font-weight:600;color:#9a9a96;margin-bottom:1px">Ort</div><div style="font-family:'Tinos',serif;font-size:12px;color:#012851;margin-bottom:8px">Westfront</div>
|
||
<div style="font-size:8px;font-weight:600;color:#9a9a96;margin-bottom:1px">Status</div><div style="font-family:'Tinos',serif;font-size:12px;color:#012851">Transkribiert</div>
|
||
</div>
|
||
<!-- Personen -->
|
||
<div>
|
||
<div class="lbl">Personen</div>
|
||
<div style="display:flex;align-items:center;gap:7px;margin-bottom:6px"><span style="width:26px;height:26px;border-radius:50%;background:#012851;color:#fff;font-size:8px;display:flex;align-items:center;justify-content:center">KR</span><span style="font-family:'Tinos',serif;font-size:12px;color:#012851">Karl Raddatz</span></div>
|
||
<div style="display:flex;align-items:center;gap:7px"><span style="width:26px;height:26px;border-radius:50%;background:#5a8a6a;color:#fff;font-size:8px;display:flex;align-items:center;justify-content:center">ER</span><span style="font-family:'Tinos',serif;font-size:12px;color:#012851">Elfriede Raddatz</span></div>
|
||
</div>
|
||
<!-- Schlagwörter -->
|
||
<div>
|
||
<div class="lbl">Schlagwörter</div>
|
||
<div style="display:flex;flex-wrap:wrap;gap:5px"><span style="background:#f5f4ef;border-radius:3px;font-size:8px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:#012851;padding:3px 7px">Krieg</span><span style="background:#f5f4ef;border-radius:3px;font-size:8px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:#012851;padding:3px 7px">Briefe von der Front</span></div>
|
||
</div>
|
||
<!-- NEW: Zeitstrahl column -->
|
||
<div style="border-left:2px solid #eef6f5;padding-left:18px;margin-left:-6px">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:9px">
|
||
<span class="lbl" style="margin:0;color:#012851">Zeitstrahl</span>
|
||
<span style="font-size:9px;font-weight:600;color:#6b7280">+ Zuordnen</span>
|
||
</div>
|
||
<!-- linked event -->
|
||
<div style="border:1px solid #e4e2d7;border-radius:5px;padding:7px 9px;margin-bottom:8px">
|
||
<div style="display:flex;align-items:center;justify-content:space-between"><span style="font-family:'Tinos',serif;font-size:11px;font-weight:700;color:#012851">Briefe von der Front</span><span style="color:#9a9a96;font-size:11px">×</span></div>
|
||
<div style="font-size:8px;color:#9a9a96;margin-top:1px">1915 · 24 Briefe · persönlich</div>
|
||
<span class="tagchip" style="margin-top:5px"><i></i>Krieg</span>
|
||
</div>
|
||
<!-- quick add row -->
|
||
<div style="display:flex;gap:6px">
|
||
<span style="flex:1;border:1px solid #e4e2d7;border-radius:4px;font-size:9px;color:#9a9a96;padding:5px 8px">Ereignis suchen …</span>
|
||
<span style="background:#012851;color:#fff;border-radius:4px;font-size:9px;font-weight:600;padding:5px 8px;white-space:nowrap">+ Neu</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div style="height:120px;background:repeating-linear-gradient(45deg,#ececec,#ececec 8px,#e4e4e4 8px,#e4e4e4 16px);display:flex;align-items:center;justify-content:center;color:#aaa;font-size:10px">↓ PDF-Viewer (Brief-Scan) …</div>
|
||
</div>
|
||
|
||
<div class="annogrid">
|
||
<div class="anno"><span class="n">A</span><span><b>Top-Bar-Button „⊕ Zeitstrahl"</b> — Mint-Akzent im Aktions-Cluster (<code>DocumentTopBarActions</code>). Öffnet ein kleines Popover zum Ein-Klick-Zuordnen, ohne den Drawer zu öffnen. Im Mobile-Menü als Eintrag.</span></div>
|
||
<div class="anno"><span class="n">B</span><span><b>„Zeitstrahl"-Spalte im Details-Drawer</b> — neue Spalte neben Geschichten. Zeigt verknüpfte Ereignisse (Titel · Datum · Tag-Chip), Unlink über <code>×</code>, plus Quick-Add-Zeile. Nur sichtbar/aktiv bei <code>canWrite</code>.</span></div>
|
||
<div class="anno"><span class="n">C</span><span><b>Quick-Add-Zeile</b> — Typeahead „Ereignis suchen …" (sofortiges Verlinken, keine Navigation) + <b>„+ Neu"</b>.</span></div>
|
||
<div class="anno"><span class="n">D</span><span><b>„+ Neu"</b> → <code>/zeitstrahl/events/new?documentId={id}</code> — öffnet den Editor (§2) mit diesem Brief in Feld ⑤ vorbefüllt. Spiegelt <code>/geschichten/new?documentId=</code>.</span></div>
|
||
</div>
|
||
|
||
|
||
<!-- ══ 5 · QUICK-ADD STATES ══ -->
|
||
<div class="sh"><h2>5 · Quick-Action — Zustände</h2><p>Der Typeahead in der Zeitstrahl-Spalte (oder im Top-Bar-Popover). Gleiches Muster wie <code>DocumentMultiSelect</code>, nur sucht es Ereignisse statt Dokumente.</p></div>
|
||
|
||
<div class="states" style="grid-template-columns:repeat(2,1fr)">
|
||
<div class="state">
|
||
<div class="sh2"><span>A · Nicht zugeordnet</span></div>
|
||
<div class="sb">
|
||
<div style="font-size:10px;color:#9a9a96;font-style:italic;margin-bottom:9px">Noch keinem Ereignis zugeordnet.</div>
|
||
<div style="display:flex;gap:6px"><span style="flex:1;border:1px solid #e4e2d7;border-radius:4px;font-size:10px;color:#9a9a96;padding:6px 9px">Ereignis suchen …</span><span class="btn primary" style="height:30px;font-size:10px;padding:0 11px">+ Neu</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="state">
|
||
<div class="sh2"><span>B · Suche — Treffer</span></div>
|
||
<div class="sb">
|
||
<div style="border:1px solid #012851;border-radius:4px;font-size:10px;color:#012851;padding:6px 9px;margin-bottom:0">Front▏</div>
|
||
<div class="dd">
|
||
<div class="opt hl">Briefe von der Front <span class="d">· 1915 · 24 Briefe</span></div>
|
||
<div class="opt">Kriegsausbruch <span class="d">· 1914 · 6 Briefe</span></div>
|
||
<div class="opt" style="color:#012851;font-weight:600">+ „Front" als neues Ereignis anlegen</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="state">
|
||
<div class="sh2"><span>C · Zugeordnet</span></div>
|
||
<div class="sb">
|
||
<div style="border:1px solid #e4e2d7;border-radius:5px;padding:7px 9px"><div style="display:flex;align-items:center;justify-content:space-between"><span style="font-family:'Tinos',serif;font-size:11px;font-weight:700;color:#012851">Briefe von der Front</span><span style="font-size:9px;color:#2e7d57">✓ verknüpft <span style="color:#9a9a96">×</span></span></div><span class="tagchip" style="margin-top:5px"><i></i>Krieg</span></div>
|
||
<div class="cap">Sofortiges Verlinken (POST). Toast „Zum Ereignis hinzugefügt", <code style="font-size:10px">aria-live</code>. Unlink über <code>×</code> (DELETE).</div>
|
||
</div>
|
||
</div>
|
||
<div class="state">
|
||
<div class="sh2"><span>D · Mehrfach zugeordnet</span></div>
|
||
<div class="sb">
|
||
<div style="display:flex;flex-direction:column;gap:5px">
|
||
<div style="border:1px solid #e4e2d7;border-radius:5px;padding:5px 9px;display:flex;justify-content:space-between"><span style="font-family:'Tinos',serif;font-size:10.5px;color:#012851">Briefe von der Front</span><span style="font-size:9px;color:#9a9a96">×</span></div>
|
||
<div style="border:1px solid #e4e2d7;border-radius:5px;padding:5px 9px;display:flex;justify-content:space-between"><span style="font-family:'Tinos',serif;font-size:10.5px;color:#012851">Weihnachten 1915</span><span style="font-size:9px;color:#9a9a96">×</span></div>
|
||
</div>
|
||
<div class="cap">Ein Brief darf zu mehreren Ereignissen gehören (ManyToMany) — alle werden gelistet.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ══ 6 · TOKENS ══ -->
|
||
<div class="sh"><h2>6 · Wiederverwendete Bausteine & Tokens</h2></div>
|
||
<div class="callout mint"><strong>Maximal wiederverwenden:</strong> <code>DocumentMultiSelect</code> (Brief-Gruppierung, unverändert) · <code>PersonMultiSelect</code> (Beteiligte) · <code>GeschichteEditor</code>-Layout (zwei Spalten, Sticky-Save, <code>beforeNavigate</code>) · <code>DocumentMetadataDrawer</code>-Spaltenmuster (Quick-Action) · <code>useUnsavedWarning</code> · <code>formatDocumentDate</code> / <code>DatePrecision</code>. Brand-Tokens wie im Zeitstrahl-Spec: Navy <code>#012851</code>, Mint <code>#a1dcd8</code>, Linie <code>#e4e2d7</code>, ink-3 <code>#6b7280</code>, danger <code>#c0392b</code>; Serifen-Titel (Tinos), Sans-Chrome (Montserrat).</div>
|
||
|
||
|
||
<!-- ══ 7 · IMPL-REF ══ -->
|
||
<div class="sh"><h2>7 · Implementierungs-Referenz & Barrierefreiheit</h2></div>
|
||
<div class="impl-ref">
|
||
<table>
|
||
<tr><th>Baustein</th><th>Datei / Endpoint</th><th>Verantwortung</th></tr>
|
||
<tr><td>Editor-Route (neu)</td><td><code>/zeitstrahl/events/new · [id]/edit</code></td><td><code>+page.server.ts</code> (Form-Actions, <code>WRITE_ALL</code>) + <code>+page.svelte</code>; <code>?documentId=</code> vorbefüllt Feld ⑤</td></tr>
|
||
<tr><td>Editor-Komponente (neu)</td><td><code>TimelineEventEditor.svelte</code></td><td>Spiegelt <code>GeschichteEditor</code>: Titel, Typ, Datum+Präzision, Beschreibung; Sidebar-Picker; Sticky-Save; <code>beforeNavigate</code></td></tr>
|
||
<tr><td>Brief-Gruppierung (reuse)</td><td><code>DocumentMultiSelect.svelte</code></td><td>Unverändert — Typeahead <code>/api/documents/search</code>, Chips, Hidden-Inputs <code>documentIds</code></td></tr>
|
||
<tr><td>Personen (reuse)</td><td><code>PersonMultiSelect.svelte</code></td><td>Unverändert — Beteiligte Personen</td></tr>
|
||
<tr><td>Datum + Präzision</td><td><code>DatePrecisionInput</code> (geteilt)</td><td>Wie Dokument-Datum (<code>metaDatePrecision</code>); „Zeitspanne" → End-Datum; <code>formatDocumentDate</code> fürs Label</td></tr>
|
||
<tr><td>Quick-Action-Spalte (neu)</td><td><code>DocumentTimelineColumn.svelte</code></td><td>Im <code>DocumentMetadataDrawer</code> neben Geschichten; verknüpfte Ereignisse + Quick-Add; nur bei <code>canWrite</code></td></tr>
|
||
<tr><td>Quick-Add-Picker (neu)</td><td><code>DocumentTimelineEventPicker.svelte</code></td><td>Ereignis-Typeahead; sofort verlinken oder <code>?documentId=</code> zum Editor; auch im Top-Bar-Popover</td></tr>
|
||
<tr><td>Top-Bar-Button (neu)</td><td><code>DocumentTopBarActions</code> · <code>DocumentMobileMenu</code></td><td>„⊕ Zeitstrahl"-Button (canWrite); öffnet Quick-Add-Popover</td></tr>
|
||
<tr><td>Backend — CRUD</td><td><code>POST · PUT · DELETE /api/timeline/events</code></td><td><code>TimelineEventController</code>, <code>WRITE_ALL</code>; <code>TimelineEventRequest</code> mit <code>documentIds</code> / <code>personIds</code></td></tr>
|
||
<tr><td>Backend — Link/Unlink</td><td><code>PUT /api/timeline/events/{id}</code></td><td>Verlinken/Lösen läuft über das Event-Update (<code>documents</code>-Set); kein neuer ErrorCode nötig</td></tr>
|
||
<tr><td>Barrierefreiheit</td><td>—</td><td>Picker-Dropdowns Tastatur-navigierbar (↑↓↵), <code>aria-live</code> für „verknüpft/gelöst"; 44px-Ziele; sichtbarer Fokus-Ring; Löschen/Unlink mit Bestätigung</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="note">Offene Designentscheidung: Soll der Top-Bar-Button (A) MVP sein oder reicht zunächst die Drawer-Spalte (B)? Empfehlung: <b>B als MVP</b> (spiegelt Geschichten exakt, geringster Aufwand), A als schneller Nachzug.</div>
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|