style(frontend): Prettier config + one-time repo-wide format pass

Prettier 3 (pinned), printWidth 100, double quotes — chosen to match the existing
hand-formatting and minimise reflow. This commit is ONLY the mechanical format pass
(`prettier --write`) plus the config/ignore/scripts, isolated so it never pollutes a
feature diff. Verified behaviour-neutral: typecheck, eslint (0 errors), and vitest
all green before and after. See .git-blame-ignore-revs — `git blame` skips this sha.
This commit is contained in:
2026-07-21 02:26:40 +02:00
parent 04ecd8b3a7
commit e257e2aca0
101 changed files with 4388 additions and 2641 deletions
+36 -23
View File
@@ -55,15 +55,17 @@ function Actions({
// `dense` shrinks 28px buttons to 24 and halves the gap: six of them need 188px, but the small
// card's text column bottoms out around 160 (its 180px column less the padding), so at its
// narrowest the last button used to hang outside the card. 154 at dense.
const btn = clsx(
"rounded-md hover:bg-surface text-muted hover:text-fg",
dense ? "p-1" : "p-1.5"
);
const btn = clsx("rounded-md hover:bg-surface text-muted hover:text-fg", dense ? "p-1" : "p-1.5");
return (
// flex-wrap is the safety net, not the plan: the sizing above is what makes them fit. If a
// future button or a narrower column breaks that arithmetic, the row wraps to a second line
// rather than silently rendering a half-clipped control outside the card.
<div className={clsx("flex flex-wrap opacity-0 group-hover:opacity-100 transition", dense ? "gap-0.5" : "gap-1")}>
<div
className={clsx(
"flex flex-wrap opacity-0 group-hover:opacity-100 transition",
dense ? "gap-0.5" : "gap-1",
)}
>
<button
onClick={act("watched")}
title={video.status === "watched" ? t("card.watchedUnmark") : t("card.markWatched")}
@@ -89,11 +91,7 @@ function Actions({
title={video.status === "hidden" ? t("card.unhide") : t("card.hide")}
className={clsx(btn, video.status === "hidden" && "text-accent")}
>
{video.status === "hidden" ? (
<Eye className="w-4 h-4" />
) : (
<EyeOff className="w-4 h-4" />
)}
{video.status === "hidden" ? <Eye className="w-4 h-4" /> : <EyeOff className="w-4 h-4" />}
</button>
{onResetState && resettable && (
<button
@@ -117,7 +115,7 @@ function Actions({
function openInApp(
e: React.MouseEvent,
video: Video,
onOpen?: (v: Video, startAt?: number | null) => void
onOpen?: (v: Video, startAt?: number | null) => void,
): void {
if (!onOpen || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
e.preventDefault();
@@ -229,7 +227,7 @@ function Thumb({
onClick={(e) => openInApp(e, video, onOpen)}
className={clsx(
"block relative rounded-xl overflow-hidden bg-surface border border-border shadow-md group-hover:shadow-2xl transition-shadow",
className
className,
)}
>
{video.thumbnail_url ? (
@@ -279,7 +277,7 @@ function Thumb({
aria-label={t("card.continue")}
className={clsx(
"inline-flex items-center justify-center gap-1.5 font-semibold bg-accent text-accent-fg shadow-lg hover:opacity-90 transition",
small ? "w-9 h-9 rounded-full" : "px-3 py-1.5 rounded-lg text-sm"
small ? "w-9 h-9 rounded-full" : "px-3 py-1.5 rounded-lg text-sm",
)}
>
<Play className="w-4 h-4 fill-current" />
@@ -291,7 +289,7 @@ function Thumb({
aria-label={t("card.restart")}
className={clsx(
"inline-flex items-center justify-center gap-1.5 font-medium bg-white/15 text-white backdrop-blur-sm hover:bg-white/25 transition",
small ? "w-9 h-9 rounded-full" : "px-3 py-1.5 rounded-lg text-sm"
small ? "w-9 h-9 rounded-full" : "px-3 py-1.5 rounded-lg text-sm",
)}
>
<RotateCcw className="w-4 h-4" />
@@ -305,10 +303,12 @@ function Thumb({
aria-label={t("card.play")}
className={clsx(
"inline-flex items-center justify-center rounded-full bg-accent text-accent-fg shadow-lg hover:scale-105 transition",
small ? "w-9 h-9" : "w-12 h-12"
small ? "w-9 h-9" : "w-12 h-12",
)}
>
<Play className={clsx("fill-current translate-x-[1px]", small ? "w-4 h-4" : "w-5 h-5")} />
<Play
className={clsx("fill-current translate-x-[1px]", small ? "w-4 h-4" : "w-5 h-5")}
/>
</button>
)}
</div>
@@ -403,7 +403,12 @@ function VideoCard({
const published = (
<>
{relativeTime(video.published_at)}
{video.published_at && <>{" · "}{formatDate(video.published_at, i18n.language)}</>}
{video.published_at && (
<>
{" · "}
{formatDate(video.published_at, i18n.language)}
</>
)}
</>
);
// Show the full text in a native tooltip only when it's actually cut off — vertically where the
@@ -436,10 +441,10 @@ function VideoCard({
target="_blank"
rel="noreferrer"
onClick={(e) => openInApp(e, video, onOpen)}
title={titleClamped ? video.title ?? undefined : undefined}
title={titleClamped ? (video.title ?? undefined) : undefined}
className={clsx(
"font-medium leading-snug hover:text-accent",
noThumb ? "block truncate" : "line-clamp-2"
noThumb ? "block truncate" : "line-clamp-2",
)}
>
{video.title}
@@ -453,7 +458,7 @@ function VideoCard({
e.stopPropagation();
openChannel(video.channel_id, video.channel_title ?? t("card.thisChannel"));
}}
title={channelClamped ? video.channel_title ?? undefined : undefined}
title={channelClamped ? (video.channel_title ?? undefined) : undefined}
className="text-sm text-muted truncate block w-fit max-w-full text-left hover:text-fg"
>
{video.channel_title}
@@ -498,7 +503,11 @@ function VideoCard({
const pct = resumePct(video);
const fits = (needs: number) => width === 0 || width >= needs;
return (
<div data-testid="video-card" data-video-id={video.id} className={clsx(rowShell, "flex items-center gap-3 px-3 py-2", watched && "opacity-55")}>
<div
data-testid="video-card"
data-video-id={video.id}
className={clsx(rowShell, "flex items-center gap-3 px-3 py-2", watched && "opacity-55")}
>
{/* Actions lead: this is where the eye already is (the title is the thing you read), so
they're the shortest pointer trip from it. */}
<div className="shrink-0 w-48">{actions}</div>
@@ -551,7 +560,11 @@ function VideoCard({
if (spec.family === "row") {
return (
<div data-testid="video-card" data-video-id={video.id} className={clsx(rowShell, "flex gap-3 p-2", watched && "opacity-55")}>
<div
data-testid="video-card"
data-video-id={video.id}
className={clsx(rowShell, "flex gap-3 p-2", watched && "opacity-55")}
>
<Thumb
video={video}
className={clsx("aspect-video shrink-0", spec.actionsBelow ? "w-40" : "w-44")}
@@ -587,7 +600,7 @@ function VideoCard({
"cv-card group glass-card glass-hover rounded-2xl transition-all duration-150 hover:-translate-y-1",
"flex flex-col",
spec.dense ? "p-2" : "p-2.5",
watched && "opacity-55"
watched && "opacity-55",
)}
>
{/* The small card's image is in the SAME size class as a row's (its column bottoms out at