fix(ui): stable shelf-card menu triggers, a named Button by type, true layout comments
- Home's rail handed each card a fresh `() => menu.triggerProps(c)` per
render, defeating memo(VideoCard) on every tile whenever the menu's own
state changed. `useItemTriggers` (ui/useContextMenu) keeps one trigger per
item, index-aligned; tested for identity across renders.
- The Button accessible-name union had one hole: `<Button icon={…} />` with
no children and no size typechecked into a nameless button. A textful
button now needs children or a name; pinned with @ts-expect-error.
- comfortPin's header said the pin belongs "on every card and row", which
the code never meant (an episode, a season, a person are not pin kinds).
It now says what is pinnable — and the show page's Related strip, whose
shows ARE pinnable, gets the pin menu it was missing (and a rem width).
- gridColumns / feedView / VirtualGrid claimed layouts 1024–2560 are
"byte-identical" under the column cap; the small cards are capped at 2560
with the filter rail collapsed. The comments say so.
This commit is contained in:
@@ -11,11 +11,12 @@ import { type ActionMenuItem } from "./ui/ActionMenu";
|
||||
|
||||
// E24 S3 — "put this on my comfort shelf", from wherever you happen to be looking at the thing.
|
||||
//
|
||||
// The shelf is the Home surface's object, but the GESTURE belongs on every card and row in the app:
|
||||
// you decide something is comfort media while you are watching it, not while you are on a page that
|
||||
// already lists it. So this file is the one place the pin lives, and every surface composes the same
|
||||
// `ActionMenuItem` into the menu it already has (`Playlists`, `PlaylistsRail`) or mounts the
|
||||
// `ComfortPinMenu` wrapper when it has none.
|
||||
// The shelf is the Home surface's object, but the GESTURE belongs wherever a pinnable thing is
|
||||
// shown — a video, a channel, a playlist, a Plex show or movie: you decide something is comfort media
|
||||
// while you are watching it. (Locked decision 3: an episode, a season and a person are not pin kinds,
|
||||
// so their cards and strips carry no pin.) This file is the one place the pin lives; every surface
|
||||
// composes the same `ActionMenuItem` into the menu it already has (`Playlists`, `PlaylistsRail`) or
|
||||
// mounts the `ComfortPinMenu` wrapper when it has none.
|
||||
//
|
||||
// Feature layer, not `components/ui/`: it speaks a domain API slice, which the platform boundary
|
||||
// (eslint `no-restricted-imports`) forbids a `ui/` primitive from doing. The MENU SURFACE that
|
||||
|
||||
Reference in New Issue
Block a user