import { bildAdresse, type Film, type Serie } from './api'; import { icons } from './icons'; import { knopf } from './util'; /** Was im Hero stehen kann — Film oder Serie, mehr braucht es nicht. */ export type Heroeintrag = { art: 'filme' | 'serien'; id: string; titel: string; schriftzug: string | null; hintergrund: string; jahr: number | null; laufzeit: number | null; freigabe: string | null; bewertung: number | null; beschreibung: string | null; }; const WECHSEL_MS = 9000; const HOECHSTENS = 7; /** Der Aufmacher der Startseite. * * **Warum überhaupt.** Die Startseite begann bei einer Reihe aus 150 px * breiten Plakaten — das grösste Element über dem Falz war 225 px hoch. Plex * und Netflix öffnen mit einem Bild über die volle Breite, und das ist der * grösste Einzelunterschied im Eindruck. Es ist ein Layout-, kein * Farbproblem. * * **Nur mit Hintergrundbild.** Ein Hero ohne Bild ist schlechter als keiner: * eine graue Fläche über den halben Bildschirm sagt nichts und nimmt den * Reihen den Platz. Gibt es keinen einzigen Titel mit Backdrop, entfällt er * ersatzlos. * * **Pause bei Mauszeiger und Fokus.** Wer gerade liest oder mit der Tastatur * unterwegs ist, soll nicht nach neun Sekunden woanders landen. Und wer * „Bewegung reduzieren" eingestellt hat, bekommt gar keinen selbsttätigen * Wechsel — nur die Punkte zum Weiterklicken. */ export function hero( eintraege: Heroeintrag[], oeffnen: (art: 'filme' | 'serien', id: string) => void, abspielen: (art: 'filme' | 'serien', id: string) => void, signal?: AbortSignal, ): HTMLElement | null { const mitBild = eintraege.filter(e => e.hintergrund).slice(0, HOECHSTENS); if (mitBild.length === 0) return null; const wurzel = document.createElement('section'); wurzel.className = 'hero'; wurzel.setAttribute('aria-roledescription', 'Karussell'); wurzel.setAttribute('aria-label', 'Vorgestellte Titel'); const buehne = document.createElement('div'); buehne.className = 'hero-buehne'; const folien = mitBild.map((e, i) => { const folie = document.createElement('div'); folie.className = 'hero-folie' + (i === 0 ? ' an' : ''); folie.style.backgroundImage = `url("${bildAdresse(e.hintergrund)}")`; folie.setAttribute('aria-hidden', i === 0 ? 'false' : 'true'); buehne.appendChild(folie); return folie; }); const inhalt = document.createElement('div'); inhalt.className = 'hero-inhalt'; const schriftzug = document.createElement('img'); schriftzug.className = 'hero-schriftzug'; const titel = document.createElement('h1'); titel.className = 'hero-titel'; const meta = document.createElement('div'); meta.className = 'hero-meta'; const text = document.createElement('p'); text.className = 'hero-text'; const spielen = knopf('Abspielen', 'btn btn-primary'); spielen.prepend(iconElement(icons.abspielen)); const mehr = knopf('Mehr', 'btn'); const knoepfe = document.createElement('div'); knoepfe.className = 'hero-knoepfe'; knoepfe.append(spielen, mehr); inhalt.append(schriftzug, titel, meta, text, knoepfe); const punkte = document.createElement('div'); punkte.className = 'hero-punkte'; const punktknoepfe = mitBild.map((e, i) => { const b = document.createElement('button'); b.type = 'button'; b.className = 'hero-punkt' + (i === 0 ? ' an' : ''); // **Echte Knöpfe mit Beschriftung**, keine `