feat(ui): E31 S4c — the channel header folds, the Plex pages fill their hero, the player gets a side panel
- Channel page: the banner and identity block fold away once the grid scrolls (ui/scrollFold: folds past 32px only if the page can stay scrolled, unfolds at the very top) and the name rides in the tab row. One Back button in both states keeps its focus; folded at a tablet width the actions wrap instead of pushing the page sideways. - Plex movie and show pages: the TMDB facts over the key crew are the hero's second column (plexDetailAside), the keywords sit under the text; the show page shows them for the first time, with the same three toggles. A collection's hero is sized to its text. - YouTube player, 1280px and wider: the title, channel, actions, description and queue sit in a side panel beside the video, which takes the window's height (1438x809 at 1920x911, was ~1008 wide). The wheel scrolls that panel while it can and turns the volume elsewhere. - DESIGN.md decision log: the keywords' place under the text.
This commit is contained in:
@@ -230,7 +230,9 @@ export function ActionBtn({
|
||||
/** The shared detail-page hero shell used by BOTH the show page and the season subpage (they were
|
||||
* copy-paste siblings). Owns the glass frame, the play/resume poster button, the customize-menu slot,
|
||||
* and the flex info column; the caller passes the customize menu + the title/metadata/actions as
|
||||
* `children`. Poster is slightly larger on the show page (default) than the season page. */
|
||||
* `children`. Poster is slightly larger on the show page (default) than the season page. `aside` is the
|
||||
* show page's second column (the facts and crew, plexDetailAside): beside the text in a wide hero,
|
||||
* under it in a narrow one. */
|
||||
export function DetailHero({
|
||||
thumb,
|
||||
posterTitle,
|
||||
@@ -239,6 +241,7 @@ export function DetailHero({
|
||||
onPosterClick,
|
||||
posterSizeClass = "w-32 sm:w-44",
|
||||
customizeMenu,
|
||||
aside,
|
||||
children,
|
||||
}: {
|
||||
thumb: string;
|
||||
@@ -248,11 +251,11 @@ export function DetailHero({
|
||||
onPosterClick: () => void;
|
||||
posterSizeClass?: string;
|
||||
customizeMenu: ReactNode;
|
||||
aside?: ReactNode;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className={`${SURFACE.panel} relative p-4 sm:p-5 mb-8 flex gap-4 sm:gap-5`}>
|
||||
<div className="absolute right-3 top-3 z-base">{customizeMenu}</div>
|
||||
const main = (
|
||||
<div className="flex gap-4 sm:gap-5">
|
||||
<Pressable
|
||||
onClick={onPosterClick}
|
||||
disabled={posterDisabled}
|
||||
@@ -273,6 +276,19 @@ export function DetailHero({
|
||||
<div className="min-w-0 flex-1">{children}</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className={`${SURFACE.panel} @container relative p-4 sm:p-5 mb-8`}>
|
||||
<div className="absolute right-3 top-3 z-base">{customizeMenu}</div>
|
||||
{aside ? (
|
||||
<div className="grid gap-6 @5xl:grid-cols-[minmax(0,1fr)_minmax(0,24rem)]">
|
||||
{main}
|
||||
{aside}
|
||||
</div>
|
||||
) : (
|
||||
main
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/** The "mark whole show/season watched" hero action (icon + label flip on state). Verbatim in both
|
||||
|
||||
Reference in New Issue
Block a user