CI / pruefen (pull_request) Canceled after 0s
Der Titelblock hatte mit line-clamp-2 zwar eine Ober-, aber keine Untergrenze. Einzeilige Titel belegten dadurch 19 statt 39 Pixel, und alles darunter rutschte um eine Zeilenhoehe nach oben — neben Karten mit zweizeiligem Titel wirkte das Raster ausgefranst. Der Titelblock bekommt jetzt mit min-h-[2lh] immer zwei Zeilen. Die Einheit lh haengt an der tatsaechlichen Zeilenhoehe, damit der Wert nicht von einer Aenderung an leading-snug abgehaengt wird. In der Bibliothekskarte kam hinzu, dass der Fortschrittsbalken nur bei Serien erscheint. Sein Platz wird jetzt auch dann freigehalten, wenn er leer bleibt — als unsichtbarer Nachbau statt einer festen Pixelhoehe, damit er sich von selbst nachzieht. Nachgemessen bei 1400 px: Metazeilen einer Reihe liegen jetzt alle auf derselben Oberkante (Suche 711 px, Bibliothek 715/1117/1520 px), und alle Karten sind gleich hoch (353 bzw. 387 px). Vorher: 691 gegen 711 px und Kartenhoehen von 333 bis 367 px. Bei Handybreite ebenfalls sauber. Refs #2
103 lines
4.0 KiB
TypeScript
103 lines
4.0 KiB
TypeScript
import Link from "next/link";
|
|
import { Poster } from "@/components/Poster";
|
|
import { ProgressBar } from "@/components/ProgressBar";
|
|
import { STATUS_COLOR, STATUS_LABEL, type StatusKey } from "@/lib/labels";
|
|
import type { LibraryItem } from "@/lib/queries";
|
|
|
|
/**
|
|
* Posterkachel der Bibliothek.
|
|
*
|
|
* Alles Wesentliche steht ohne Klick da: Status, Fortschritt, Bewertung.
|
|
* Die Karte ist ein Link — der ganze Bereich ist anklickbar, nicht nur der Titel.
|
|
*/
|
|
export function LibraryCard({ item }: { item: LibraryItem }) {
|
|
const status = item.status as StatusKey;
|
|
const showProgress = item.type === "SERIES" && item.total > 0 && item.status !== "WATCHLIST";
|
|
|
|
return (
|
|
<Link href={`/titel/${item.titleId}`} className="fl-poster-card group block focus:outline-none">
|
|
<div className="relative">
|
|
<Poster path={item.posterPath} alt={item.title} size="w342" />
|
|
|
|
{/* Status und Sammlung teilen sich die obere Zeile — unten sitzt bei
|
|
den Postern oft der Titel, dort würden sie ihn verdecken. */}
|
|
<span className="absolute left-2 top-2 flex flex-wrap gap-1">
|
|
<span
|
|
className="rounded-full px-2 py-0.5 text-[0.65rem] font-semibold backdrop-blur-md"
|
|
style={{
|
|
color: STATUS_COLOR[status],
|
|
backgroundColor: `color-mix(in oklab, var(--fl-bg) 72%, transparent)`,
|
|
boxShadow: `inset 0 0 0 1px color-mix(in oklab, ${STATUS_COLOR[status]} 45%, transparent)`,
|
|
}}
|
|
>
|
|
{STATUS_LABEL[status]}
|
|
</span>
|
|
|
|
{item.owned && (
|
|
<span
|
|
className="rounded-full px-2 py-0.5 text-[0.65rem] font-semibold text-[var(--fl-on-accent)]"
|
|
style={{ backgroundImage: "var(--fl-gradient)" }}
|
|
title={
|
|
item.ownedSource ? `In deiner Sammlung: ${item.ownedSource}` : "In deiner Sammlung"
|
|
}
|
|
>
|
|
Hab ich
|
|
</span>
|
|
)}
|
|
</span>
|
|
|
|
{item.rating != null && (
|
|
<span
|
|
className="absolute right-2 top-2 rounded-full px-2 py-0.5 text-[0.65rem] font-semibold text-[var(--fl-on-accent)]"
|
|
style={{ backgroundImage: "var(--fl-gradient)" }}
|
|
>
|
|
{item.rating}
|
|
</span>
|
|
)}
|
|
|
|
{item.currentRun > 0 && (
|
|
<span className="absolute bottom-2 right-2 rounded-full bg-[color-mix(in_oklab,var(--fl-bg)_78%,transparent)] px-2 py-0.5 text-[0.65rem] font-medium text-[var(--fl-muted)] backdrop-blur-md">
|
|
{item.currentRun + 1}. Durchlauf
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mt-2 space-y-1">
|
|
<p className="line-clamp-2 min-h-[2lh] text-sm font-medium leading-snug">{item.title}</p>
|
|
<p className="text-xs text-[var(--fl-faint)]">
|
|
{item.type === "SERIES" ? "Serie" : "Film"}
|
|
{item.year ? ` · ${item.year}` : ""}
|
|
{item.owned && item.ownedSource
|
|
? ` · ${item.ownedSource}`
|
|
: item.whereToWatch
|
|
? ` · ${item.whereToWatch}`
|
|
: ""}
|
|
</p>
|
|
|
|
<div className="pt-0.5">
|
|
{showProgress ? (
|
|
<>
|
|
<ProgressBar
|
|
percent={item.percent}
|
|
label={`${item.watched} von ${item.total} Episoden gesehen`}
|
|
/>
|
|
<p className="mt-1 text-xs text-[var(--fl-faint)]">
|
|
{item.watched}/{item.total} Episoden
|
|
</p>
|
|
</>
|
|
) : (
|
|
// Filme und Watchlist-Einträge haben keinen Balken. Der Platz wird
|
|
// trotzdem freigehalten — sonst fallen sie kürzer aus als Serien und
|
|
// das Raster franst reihenweise aus. Der Nachbau statt einer festen
|
|
// Pixelhöhe hält sich von selbst nach, wenn sich der Balken ändert.
|
|
<div className="invisible" aria-hidden>
|
|
<div className="fl-progress" />
|
|
<p className="mt-1 text-xs"> </p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|