import { type ReactNode } from "react"; import { hueOf, hueTileGradient } from "../lib/hueTile"; import { navItemAttrs } from "../lib/listNav"; import { MEDIA_IMG } from "./ui/mediaCardStyles"; import { Pressable } from "./ui/Pressable"; import { cardImage } from "../lib/plexImage"; // A browse tile split in two: the TOP half shows up to 2 montage posters (from /api/plex/image/{key}), // the BOTTOM half is a solid colour-hash band that carries the label โ€” so the text is always readable // (a full-bleed poster collage drowned it). A group with no art falls back to an all-colour tile, never // blank. Shared by the Discover genre tiles and the Playlist/Collection browse tiles. // // Hover = the media card's: the shadow lifts and the art zooms inside its half, plus the // accent edge glass-hover gives a pressable panel. It had `glass-hover` on a tile with no border, so // the only visible change was a shadow under a colour band โ€” the owner read it as no hover at all. export default function PosterTile({ title, subtitle, topRight, art, onClick, className, navIndex, }: { title: string; subtitle?: ReactNode; // a bottom sub-line under the title (e.g. "12 items ยท 4h 30m") topRight?: ReactNode; // top-right corner content on the colour band (e.g. an icon) art?: string[]; // up to 2 poster rating_keys; fewer/none falls back to the colour hash onClick: () => void; className?: string; // caller sets the height (e.g. "h-20" / "h-28") navIndex?: number; // position in a keyboard-walkable grid (lib/listNav); Enter is the button's own }) { const posters = (art ?? []).slice(0, 2); const band = hueTileGradient(hueOf(title)); return ( {/* Top half: 2 montage posters, or the colour hash when a group has no art. */}
{posters.length > 0 && [0, 1].map((i) => posters[i] ? ( ) : (
), )}
{/* Bottom half: solid colour band โ€” the label lives here so it stays readable over any art. */}
{topRight != null && {topRight}}
{title}
{subtitle != null &&
{subtitle}
}
); }