2 Commits
Author SHA1 Message Date
hnzio 22ae3a68d6 Release 0.5.7 2026-10-23 00:14:43 +02:00
hnzio dfa236390d Release 0.5.6 2026-10-22 20:54:46 +02:00
6 changed files with 497 additions and 185 deletions

No files matched your search

+49
View File
@@ -257,3 +257,52 @@
programmatisch geprüft
- vollständige Unit- und E2E-Matrix gemäß Auftrag nicht erneut ausgeführt
- `git diff --check`: erfolgreich
## Oberflächenkorrektur 0.5.6
| Kriterium | Nachweis | Stand |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------- | --------------------- |
| Gold-/Violettlicht und Glasflächen sichtbar | Fundus und Editor in Light/Dark auf Desktop und Mobil visuell sowie über berechnete Werte geprüft | erfüllt am 22.10.2026 |
| Schreibflächen ruhig und eindeutig abgegrenzt | deckende Feldfarbe, Kontur und goldener Fokus im geöffneten Piece-Editor geprüft | erfüllt am 22.10.2026 |
| Neuanlage und Suche unmittelbar erreichbar | sichtbare Fundusaktionen sowie geöffnete Vorlagenauswahl auf Desktop und Mobil geprüft | erfüllt am 22.10.2026 |
| Zusatzfilter und Zeilenaktionen zugänglich | native Aufklappelemente für Filter und Aktionen per Browserinteraktion geprüft | erfüllt am 22.10.2026 |
| Funduszeilen per Tastatur zu öffnen | erster Titeleintrag fokussiert, mit Eingabetaste geöffnet und Editoraufruf geprüft | erfüllt am 22.10.2026 |
| Lightmode und Smartphone ohne Seitenüberlauf | Chromium-Messung bei 1440 × 1000 und 390 × 844 Pixeln in beiden Themes | erfüllt am 22.10.2026 |
## Ausgeführte Prüfungen Oberflächenkorrektur 0.5.6
- `npm run check`: 0 Fehler und 0 Warnungen
- gezielter Chromium-Lauf für Fundus und geöffneten Piece-Editor bei
1440 × 1000 und 390 × 844 Pixeln in Light/Dark ohne Konsolenfehler oder
horizontalen Seitenüberlauf
- Neuanlage, Zusatzfilter, Aktionsmenü, Tastaturöffnung, Glaswerte und goldener
Fokus automatisiert kontrolliert; alle erzeugten Desktop-/Mobilaufnahmen
visuell geprüft
- Produktionsbuild sowie vollständige Unit- und E2E-Matrix gemäß Auftrag nicht
ausgeführt
- `git diff --check`: erfolgreich
## Materialkorrektur 0.5.7
| Kriterium | Nachweis | Stand |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------ | --------------------- |
| Hintergrundlicht im Arbeitsbereich sichtbar | Fundus und Sendungsplanung ohne Popup in Dark/Light auf Desktop und Mobil visuell geprüft | erfüllt am 23.10.2026 |
| Popup erhält die Lichtstimmung | Editor mit leichtem `46%`-Backdrop und `6px` Blur gegen Ansicht ohne Popup verglichen | erfüllt am 23.10.2026 |
| Verschachtelte Ablaufkarten werden dunkler | berechnete RGBA-Werte von Außenglas, Abschnitt, Piece und Aktionsgruppe kontrolliert | erfüllt am 23.10.2026 |
| Graue Sonderflächen entfernt | aktive Tabs, private Recherche, Quellen-/Materialflächen und Aktionsgruppen visuell geprüft | erfüllt am 23.10.2026 |
| Schreibfelder bleiben ruhig und klar | deckende Feldfüllung, feine Kontur und unveränderter Goldfokus in beiden Editorbereichen geprüft | erfüllt am 23.10.2026 |
| Lightmode und Smartphone ohne Seitenüberlauf | Chromium-Messung bei 1440 × 1000 und 390 × 844 Pixeln in beiden Themes | erfüllt am 23.10.2026 |
## Ausgeführte Prüfungen Materialkorrektur 0.5.7
- `npm run check`: 0 Fehler und 0 Warnungen
- `npm run build`: erfolgreich mit `@sveltejs/adapter-node`
- berechnete Styles vor und nach der Korrektur für App-Hintergrund, Navigation,
Ablauf-Panel, Abschnitte, Pieces, Aktionsgruppen, Dialog, Backdrop, Tabs,
Rechercheflächen und Schreibfelder kontrolliert
- gezielter Chromium-Lauf für Sendungsplanung sowie Piece-Editor mit
„Sendungstext“ und „Recherche & Quellen“ bei 1440 × 1000 und 390 × 844 Pixeln
in Light/Dark ohne Konsolenfehler oder horizontalen Seitenüberlauf
- Desktop-/Mobilaufnahmen mit und ohne Popup visuell verglichen
- vollständige Funktionstests gemäß Auftrag nicht ausgeführt
- `git diff --check`: erfolgreich
+39
View File
@@ -7,6 +7,45 @@ Anmeldung, Rollen, persistente Inhaltsbearbeitung, Sendungsplanung,
Live-Steuerung, Präsentationsausgabe und lokaler Betriebsweg sind dokumentiert.
Etappe 6 wurde nicht begonnen.
## Materialkorrektur 0.5.7
- statische Gold-/Blauviolettlichter so positioniert und verstärkt, dass sie im
eigentlichen Arbeitsbereich statt fast ausschließlich hinter der Navigation
sichtbar werden
- gemeinsame Materialtokens auf Außenglas, dunkle Innenfläche und tiefe
Ablaufkarte reduziert; verschachtelte Abschnitte, Pieces und Aktionsgruppen
werden nach innen dunkler statt heller und blaugrau
- aktive Editortabs transparent goldgetönt und private Recherche sowie
Quellen-/Materialbereiche auf transparente Nachtblauflächen zurückgeführt
- Dialog-Backdrop von starker Abdunklung und Unschärfe auf eine leichtere
Trennung reduziert, sodass die Lichtstimmung bei geöffnetem Editor erhalten
bleibt
- deckende Schreibfelder, Goldfokus, Lightmode, Mobilansicht und lesbare
Komponentenfüllungen ohne verfügbaren Blur bleiben erhalten
Die berechneten Hintergründe, Transparenzen, Filter und Begrenzungseigenschaften
wurden vor und nach der Korrektur in Chromium kontrolliert. Sendungsplanung,
Sendungstext und Recherche wurden bei 1440 × 1000 und 390 × 844 Pixeln in beiden
Themes visuell geprüft.
## Oberflächenkorrektur 0.5.6
- sichtbare statische Gold- und Blauviolettlichter hinter den halbtransparenten
Navigations- und Editorflächen
- klarere Glaswirkung in Navigation sowie Kopf, Tabs und Fuß des Piece-Editors;
Schreibflächen bleiben deckend, ruhig und goldfokussiert
- Fundus mit dauerhaft sichtbarer Suche und Neuanlage, aufklappbaren Zusatzfiltern
und inhaltsorientierten, vollständig anklickbaren Zeilen
- vorhandene Vorschaubilder beziehungsweise kleine Symbolplatzhalter sowie
gebündelte Menüs für Duplizieren und Archivieren
- bestehende Server-Actions, Filterlogik und Editor-Bereiche unverändert
Geprüft wurden `npm run check` sowie Fundus und geöffneter Piece-Editor in
Chromium bei 1440 × 1000 und 390 × 844 Pixeln in Light/Dark. Die gezielte
Kontrolle umfasste Tastaturöffnung, Menüs, Fokus, Glaswerte, Seitenüberlauf und
visuell geprüfte Screenshots. Produktionsbuild und vollständige Testmatrix wurden
gemäß Auftrag nicht ausgeführt.
## Oberflächenkorrektur 0.5.5
- dunkle Grundfläche mit sehr zurückhaltenden Gold-/Cyan-Lichtfeldern innerhalb
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "sendewerk",
"version": "0.5.5",
"version": "0.5.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sendewerk",
"version": "0.5.5",
"version": "0.5.7",
"dependencies": {
"@node-rs/argon2": "^2.2.2",
"better-sqlite3": "^13.0.3",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "sendewerk",
"private": true,
"version": "0.5.5",
"version": "0.5.7",
"type": "module",
"engines": {
"node": ">=22.17 <25"
+286 -80
View File
@@ -16,6 +16,11 @@
--panel-soft: rgb(226 233 242 / 72%);
--glass: rgb(252 254 255 / 68%);
--glass-strong: rgb(250 252 255 / 84%);
--glass-chrome: rgb(252 254 255 / 74%);
--material-inset: rgb(235 241 248 / 82%);
--material-deep: rgb(225 233 243 / 90%);
--ambient-gold: rgb(231 185 87 / 20%);
--ambient-violet: rgb(102 89 184 / 15%);
--field: #f8fbfe;
--text: #172033;
--text-muted: #5d6a7d;
@@ -46,11 +51,16 @@
color-scheme: dark;
--bg: #0b1220;
--bg-elevated: rgb(11 18 32 / 68%);
--panel: rgb(18 31 52 / 72%);
--panel: rgb(12 24 42 / 72%);
--panel-strong: #111d30;
--panel-soft: rgb(28 43 65 / 62%);
--glass: rgb(15 27 46 / 62%);
--glass-strong: rgb(17 30 51 / 82%);
--panel-soft: rgb(7 16 30 / 76%);
--glass: rgb(10 22 39 / 64%);
--glass-strong: rgb(10 22 39 / 84%);
--glass-chrome: rgb(9 20 36 / 72%);
--material-inset: rgb(6 15 28 / 72%);
--material-deep: rgb(4 11 22 / 82%);
--ambient-gold: rgb(231 185 87 / 32%);
--ambient-violet: rgb(102 89 184 / 24%);
--field: #101a2b;
--text: #fff7e8;
--text-muted: #a9b6c8;
@@ -88,16 +98,8 @@ body {
min-width: 20rem;
min-height: 100vh;
background:
radial-gradient(
ellipse 62rem 38rem at 88% -8%,
color-mix(in srgb, var(--gold) 7%, transparent),
transparent 70%
),
radial-gradient(
ellipse 54rem 42rem at 4% 48%,
color-mix(in srgb, var(--accent) 6%, transparent),
transparent 72%
),
radial-gradient(ellipse 52rem 36rem at 14% -6%, var(--ambient-gold), transparent 66%),
radial-gradient(ellipse 58rem 44rem at 94% 18%, var(--ambient-violet), transparent 68%),
var(--bg);
background-attachment: fixed;
color: var(--text);
@@ -176,7 +178,10 @@ textarea:focus {
padding: 1.25rem 0.85rem 1rem;
border-right: 1px solid color-mix(in srgb, var(--gold) 20%, var(--line));
background: var(--glass);
box-shadow: 10px 0 34px rgb(0 0 0 / 12%);
box-shadow:
inset -1px 0 rgb(255 255 255 / 8%),
10px 0 34px rgb(0 0 0 / 12%);
-webkit-backdrop-filter: blur(24px) saturate(1.3);
backdrop-filter: blur(24px) saturate(1.3);
overflow-y: auto;
}
@@ -520,7 +525,7 @@ textarea:focus {
.piece-grid {
display: grid;
gap: 0;
overflow: hidden;
overflow: visible;
border: 1px solid var(--line);
border-radius: var(--radius-medium);
background: var(--glass);
@@ -759,11 +764,14 @@ textarea:focus {
.builder-pane {
min-width: 0;
padding: 0.9rem;
border: 1px solid var(--line);
border: 1px solid color-mix(in srgb, var(--gold) 12%, var(--line));
border-radius: var(--radius-medium);
background: var(--glass);
box-shadow: var(--shadow-soft);
backdrop-filter: blur(18px) saturate(1.08);
box-shadow:
inset 0 1px rgb(255 255 255 / 7%),
var(--shadow-soft);
-webkit-backdrop-filter: blur(20px) saturate(1.16);
backdrop-filter: blur(20px) saturate(1.16);
}
.pane-heading {
@@ -782,7 +790,7 @@ textarea:focus {
.pane-heading > span {
padding: 0.3rem 0.55rem;
border-radius: 2rem;
background: var(--panel-soft);
background: var(--material-deep);
color: var(--text-muted);
font-size: 0.7rem;
font-weight: 680;
@@ -850,13 +858,14 @@ textarea:focus {
.run-list {
display: grid;
gap: 0;
border-top: 1px solid var(--line);
gap: 0.5rem;
}
.run-section {
padding: 0.78rem 0.2rem;
border-bottom: 1px solid var(--line);
padding: 0.78rem;
border: 1px solid var(--line);
border-radius: var(--radius-medium);
background: var(--material-inset);
}
.run-section > header {
@@ -883,7 +892,7 @@ textarea:focus {
height: 2rem;
place-items: center;
border-radius: 0.65rem;
background: color-mix(in srgb, var(--category) 16%, var(--panel-soft));
background: color-mix(in srgb, var(--category) 18%, var(--material-deep));
color: var(--text-muted);
font-size: 0.67rem;
font-weight: 750;
@@ -903,7 +912,7 @@ textarea:focus {
padding: 0.55rem 0.65rem;
border-radius: 0.72rem;
border: 1px solid transparent;
background: color-mix(in srgb, var(--panel-soft) 68%, transparent);
background: var(--material-deep);
transition:
background-color 140ms ease,
border-color 140ms ease;
@@ -911,8 +920,8 @@ textarea:focus {
.usage-row:hover,
.usage-row:focus-within {
border-color: var(--line-strong);
background: var(--glass-strong);
border-color: color-mix(in srgb, var(--gold) 34%, var(--line));
background: color-mix(in srgb, var(--gold) 4%, var(--material-deep));
}
.section-drag-handle,
@@ -2048,24 +2057,53 @@ textarea:focus {
}
.template-picker {
margin-bottom: 0.85rem;
border: 1px solid var(--line);
border-radius: var(--radius-medium);
background: var(--panel);
position: relative;
z-index: 8;
}
.template-picker summary {
padding: 0.75rem 0.9rem;
display: flex;
min-height: 2.5rem;
align-items: center;
gap: 0.35rem;
padding: 0.55rem 0.8rem;
border-radius: 0.72rem;
background: var(--primary);
box-shadow: 0 8px 22px color-mix(in srgb, var(--gold) 20%, transparent);
color: var(--primary-text);
cursor: pointer;
list-style: none;
font-size: 0.8rem;
font-weight: 720;
}
.template-picker summary::-webkit-details-marker,
.filter-picker summary::-webkit-details-marker,
.piece-actions summary::-webkit-details-marker {
display: none;
}
.fundus-heading-actions {
display: flex;
align-items: center;
gap: 0.55rem;
}
.template-grid {
position: absolute;
top: calc(100% + 0.5rem);
right: 0;
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
width: min(42rem, calc(100vw - var(--sidebar-width) - 4rem));
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.6rem;
padding: 0 0.75rem 0.75rem;
padding: 0.7rem;
border: 1px solid color-mix(in srgb, var(--gold) 34%, var(--line));
border-radius: var(--radius-medium);
background: var(--glass-strong);
box-shadow: var(--shadow);
-webkit-backdrop-filter: blur(22px) saturate(1.18);
backdrop-filter: blur(22px) saturate(1.18);
}
.template-grid button {
@@ -2089,14 +2127,65 @@ textarea:focus {
}
.library-filters {
display: grid;
grid-template-columns: minmax(15rem, 1.5fr) repeat(4, minmax(7rem, 0.65fr)) auto auto;
align-items: end;
gap: 0.55rem;
margin-bottom: 0.75rem;
position: relative;
z-index: 6;
margin-bottom: 0.85rem;
}
.library-filters > label:not(.search-field) {
.fundus-search-row {
display: flex;
align-items: center;
gap: 0.55rem;
}
.fundus-search-row .search-field {
width: min(100%, 34rem);
}
.filter-picker {
position: relative;
}
.filter-picker summary {
display: flex;
min-height: 2.5rem;
align-items: center;
gap: 0.4rem;
padding: 0.45rem 0.72rem;
border: 1px solid var(--line);
border-radius: 0.72rem;
background: var(--glass);
color: var(--text-muted);
cursor: pointer;
list-style: none;
font-size: 0.75rem;
font-weight: 700;
white-space: nowrap;
}
.filter-picker[open] summary {
border-color: color-mix(in srgb, var(--gold) 46%, var(--line));
color: var(--text);
}
.filter-panel {
position: absolute;
top: calc(100% + 0.5rem);
right: 0;
display: grid;
width: min(38rem, calc(100vw - var(--sidebar-width) - 4rem));
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.7rem;
padding: 0.8rem;
border: 1px solid color-mix(in srgb, var(--gold) 28%, var(--line));
border-radius: var(--radius-medium);
background: var(--glass-strong);
box-shadow: var(--shadow);
-webkit-backdrop-filter: blur(22px) saturate(1.18);
backdrop-filter: blur(22px) saturate(1.18);
}
.filter-panel > label {
display: grid;
gap: 0.2rem;
color: var(--text-muted);
@@ -2104,7 +2193,7 @@ textarea:focus {
font-weight: 700;
}
.library-filters select {
.filter-panel select {
min-width: 0;
height: 2.5rem;
padding: 0.35rem 0.5rem;
@@ -2135,15 +2224,26 @@ textarea:focus {
.library-filter-options {
display: flex;
grid-column: 1 / -1;
flex-wrap: wrap;
gap: 0.15rem 1rem;
margin: -0.35rem 0 0.75rem;
gap: 0.4rem 1rem;
margin: 0;
}
.library-filter-options .filter-checkbox {
margin: 0;
}
.filter-actions {
display: flex;
grid-column: 1 / -1;
align-items: center;
justify-content: flex-end;
gap: 0.45rem;
padding-top: 0.65rem;
border-top: 1px solid var(--line);
}
.piece-usage-history {
margin-top: 0.35rem;
color: var(--text-muted);
@@ -2192,9 +2292,14 @@ textarea:focus {
}
.piece-card {
position: relative;
grid-template-columns: auto minmax(0, 1.65fr) minmax(8rem, 0.85fr) minmax(9rem, auto) auto;
}
.piece-card:has(.piece-actions[open]) {
z-index: 5;
}
.piece-thumbnail {
width: 3.8rem;
height: 3.8rem;
@@ -2207,20 +2312,80 @@ textarea:focus {
place-items: center;
background: var(--panel-soft);
color: var(--text-faint);
font-size: 0.75rem;
font-weight: 800;
border: 1px solid var(--line);
}
.piece-primary h2 a:hover {
.piece-thumbnail-placeholder svg {
width: 1.35rem;
height: 1.35rem;
stroke: currentColor;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 1.5;
}
.piece-primary h2 a:hover,
.piece-card:focus-within .piece-primary h2 a {
color: var(--accent);
}
.piece-primary h2 a::after {
position: absolute;
inset: 0;
content: '';
}
.piece-card :is(a, button, input, summary) {
position: relative;
z-index: 2;
}
.piece-actions {
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: flex-end;
gap: 0.55rem;
position: relative;
z-index: 4;
}
.piece-actions summary {
display: grid;
width: 2.2rem;
height: 2.2rem;
place-items: center;
border: 1px solid var(--line);
border-radius: 0.68rem;
background: var(--glass-strong);
color: var(--text-muted);
cursor: pointer;
list-style: none;
font-size: 0.65rem;
letter-spacing: 0.08em;
}
.piece-actions[open] summary {
border-color: color-mix(in srgb, var(--gold) 46%, var(--line));
color: var(--text);
}
.piece-actions-popover {
position: absolute;
top: calc(100% + 0.35rem);
right: 0;
z-index: 5;
display: grid;
min-width: 9.5rem;
gap: 0.15rem;
padding: 0.35rem;
border: 1px solid var(--line);
border-radius: 0.72rem;
background: var(--glass-strong);
box-shadow: var(--shadow);
-webkit-backdrop-filter: blur(18px) saturate(1.15);
backdrop-filter: blur(18px) saturate(1.15);
}
.piece-actions-popover button {
width: 100%;
justify-content: flex-start;
padding: 0.5rem 0.6rem;
}
.danger-text {
@@ -3366,7 +3531,7 @@ textarea:focus {
padding: 0.16rem;
border: 1px solid var(--line);
border-radius: 0.7rem;
background: var(--glass-strong);
background: color-mix(in srgb, var(--gold) 3%, var(--material-deep));
}
.row-actions > form > button,
@@ -3415,9 +3580,10 @@ textarea:focus {
overflow: hidden;
border: 1px solid color-mix(in srgb, var(--gold) 58%, var(--line-strong));
border-radius: var(--radius-large);
background: var(--glass-strong);
background: var(--glass);
box-shadow: var(--shadow-large);
color: var(--text);
-webkit-backdrop-filter: blur(28px) saturate(1.12);
backdrop-filter: blur(28px) saturate(1.12);
}
@@ -3426,8 +3592,9 @@ textarea:focus {
}
.piece-editor-dialog::backdrop {
background: color-mix(in srgb, var(--bg) 76%, transparent);
backdrop-filter: blur(12px);
background: color-mix(in srgb, var(--bg) 46%, transparent);
-webkit-backdrop-filter: blur(6px) saturate(0.95);
backdrop-filter: blur(6px) saturate(0.95);
}
.piece-dialog-header {
@@ -3438,7 +3605,9 @@ textarea:focus {
gap: 1rem;
padding: 0.9rem 1rem 0.75rem;
border-bottom: 1px solid var(--line);
background: color-mix(in srgb, var(--glass-strong) 88%, transparent);
background: var(--glass-chrome);
box-shadow: inset 0 1px rgb(255 255 255 / 10%);
-webkit-backdrop-filter: blur(24px) saturate(1.2);
backdrop-filter: blur(20px) saturate(1.12);
}
@@ -3486,7 +3655,8 @@ textarea:focus {
gap: 0.25rem;
padding: 0.45rem 1rem;
border-bottom: 1px solid var(--line);
background: color-mix(in srgb, var(--glass-strong) 88%, transparent);
background: var(--glass-chrome);
-webkit-backdrop-filter: blur(24px) saturate(1.2);
backdrop-filter: blur(20px) saturate(1.12);
}
@@ -3502,8 +3672,8 @@ textarea:focus {
}
.piece-dialog-tabs button.active {
background: color-mix(in srgb, var(--gold) 13%, var(--panel));
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 36%, transparent);
background: color-mix(in srgb, var(--gold) 15%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 48%, transparent);
color: var(--text);
}
@@ -3513,7 +3683,7 @@ textarea:focus {
padding: clamp(0.85rem, 2vw, 1.4rem);
overflow: auto;
overscroll-behavior: contain;
background: color-mix(in srgb, var(--bg) 76%, transparent);
background: var(--material-deep);
}
.piece-dialog-form {
@@ -3576,7 +3746,7 @@ textarea:focus {
padding: 0.85rem;
border: 1px solid color-mix(in srgb, var(--gold) 30%, var(--line));
border-radius: var(--radius-medium);
background: color-mix(in srgb, var(--gold) 5%, var(--glass));
background: var(--material-inset);
}
.markdown-editor-heading {
@@ -3611,7 +3781,7 @@ textarea:focus {
padding: 0.22rem 0.4rem;
border: 1px solid var(--line);
border-radius: 0.45rem;
background: color-mix(in srgb, var(--panel-soft) 72%, transparent);
background: var(--material-inset);
color: var(--text-muted);
font-size: 0.65rem;
cursor: pointer;
@@ -3626,6 +3796,7 @@ textarea:focus {
border: 1px solid var(--line-strong);
border-radius: var(--radius-small);
background: var(--field);
box-shadow: inset 0 1px 2px rgb(0 0 0 / 5%);
color: var(--text);
font: inherit;
font-size: 0.88rem;
@@ -3639,7 +3810,7 @@ textarea:focus {
padding: 0.85rem;
border: 1px solid var(--line);
border-radius: var(--radius-medium);
background: color-mix(in srgb, var(--glass) 78%, transparent);
background: var(--material-inset);
}
.piece-meta-details summary {
@@ -3810,8 +3981,11 @@ textarea:focus {
gap: 0.8rem;
padding: 0.65rem 1rem;
border-top: 1px solid var(--line);
background: color-mix(in srgb, var(--glass-strong) 90%, transparent);
box-shadow: 0 -10px 30px rgb(0 0 0 / 10%);
background: var(--glass-chrome);
box-shadow:
inset 0 -1px rgb(255 255 255 / 8%),
0 -10px 30px rgb(0 0 0 / 10%);
-webkit-backdrop-filter: blur(24px) saturate(1.2);
backdrop-filter: blur(20px) saturate(1.12);
}
@@ -4327,12 +4501,6 @@ textarea:focus {
}
@media (max-width: 72rem) {
.library-filters {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.library-filters .search-field {
grid-column: 1 / -1;
}
.piece-card {
grid-template-columns: auto minmax(0, 1fr) minmax(8rem, 0.7fr) auto;
}
@@ -4405,6 +4573,7 @@ textarea:focus {
border-bottom: 1px solid color-mix(in srgb, var(--gold) 18%, var(--line));
background: var(--glass);
box-shadow: 0 8px 28px rgb(0 0 0 / 12%);
-webkit-backdrop-filter: blur(24px) saturate(1.2);
backdrop-filter: blur(24px) saturate(1.2);
}
.mobile-header .theme-toggle {
@@ -4428,6 +4597,7 @@ textarea:focus {
border-top: 1px solid color-mix(in srgb, var(--gold) 18%, var(--line));
background: var(--glass);
box-shadow: 0 -8px 28px rgb(0 0 0 / 12%);
-webkit-backdrop-filter: blur(24px) saturate(1.2);
backdrop-filter: blur(24px) saturate(1.2);
}
.mobile-navigation:has(a:nth-child(5)) {
@@ -4467,7 +4637,6 @@ textarea:focus {
.template-grid,
.two-columns,
.markdown-grid,
.library-filters,
.capture-form,
.upload-form,
.source-row {
@@ -4481,7 +4650,6 @@ textarea:focus {
.builder-filter {
grid-template-columns: 1fr;
}
.library-filters .search-field,
.wide-field {
grid-column: auto;
}
@@ -4742,6 +4910,44 @@ textarea:focus {
align-items: stretch;
flex-direction: column;
}
.split-heading {
align-items: flex-start;
flex-direction: column;
}
.fundus-heading-actions {
width: 100%;
}
.template-picker {
margin-left: auto;
}
.template-grid,
.filter-panel {
position: absolute;
top: calc(100% + 0.5rem);
right: 0;
left: auto;
width: calc(100vw - 2rem);
max-height: calc(100dvh - var(--mobile-header) - var(--mobile-nav) - 1rem);
overflow-y: auto;
}
.fundus-search-row {
align-items: stretch;
flex-wrap: wrap;
}
.fundus-search-row .search-field {
width: 100%;
flex: 1 0 100%;
}
.filter-picker {
margin-left: auto;
}
.filter-panel {
grid-template-columns: 1fr;
}
.library-filter-options,
.filter-actions {
grid-column: auto;
}
.search-field {
width: 100%;
}
@@ -4775,7 +4981,9 @@ textarea:focus {
height: 8rem;
}
.piece-thumbnail-placeholder {
display: none;
display: grid;
width: 3.25rem;
height: 3.25rem;
}
.piece-card:last-child {
border-bottom: 1px solid var(--line);
@@ -4806,11 +5014,9 @@ textarea:focus {
justify-content: flex-start;
}
.piece-actions {
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: flex-start;
gap: 0.7rem;
position: absolute;
top: 0.8rem;
right: 0.8rem;
}
.show-summary {
width: 100%;
+120 -102
View File
@@ -59,101 +59,112 @@
<h1>Fundus</h1>
<p class="page-intro">Vorbereitete Inhalte für kommende Sendungen.</p>
</div>
<div class="heading-stat" aria-label={`${visiblePieces.length} gefundene Inhalte`}>
<strong>{visiblePieces.length}</strong><span>Inhalte</span>
<div class="fundus-heading-actions">
<div class="heading-stat" aria-label={`${visiblePieces.length} gefundene Inhalte`}>
<strong>{visiblePieces.length}</strong><span>Inhalte</span>
</div>
<details class="template-picker">
<summary><span aria-hidden="true">+</span> Neues Piece</summary>
<div class="template-grid">
{#each data.templates as template (template.id)}
<form method="POST" action="?/create">
<input type="hidden" name="template" value={template.id} />
<button type="submit"
><strong>{template.name}</strong><span>{template.description}</span></button
>
</form>
{/each}
</div>
</details>
</div>
</header>
{#if form?.error}<div class="form-message error" role="alert">{form.error}</div>{/if}
{#if form?.success}<div class="form-message success" role="status">{form.success}</div>{/if}
<details class="template-picker">
<summary>Neues Piece anlegen</summary>
<div class="template-grid">
{#each data.templates as template (template.id)}
<form method="POST" action="?/create">
<input type="hidden" name="template" value={template.id} />
<button type="submit"
><strong>{template.name}</strong><span>{template.description}</span></button
>
</form>
{/each}
</div>
</details>
<form
id="library-filters"
class="library-filters"
method="GET"
aria-label="Fundus durchsuchen und filtern"
>
<label class="search-field"
><span aria-hidden="true">⌕</span><span class="sr-only">Fundus durchsuchen</span><input
name="q"
type="search"
value={data.filters.query}
placeholder="Titel, Quelle oder Thema suchen"
/></label
>
<label
><span>Status</span><select name="status"
><option value="">Alle</option><option
value="ready"
selected={data.filters.status === 'ready'}>Sendefertig</option
><option value="preparing" selected={data.filters.status === 'preparing'}>In Arbeit</option
></select
></label
>
<label
><span>Format</span><select name="format"
><option value="">Alle</option>{#each data.taxonomy.formats as item (item.id)}<option
value={item.id}
selected={data.filters.formatId === item.id}>{item.name}</option
>{/each}</select
></label
>
<label
><span>Thema</span><select name="topic"
><option value="">Alle</option>{#each data.taxonomy.topics as item (item.id)}<option
value={item.id}
selected={data.filters.topicId === item.id}>{item.name}</option
>{/each}</select
></label
>
<label
><span>Abschnitt</span><select name="category"
><option value="">Alle</option>{#each data.taxonomy.categories as item (item.id)}<option
value={item.id}
selected={data.filters.categoryId === item.id}>{item.name}</option
>{/each}</select
></label
>
<button class="secondary-button" type="submit">Anwenden</button>
<button class="text-button" type="button" onclick={resetFilters}>Zurücksetzen</button>
<div class="fundus-search-row">
<label class="search-field"
><span aria-hidden="true">⌕</span><span class="sr-only">Fundus durchsuchen</span><input
name="q"
type="search"
value={data.filters.query}
placeholder="Titel, Quelle oder Thema suchen"
/></label
>
<button class="secondary-button" type="submit">Suchen</button>
<details class="filter-picker">
<summary><span aria-hidden="true">≡</span> Weitere Filter</summary>
<div class="filter-panel">
<label
><span>Status</span><select name="status"
><option value="">Alle</option><option
value="ready"
selected={data.filters.status === 'ready'}>Sendefertig</option
><option value="preparing" selected={data.filters.status === 'preparing'}
>In Arbeit</option
></select
></label
>
<label
><span>Format</span><select name="format"
><option value="">Alle</option>{#each data.taxonomy.formats as item (item.id)}<option
value={item.id}
selected={data.filters.formatId === item.id}>{item.name}</option
>{/each}</select
></label
>
<label
><span>Thema</span><select name="topic"
><option value="">Alle</option>{#each data.taxonomy.topics as item (item.id)}<option
value={item.id}
selected={data.filters.topicId === item.id}>{item.name}</option
>{/each}</select
></label
>
<label
><span>Abschnitt</span><select name="category"
><option value="">Alle</option
>{#each data.taxonomy.categories as item (item.id)}<option
value={item.id}
selected={data.filters.categoryId === item.id}>{item.name}</option
>{/each}</select
></label
>
<div class="library-filter-options" aria-label="Fundusauswahl erweitern">
<label class="filter-checkbox">
<input
type="checkbox"
name="includeUsed"
value="1"
checked={showUsedPieces}
onchange={(event) => setSourceFilter('includeUsed', event.currentTarget.checked)}
/>
<span>Auch verwendete Inhalte zeigen</span>
</label>
<label class="filter-checkbox">
<input
type="checkbox"
name="includePlanned"
value="1"
checked={showPlannedPieces}
onchange={(event) => setSourceFilter('includePlanned', event.currentTarget.checked)}
/>
<span>Auch eingeplante Inhalte zeigen</span>
</label>
</div>
<div class="filter-actions">
<button class="secondary-button" type="submit">Filter anwenden</button>
<button class="text-button" type="button" onclick={resetFilters}>Zurücksetzen</button>
</div>
</div>
</details>
</div>
</form>
<div class="library-filter-options" aria-label="Fundusauswahl erweitern">
<label class="filter-checkbox">
<input
type="checkbox"
name="includeUsed"
value="1"
form="library-filters"
checked={showUsedPieces}
onchange={(event) => setSourceFilter('includeUsed', event.currentTarget.checked)}
/>
<span>Auch verwendete Inhalte zeigen</span>
</label>
<label class="filter-checkbox">
<input
type="checkbox"
name="includePlanned"
value="1"
form="library-filters"
checked={showPlannedPieces}
onchange={(event) => setSourceFilter('includePlanned', event.currentTarget.checked)}
/>
<span>Auch eingeplante Inhalte zeigen</span>
</label>
</div>
{#if visiblePieces.length}
<div class="piece-grid">
@@ -166,9 +177,12 @@
class="piece-thumbnail"
src={`/media/${piece.mediaId}`}
alt=""
/>{:else}<span class="piece-thumbnail piece-thumbnail-placeholder" aria-hidden="true"
>S</span
>{/if}
/>{:else}<span class="piece-thumbnail piece-thumbnail-placeholder" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none">
<path d="M4.5 6.5h15v11h-15zM7.5 14l3-3 2.2 2.2 1.8-1.7 2.5 2.5" />
<circle cx="15.8" cy="9.2" r="1.2" />
</svg>
</span>{/if}
<div class="piece-primary">
<h2><a href={resolve('/fundus/[id]', { id: piece.id })}>{piece.title}</a></h2>
<p>{piece.summary || 'Noch keine Kurzbeschreibung.'}</p>
@@ -193,22 +207,26 @@
></span
>
</div>
<div class="piece-actions">
<a class="text-link" href={resolve('/fundus/[id]', { id: piece.id })}>Bearbeiten</a>
<form method="POST" action="?/duplicate">
<input type="hidden" name="pieceId" value={piece.id} /><button
class="text-button"
type="submit">Duplizieren</button
>
</form>
<form method="POST" action="?/archive">
<input type="hidden" name="pieceId" value={piece.id} /><input
type="hidden"
name="revision"
value={piece.revision}
/><button class="text-button danger-text" type="submit">Archivieren</button>
</form>
</div>
<details class="piece-actions">
<summary aria-label={`Aktionen für ${piece.title}`}
><span aria-hidden="true">•••</span></summary
>
<div class="piece-actions-popover">
<form method="POST" action="?/duplicate">
<input type="hidden" name="pieceId" value={piece.id} /><button
class="text-button"
type="submit">Duplizieren</button
>
</form>
<form method="POST" action="?/archive">
<input type="hidden" name="pieceId" value={piece.id} /><input
type="hidden"
name="revision"
value={piece.revision}
/><button class="text-button danger-text" type="submit">Archivieren</button>
</form>
</div>
</details>
</article>
{/each}
</div>