From d3212a3f6011f9ee408343f71ed24d119bb29e05 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Fri, 28 Aug 2026 00:40:19 +0200 Subject: [PATCH] Workspace: Zurueck-Knopf hochwertiger, auf der Startseite entfernt Zwei Rueckmeldungen umgesetzt. 1. Auf der Startseite gibt es den Knopf jetzt gar nicht mehr im Dokument. Vorher erschien er dort, sobald man von einer anderen Workspace-Seite kam -- aber die Startseite IST die oberste Ebene, ein "davor" gibt es nicht. 2. Aussehen: statt des Textzeichens "<-" jetzt ein echtes SVG-Winkel- symbol, Pillenform, und ein Verlaufsrahmen. Wichtig dabei: Die Fuellung ist DECKEND. Beim ersten Versuch war sie halbtransparent, dadurch schien der Rahmenverlauf durch die ganze Flaeche und der Knopf sah aus wie eine Hauptaktion -- genau das soll er nicht. Jetzt bleibt vom Verlauf nur der 1px schmale Rand sichtbar. Ruhezustand: dunkle Pille, feine Stahlkante, gedaempfter Text. Ueberfahren: Cyan-Violett-Rand, heller Text, weicher Schein, und der Pfeil rueckt zwei Pixel nach links -- die Bewegung sagt die Richtung ohne zusaetzlichen Text. Bei prefers-reduced-motion faellt sie weg. Geprueft: Start -> kein Knopf; Aufgaben -> "Zurueck", fuehrt zurueck; Personen direkt aufgerufen -> "Uebersicht". Keine Konsolenfehler. Nur statische Dateien, kein Neustart noetig. --- workspace/assets/css/kopf.js | 68 ++++++++++++++++++++++++++++++++++ workspace/assets/css/start.css | 53 ++++++++++++++++++++------ workspace/assets/js/kopf.js | 10 ++--- workspace/aufgaben.html | 7 +++- workspace/kalender.html | 7 +++- workspace/personen.html | 7 +++- workspace/profil.html | 7 +++- workspace/start.html | 1 - 8 files changed, 139 insertions(+), 21 deletions(-) create mode 100644 workspace/assets/css/kopf.js diff --git a/workspace/assets/css/kopf.js b/workspace/assets/css/kopf.js new file mode 100644 index 00000000..d4f1ae4f --- /dev/null +++ b/workspace/assets/css/kopf.js @@ -0,0 +1,68 @@ +/* =================================================================== + Gemeinsames Verhalten der Kopfleiste: Zurück-Knopf und Abmelden. + + Liegt bewusst in einer eigenen Datei. Vorher stand das Abmelden in + jeder Seitendatei noch einmal -- fünfmal derselbe Block, fünfmal eine + Stelle zum Vergessen, wenn sich etwas ändert. + =================================================================== */ +(() => { + 'use strict'; + + const START = '/workspace/start.html'; + + /* Gibt es eine sinnvolle vorherige Seite INNERHALB des Workspace? + + Blindes history.back() reicht nicht: Wer die Adresse direkt eingibt + oder gerade von der Anmeldung kommt, landet damit außerhalb des + Workspace oder wieder im Anmeldeformular. Deshalb wird zuerst + geprüft, woher der Aufruf kam. */ + function hatVorherigeSeite() { + if (!document.referrer) return false; + let u; + try { u = new URL(document.referrer); } catch { return false; } + if (u.origin !== location.origin) return false; + if (!u.pathname.startsWith('/workspace/')) return false; + /* Die Anmeldeseite ist kein sinnvolles Ziel -- wer angemeldet ist, + würde dort sofort wieder weitergeleitet. */ + if (u.pathname === '/workspace/' || u.pathname.endsWith('/index.html')) return false; + /* Gleiche Seite heißt: neu geladen, nicht hergekommen. */ + if (u.pathname === location.pathname) return false; + return true; + } + + /* Die Startseite hat den Knopf gar nicht erst im Dokument -- dort gibt + es kein "davor". Deshalb genügt hier die Prüfung, ob er existiert. */ + const knopf = document.getElementById('zurueck'); + if (knopf) { + const beschriftung = knopf.querySelector('.zurueck-knopf__text'); + if (hatVorherigeSeite()) { + knopf.hidden = false; + knopf.addEventListener('click', () => { + /* history.back() statt eines festen Ziels: Es führt wirklich + dorthin zurück, wo man war -- samt Bildlaufposition. Nur wenn + es keine Historie gibt, wird ersatzweise umgeleitet. */ + if (history.length > 1) history.back(); + else location.assign(START); + }); + } else { + /* Kein Verlauf, aber wir sind in einem Unterbereich: dann wenigstens + ein Weg zur Übersicht. */ + knopf.hidden = false; + if (beschriftung) beschriftung.textContent = 'Übersicht'; + knopf.addEventListener('click', () => location.assign(START)); + } + } + + const abmelden = document.getElementById('abmelden'); + if (abmelden) { + abmelden.addEventListener('click', async () => { + abmelden.disabled = true; + try { + await fetch('/workspace/api/abmelden', { + method: 'POST', credentials: 'same-origin', + }); + } catch { /* Auch ohne Antwort weiterleiten -- das Cookie läuft ohnehin ab. */ } + location.assign('/workspace/'); + }); + } +})(); diff --git a/workspace/assets/css/start.css b/workspace/assets/css/start.css index 6f020545..7f982623 100644 --- a/workspace/assets/css/start.css +++ b/workspace/assets/css/start.css @@ -39,26 +39,57 @@ body.start { .kopfleiste .marke { margin: 0; font-size: .72rem; } /* Zurück-Knopf. Steht ganz links, weil dort jeder ihn erwartet -- gleiche - Stelle wie im Browser. Bleibt verborgen (hidden), wenn es nichts gibt, - wohin er führen könnte; das entscheidet kopf.js. */ + Stelle wie im Browser. Auf der Startseite gibt es ihn gar nicht: Dort + ist kein "davor", und ein Knopf, der nichts tut, ist schlimmer als + keiner. Auf den übrigen Seiten entscheidet kopf.js, ob er erscheint. */ .zurueck-knopf { flex: 0 0 auto; - padding: 7px 13px; - background: rgba(255, 255, 255, .045); - border: 1px solid var(--rand); - border-radius: 9px; + display: inline-flex; align-items: center; gap: 7px; + padding: 8px 15px 8px 12px; + /* Verlaufsrahmen: Die Füllung ist DECKEND, dadurch bleibt vom unteren + Verlauf nur der 1px schmale Rand sichtbar. Wäre sie durchsichtig, + schiene der Rahmenverlauf durch die ganze Fläche und der Knopf sähe + aus wie eine Hauptaktion -- das soll er gerade nicht. */ + background: + linear-gradient(180deg, #151c28, #10161f) padding-box, + linear-gradient(180deg, rgba(158, 196, 230, .40), rgba(158, 196, 230, .12)) border-box; + border: 1px solid transparent; + border-radius: 999px; color: var(--text-leise); - font: inherit; font-size: .82rem; + font: inherit; font-size: .82rem; font-weight: 500; + letter-spacing: .01em; cursor: pointer; white-space: nowrap; - transition: background var(--tempo), border-color var(--tempo), color var(--tempo); + box-shadow: 0 1px 2px rgba(0, 0, 0, .35), inset 0 1px 0 rgba(255, 255, 255, .06); + transition: color var(--tempo), box-shadow var(--tempo), background var(--tempo); } + +.zurueck-knopf__pfeil { + width: 15px; height: 15px; flex: 0 0 auto; + fill: none; stroke: currentColor; + stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; + transition: transform var(--tempo); +} + .zurueck-knopf:hover { - background: rgba(255, 255, 255, .08); - border-color: var(--rand-hell); color: var(--text); + background: + linear-gradient(180deg, #1a2431, #131b25) padding-box, + linear-gradient(180deg, rgba(63, 189, 245, .62), rgba(138, 118, 255, .30)) border-box; + box-shadow: 0 2px 12px -4px rgba(63, 189, 245, .35), inset 0 1px 0 rgba(255, 255, 255, .08); +} +/* Der Pfeil rückt beim Überfahren ein Stück nach links -- die Bewegung + sagt in welche Richtung es geht, ohne zusätzlichen Text. */ +.zurueck-knopf:hover .zurueck-knopf__pfeil { transform: translateX(-2px); } + +.zurueck-knopf:active { box-shadow: inset 0 1px 3px rgba(0, 0, 0, .4); } +.zurueck-knopf:active .zurueck-knopf__pfeil { transform: translateX(-3px); } + +@media (prefers-reduced-motion: reduce) { + .zurueck-knopf__pfeil { transition: none; } + .zurueck-knopf:hover .zurueck-knopf__pfeil, + .zurueck-knopf:active .zurueck-knopf__pfeil { transform: none; } } -.zurueck-knopf:active { transform: translateX(-1px); } .kopfleiste__rechts { display: flex; align-items: center; gap: 12px; } diff --git a/workspace/assets/js/kopf.js b/workspace/assets/js/kopf.js index bd3d93d8..d4f1ae4f 100644 --- a/workspace/assets/js/kopf.js +++ b/workspace/assets/js/kopf.js @@ -30,9 +30,11 @@ return true; } + /* Die Startseite hat den Knopf gar nicht erst im Dokument -- dort gibt + es kein "davor". Deshalb genügt hier die Prüfung, ob er existiert. */ const knopf = document.getElementById('zurueck'); if (knopf) { - const aufStartseite = location.pathname.endsWith('/start.html'); + const beschriftung = knopf.querySelector('.zurueck-knopf__text'); if (hatVorherigeSeite()) { knopf.hidden = false; knopf.addEventListener('click', () => { @@ -42,15 +44,13 @@ if (history.length > 1) history.back(); else location.assign(START); }); - } else if (!aufStartseite) { + } else { /* Kein Verlauf, aber wir sind in einem Unterbereich: dann wenigstens ein Weg zur Übersicht. */ knopf.hidden = false; - knopf.textContent = '← Übersicht'; + if (beschriftung) beschriftung.textContent = 'Übersicht'; knopf.addEventListener('click', () => location.assign(START)); } - /* Auf der Startseite ohne Verlauf bleibt der Knopf aus -- ein Knopf, - der nichts tut, ist schlimmer als keiner. */ } const abmelden = document.getElementById('abmelden'); diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index 57f24088..c31618dc 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -15,7 +15,12 @@
- +

Creator Workspace · Aufgaben

… diff --git a/workspace/kalender.html b/workspace/kalender.html index 11afc354..b25b0403 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -16,7 +16,12 @@
- +

Creator Workspace · Kalender

… diff --git a/workspace/personen.html b/workspace/personen.html index 77824492..53faf5e0 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -16,7 +16,12 @@
- +

Creator Workspace · Personen

… diff --git a/workspace/profil.html b/workspace/profil.html index 57a52262..80d9f4fb 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -16,7 +16,12 @@
- +

Creator Workspace · Profil

… diff --git a/workspace/start.html b/workspace/start.html index b5ecb492..d560b08e 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -14,7 +14,6 @@
-

Dogfather Universe · Creator Workspace

…