Second slice of the E11 keyboard layer (S4b). S4a gave the feed, the library and the channel page `j`/`k`, the arrows and Enter; Home's shelves and the whole Plex module were still Tab-stop country — a Plex poster is its own Tab stop, and a rail's cards sat behind every control of the cards before. - `lib/listNav`: a list that mounts every item no longer declares a count or columns — both are measured off the DOM when a key is pressed, so an auto-fill grid's columns follow its width and a rail is one row. ↑ on a list's top row and ↓ on its bottom row go on to the neighbouring list, onto the item horizontally nearest the one left (owner decision D4: ←→ within a rail, ↑↓ to the rail above or below). The first `j` skips cards a rail has scrolled out to the left. - `Carousel keyboardNav` registers the scroller; the scroller gets a 4px inset (against a -4px margin, layout unchanged) so the focus ring is not clipped, and `[data-nav-index]` a 2.5rem inline scroll margin so a card stepped into view clears the rail's edge fade and paging arrow. - `ui/NavGrid`: the plain, fully mounted grid that registers itself. - `navIndex` on PlexPosterCard / SeasonCard / EpisodeCard (the card root is the item, the poster the open element — the ring goes round poster and title, D2), PosterTile and Home's ShelfTile (the button is the item); cast, related and collection-strip buttons carry the attrs directly. - Wired: Home's comfort and resume rails; Plex Browse titles + episodes, Discover rails + genres, collection view, playlists/collections browse, person known-for + filmography, show seasons, season episodes, cast/related strips, info-page cast + collection strips. - `listNav.wiring.contract.test`: every `Carousel` says `keyboardNav`, every card says `navIndex`, and a card with `navIndex` sits inside a NavGrid / Carousel / VirtualGrid — both halves are opt-in, and either one missing leaves a list the keyboard silently skips.
24 lines
819 B
TypeScript
24 lines
819 B
TypeScript
import { useRef, type ReactNode } from "react";
|
|
import { useListNav } from "../../lib/listNav";
|
|
|
|
// A plain grid of cards the keyboard can walk — `j`/`k`, the arrows, Enter (lib/listNav) — for the
|
|
// grids that mount every item (the Plex title, season and episode grids). Nothing to count: the items
|
|
// and the columns per row are measured when a key is pressed, so an auto-fill grid's columns follow
|
|
// its width. Each child spreads `navItemAttrs(index)` on its root; a virtualized grid is VirtualGrid's
|
|
// `keyboardNav` instead.
|
|
export default function NavGrid({
|
|
className,
|
|
children,
|
|
}: {
|
|
className?: string;
|
|
children: ReactNode;
|
|
}) {
|
|
const ref = useRef<HTMLDivElement>(null);
|
|
useListNav(ref, { enabled: true });
|
|
return (
|
|
<div ref={ref} className={className}>
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|