Die Knöpfe bleiben, die Inhaltsangabe klappt auf
Ich hatte „die Beschreibung nur beim Hovern" gelesen und daraufhin Beschreibung *und* Knöpfe ausgeblendet. Die Knöpfe gehören immer dahin: in Ruhe steht oben, was läuft und was man damit tun kann. Die Inhaltsangabe dagegen steht erst da, wenn man es will. Zwei Sekunden auf dem Titel stehenbleiben, dann fährt er hoch und darunter klappt sie auf; wer nur vorbeifährt, sieht nichts. Gibt es keine, passiert gar nichts — der Absatz fällt dann ganz aus dem Fluss. **Angefasst wird am Titel, losgelassen am ganzen Aufmacher.** Das ist die ganze Vorsicht an dieser Stelle. Beim Aufklappen wächst der Block nach oben, der Titel rückt um 77 Bildpunkte weg und steht nicht mehr unter dem Zeiger. Hinge das Zuklappen an seinem `:hover`, wäre das die erste Hälfte einer Schaukel. Der Aufmacher selbst kann das nicht: gemessen, offen wie zu, 476 px hoch ab 48 — auf den Bildpunkt derselbe Kasten. **Die Höhe wird gemessen, nicht geraten.** Nach `auto` lässt sich nicht überblenden, und eine feste Obergrenze wäre bei einer einzeiligen Angabe zu drei Vierteln Leerlauf. Gemessen wird bei jedem Folienwechsel und bei jeder Fensteränderung; `scrollHeight` ginge nicht, der meldet bei einem `-webkit-box` die ungeklammerte Höhe. **Der Rasterabstand wandert mit.** Gemessen: zugeklappt stehen zwischen Eckdaten und Knopfzeile 16 px — mit Inhaltsangabe wie ohne, und genau so viele wie vorher. Aufgeklappt sind es 12 über und 16 unter dem Text, und die Knopfzeile steht still (Unterkante 492 in beiden Zuständen). Nebenbei kommt das Abbruchsignal endlich an: `hero()` nahm eines entgegen, aber `main.ts` baute die Startseite ohne. Sie wird gemerkt — ihr Neun-Sekunden-Takt lief also weiter, während man längst woanders war. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ac9faacefb
commit
02978e482c
+99
-3
@@ -204,7 +204,20 @@ export function hero(
|
||||
e.bewertung ? `★ ${e.bewertung.toFixed(1)}` : null,
|
||||
].filter(Boolean).join(' · ');
|
||||
|
||||
text.textContent = e.beschreibung ?? '';
|
||||
// **Nichts zu zeigen heisst: kein Aufklappen.** Bei einer angefangenen
|
||||
// Folge steht hier oft gar nichts, und bei „S2 · F5 — Der Pakt" wäre das
|
||||
// Auffahren eine Bewegung um einer Zeile willen, die schon oben steht.
|
||||
// Mit `.hidden` fällt der Absatz aus dem Fluss und nimmt seinen
|
||||
// Rasterabstand mit; der Block steht dann bei jeder Folie gleich hoch.
|
||||
//
|
||||
// **Hier und nicht am Ende von `zeige`** — weiter unten steht ein `return`
|
||||
// für noch nicht freigegebene Titel.
|
||||
const beschreibung = e.beschreibung?.trim() ?? '';
|
||||
text.textContent = beschreibung;
|
||||
text.classList.toggle('hidden', beschreibung.length === 0);
|
||||
hatText = beschreibung.length > 0;
|
||||
if (!hatText) zuklappen();
|
||||
anstossen();
|
||||
mehr.onclick = () => oeffnen(e.art, e.id);
|
||||
|
||||
// **Drei Fälle, und jeder sagt die Wahrheit.**
|
||||
@@ -290,11 +303,94 @@ export function hero(
|
||||
wurzel.addEventListener('pointercancel', () => { start = null; });
|
||||
}
|
||||
|
||||
/* ---------- Die Inhaltsangabe klappt auf ---------- */
|
||||
|
||||
/** Wie lange der Zeiger auf dem Titel stehen muss. */
|
||||
const GEDULD_MS = 2000;
|
||||
|
||||
let hatText = false;
|
||||
let wartet: number | undefined;
|
||||
let angemeldet = false;
|
||||
|
||||
/** Misst die aufgeklappte Höhe und schreibt sie als Eigenschaft.
|
||||
*
|
||||
* **Kurz auf `auto` und wieder zurück.** Dazwischen wird nicht gezeichnet —
|
||||
* beides liegt in derselben Aufgabe. `scrollHeight` ginge nicht: bei einem
|
||||
* `-webkit-box` meldet der die *ungeklammerte* Höhe, bei sechs Zeilen also
|
||||
* das Doppelte dessen, was je zu sehen ist. */
|
||||
function messen(): void {
|
||||
if (!hatText) return;
|
||||
const vorher = text.style.height;
|
||||
text.style.height = 'auto';
|
||||
const hoehe = Math.round(text.getBoundingClientRect().height);
|
||||
text.style.height = vorher;
|
||||
inhalt.style.setProperty('--hero-texthoehe', `${hoehe}px`);
|
||||
}
|
||||
|
||||
/** Einmal je Bild, nicht einmal je Ereignis — wie `weichNachBildlauf`. */
|
||||
function anstossen(): void {
|
||||
if (angemeldet) return;
|
||||
angemeldet = true;
|
||||
requestAnimationFrame(() => { angemeldet = false; messen(); });
|
||||
}
|
||||
|
||||
function aufklappen(): void {
|
||||
if (!hatText) return;
|
||||
messen(); // Erst messen, dann schalten.
|
||||
inhalt.classList.add('aufgeklappt');
|
||||
}
|
||||
|
||||
function zuklappen(): void {
|
||||
if (wartet !== undefined) { window.clearTimeout(wartet); wartet = undefined; }
|
||||
inhalt.classList.remove('aufgeklappt');
|
||||
}
|
||||
|
||||
// **Angefasst wird am Titel, losgelassen am ganzen Aufmacher.**
|
||||
//
|
||||
// Das ist die ganze Vorsicht an dieser Stelle. Klappt die Inhaltsangabe auf,
|
||||
// wächst `.hero-inhalt` nach oben — der Titel rückt um zwanzig bis siebzig
|
||||
// Bildpunkte weg und steht nicht mehr unter dem Zeiger. Hinge das Zuklappen
|
||||
// an seinem `:hover`, wäre das die erste Hälfte einer Schaukel: weg vom
|
||||
// Zeiger, zu, wieder unter den Zeiger, auf, und so fort im Takt der
|
||||
// Überblendung.
|
||||
//
|
||||
// Der Aufmacher selbst kann das nicht: er ist `min(62vh, 560px)` hoch, fest.
|
||||
// Sein Rechteck ändert sich beim Aufklappen um keinen Bildpunkt, ein Zeiger
|
||||
// darin kann also nicht hinausgeschoben werden.
|
||||
const anfassen = (e: PointerEvent): void => {
|
||||
// Ohne Zeiger kein Verweilen — am Finger steht die Inhaltsangabe ohnehin
|
||||
// die ganze Zeit da, siehe `hover: hover` im Regelwerk.
|
||||
if (e.pointerType === 'touch') return;
|
||||
if (!hatText || inhalt.classList.contains('aufgeklappt')) return;
|
||||
window.clearTimeout(wartet);
|
||||
wartet = window.setTimeout(() => { wartet = undefined; aufklappen(); }, GEDULD_MS);
|
||||
};
|
||||
|
||||
/** Bricht nur das Warten ab, nie das Aufgeklappte.
|
||||
*
|
||||
* Ist es offen, ist dieses Verlassen gerade das, was das Aufklappen selbst
|
||||
* verursacht hat. */
|
||||
const loslassen = (): void => {
|
||||
if (wartet !== undefined) { window.clearTimeout(wartet); wartet = undefined; }
|
||||
};
|
||||
|
||||
[schriftzug, titel].forEach(el => {
|
||||
el.addEventListener('pointerenter', anfassen);
|
||||
el.addEventListener('pointerleave', loslassen);
|
||||
});
|
||||
|
||||
// Drei Zeilen sind bei 620 px Breite andere als bei 380.
|
||||
window.addEventListener('resize', anstossen, { passive: true });
|
||||
|
||||
wurzel.addEventListener('mouseenter', anhalten);
|
||||
wurzel.addEventListener('mouseleave', starten);
|
||||
wurzel.addEventListener('mouseleave', () => { starten(); zuklappen(); });
|
||||
wurzel.addEventListener('focusin', anhalten);
|
||||
wurzel.addEventListener('focusout', starten);
|
||||
signal?.addEventListener('abort', anhalten);
|
||||
signal?.addEventListener('abort', () => {
|
||||
anhalten();
|
||||
loslassen();
|
||||
window.removeEventListener('resize', anstossen);
|
||||
});
|
||||
|
||||
zeige(0);
|
||||
starten();
|
||||
|
||||
Reference in New Issue
Block a user