Fix library tile buttons rendering above the sticky header while scrolling
Some checks failed
Publier l'image Docker / test (pull_request) Failing after 4s
Publier l'image Docker / publish (pull_request) Has been skipped

.libraryHeader and the alphabet index's .letterHeading copied their
z-index: 2 from tiles.css's own pre-existing sticky .searchBar - which
never showed the problem in practice, since a single slim input has
little room to actually overlap a scrolling tile. A tile's own
.tileOverlay action buttons are also z-index: 2 though, and an equal
z-index ties toward whichever renders later in the DOM - a tile, always
after the header. Wrapping the header into a much taller block gave a
scrolling tile far more room to pass underneath before fully clearing
it, which is what actually surfaced the tie. Raised both to z-index: 3,
matching shell/Shell.css's own mobileTopBar.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Nicolas 2026-09-16 22:37:11 +02:00
parent 292fec9c19
commit d23fcc028b
4 changed files with 56 additions and 2 deletions

View file

@ -376,6 +376,9 @@ Then put it behind your existing reverse proxy like everything else
it was bucketing by display name instead of Emby's own SortName, it was bucketing by display name instead of Emby's own SortName,
so an article-stripped title ("The ...") threw a whole run off — so an article-stripped title ("The ...") threw a whole run off —
see docs/architecture.md see docs/architecture.md
- [x] Fixed library tile buttons rendering on top of the sticky header
while scrolling — an equal z-index tie that a scrolling tile won
— see docs/architecture.md
- [ ] Try a full party end-to-end with two real accounts (still the main gap) - [ ] Try a full party end-to-end with two real accounts (still the main gap)
- [ ] Try casting to a real Chromecast (only the SDK's own bootstrap is - [ ] Try casting to a real Chromecast (only the SDK's own bootstrap is
confirmed here — no real device/session) confirmed here — no real device/session)

View file

@ -8,7 +8,11 @@
grid-column: 1 / -1; grid-column: 1 / -1;
position: sticky; position: sticky;
top: var(--section-sticky-top, 0px); top: var(--section-sticky-top, 0px);
z-index: 2; /* Same z-index: 3 as views/library/Library.css's own .libraryHeader,
and for the identical reason: tiles.css's .tileOverlay is z-index:
2, and a tie there breaks toward whichever renders later in the
DOM - a tile, always after this heading. */
z-index: 3;
background: var(--bg); background: var(--bg);
color: var(--accent-bright); color: var(--accent-bright);
font-size: 13px; font-size: 13px;

View file

@ -8,7 +8,18 @@
.libraryHeader { .libraryHeader {
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 2; /* Above 2, not just tiles.css's own .searchBar precedent: a tile's
.tileOverlay action buttons are ALSO z-index: 2, and (unlike the
slim .searchBar this header replaced) this header is tall enough
that a scrolling tile's own overlay - always-visible on touch, see
tiles.css's (hover: none) block - reaches it well before it's fully
scrolled past. Equal z-index ties break on paint order, and a tile
(inside #grid, after this header in the DOM) wins that tie -
reported directly as buttons rendering over the header while
scrolling. z-index: 3 matches shell/Shell.css's own .mobileTopBar,
the other sticky header this one already has to stack correctly
under on mobile. */
z-index: 3;
background: var(--bg); background: var(--bg);
padding-top: 4px; padding-top: 4px;
} }

View file

@ -4103,6 +4103,42 @@ it produced the same `A, B, T, B, L` heading sequence against the old
bucket-by-`name` code, then confirmed the fix collapses it to the bucket-by-`name` code, then confirmed the fix collapses it to the
correct `A, B, L` against the exact same input. correct `A, B, L` against the exact same input.
## Library tile buttons rendering on top of the sticky header
Reported directly: scrolling a library, a tile's own action buttons
("Lancer une watch party" / "Voir sur Emby") would briefly render
*above* the sticky title+search header instead of scrolling behind it.
Both `.libraryHeader` and the alphabet index's `.letterHeading` were
`z-index: 2` - copied from `tiles.css`'s own pre-existing `.searchBar`,
sticky at that same value long before either of them existed. What
that copy missed: a tile's own `.tileOverlay` (its hover-revealed
action buttons - always-visible rather than hover-revealed on a touch
device, see `tiles.css`'s `(hover: none)` block) is *also* `z-index: 2`.
Equal z-index is a tie, and a tie breaks toward whichever renders later
in the DOM - a tile, inside `#grid`, always after the header. The
original slim `.searchBar` never showed this in practice (a single
input has little vertical range to actually overlap a scrolling tile
during the transition); wrapping it into the much taller
`.libraryHeader` gave a scrolling tile far more room to pass directly
underneath before fully clearing it, is what actually surfaced it.
Fixed by raising `.libraryHeader` and `.letterHeading` to `z-index: 3`
- comfortably clear of `.tileOverlay`'s 2, and matching
`shell/Shell.css`'s own `.mobileTopBar` (the other sticky header
`.libraryHeader` already has to stack correctly under on mobile).
Verified: full `typecheck`/`build` (client only). Confirmed as a real
regression, not just reasoned about - real compiled CSS loaded into a
page reproducing `.libraryHeader` + a real `.grid` of tiles (their
`.tileOverlay` forced visible, simulating a touch device), scrolled so
a tile genuinely overlapped the header's own rect, then
`elementsFromPoint` read the actual paint order at that point: with
the header's z-index forced back to the old `2`, `.tileOverlay` topped
the stack exactly as reported; restored to `3`, the header (and the
search input inside it) topped it instead, `.tileOverlay` three layers
down, unreachable.
## Known limitations ## Known limitations
- Playback always goes through `hls.js` against whatever Emby's - Playback always goes through `hls.js` against whatever Emby's