Replace the mobile sidebar with a bottom sheet, grouped by data shape #10

Merged
kyuno merged 2 commits from feature/mobile-nav into master 2026-09-16 15:55:57 +02:00
Owner

Summary

  • Replaces the mobile-only "sidebar reshapes into a horizontal scrollbar" treatment (Shell.css's old 720px media query) with a bottom sheet: a slim top bar, a "Parcourir" trigger docked above the music bar, and a sheet that slides up from the bottom.
  • The sheet's content mirrors the real data shape rather than a flat list: Accueil (fixed) and Listes de lecture (fixed, shown only when a playlists-type library exists) bookend a Bibliothèques group — the part whose count and contents depend on what the connected Emby server actually returns.
  • Zero server-side changes: getLibraries() already sends collectionType per library (CatalogService.ts) — this PR is the first thing to read it client-side.
  • New per-collectionType icons for the sheet (the sidebar has never had any) — small inline SVGs, same convention as Player.ts's own icon constants.
  • The music bar's stacking under the new nav trigger is now structural (MusicBar.css's .musicBar no longer positions itself — a new .bottomStack wrapper does) instead of a hardcoded pixel offset, since the bar's own rendered height isn't constant.

Context

Follows directly from a round of mockups (compared a bottom tab bar, a hamburger drawer, this bottom sheet, and a polished version of the existing horizontal bar) and feedback on exactly this grouping (Accueil / Bibliothèques / Listes de lecture).

Verification

  • Full typecheck/build (client only).
  • Desktop sidebar re-checked untouched: same nav items, same behavior, at desktop width.
  • The compiled CSS's media query and base mobile rules were read back byte-for-byte from client/dist/app.css to confirm they match what was written.
  • The mobile sheet's open/close, closing on a link tap, active-state highlighting (now widened from #sidebarNav alone to every .navItem), the grouped rows, and the conditional "Listes de lecture" row were all driven end to end against the real Shell.ts/Shell.html with fake library data (no Emby login reachable from this sandbox — the real Shell only mounts after login).
  • The music-bar/trigger stacking was confirmed with a synthetic long-track-title music bar sitting flush above the trigger, no gap or overlap.
  • Not verified: the actual rendered layout at a genuinely narrow viewport — this sandbox's browser tool's viewport emulation stopped taking effect partway through this session (confirmed: screen.width reflected the requested size, innerWidth/matchMedia did not), so the mobile-width visual check was done by forcing the same CSS rules through an injected override rather than a real ≤720px viewport. Worth an early real-phone check once deployed.

Test plan

  • Open on a real phone (or a properly narrow desktop browser window), confirm the sidebar is gone and the bottom sheet appears below 720px
  • Confirm Accueil / Bibliothèques / Listes de lecture render in that order, with the library grid matching your Emby server's actual libraries
  • Start a listen party, confirm the "Parcourir" trigger sits flush above the music bar with no gap/overlap, including with a long track/artist name
  • Confirm the sheet closes after tapping a destination, and that browser back/forward also closes it

🤖 Generated with Claude Code

## Summary - Replaces the mobile-only "sidebar reshapes into a horizontal scrollbar" treatment (`Shell.css`'s old 720px media query) with a bottom sheet: a slim top bar, a "Parcourir" trigger docked above the music bar, and a sheet that slides up from the bottom. - The sheet's content mirrors the real data shape rather than a flat list: **Accueil** (fixed) and **Listes de lecture** (fixed, shown only when a `playlists`-type library exists) bookend a **Bibliothèques** group — the part whose count and contents depend on what the connected Emby server actually returns. - Zero server-side changes: `getLibraries()` already sends `collectionType` per library ([CatalogService.ts](server/src/services/CatalogService.ts)) — this PR is the first thing to read it client-side. - New per-`collectionType` icons for the sheet (the sidebar has never had any) — small inline SVGs, same convention as `Player.ts`'s own icon constants. - The music bar's stacking under the new nav trigger is now structural (`MusicBar.css`'s `.musicBar` no longer positions itself — a new `.bottomStack` wrapper does) instead of a hardcoded pixel offset, since the bar's own rendered height isn't constant. ## Context Follows directly from a round of mockups (compared a bottom tab bar, a hamburger drawer, this bottom sheet, and a polished version of the existing horizontal bar) and feedback on exactly this grouping (Accueil / Bibliothèques / Listes de lecture). ## Verification - Full `typecheck`/`build` (client only). - Desktop sidebar re-checked untouched: same nav items, same behavior, at desktop width. - The compiled CSS's media query and base mobile rules were read back byte-for-byte from `client/dist/app.css` to confirm they match what was written. - The mobile sheet's open/close, closing on a link tap, active-state highlighting (now widened from `#sidebarNav` alone to every `.navItem`), the grouped rows, and the conditional "Listes de lecture" row were all driven end to end against the real `Shell.ts`/`Shell.html` with fake library data (no Emby login reachable from this sandbox — the real Shell only mounts after login). - The music-bar/trigger stacking was confirmed with a synthetic long-track-title music bar sitting flush above the trigger, no gap or overlap. - **Not verified**: the actual rendered layout at a genuinely narrow viewport — this sandbox's browser tool's viewport emulation stopped taking effect partway through this session (confirmed: `screen.width` reflected the requested size, `innerWidth`/`matchMedia` did not), so the mobile-width visual check was done by forcing the same CSS rules through an injected override rather than a real ≤720px viewport. Worth an early real-phone check once deployed. ## Test plan - [ ] Open on a real phone (or a properly narrow desktop browser window), confirm the sidebar is gone and the bottom sheet appears below 720px - [ ] Confirm Accueil / Bibliothèques / Listes de lecture render in that order, with the library grid matching your Emby server's actual libraries - [ ] Start a listen party, confirm the "Parcourir" trigger sits flush above the music bar with no gap/overlap, including with a long track/artist name - [ ] Confirm the sheet closes after tapping a destination, and that browser back/forward also closes it 🤖 Generated with [Claude Code](https://claude.com/claude-code)
kyuno added 1 commit 2026-09-16 14:57:17 +02:00
Replace the mobile sidebar with a bottom sheet, grouped by data shape
Some checks failed
Publier l'image Docker / test (pull_request) Failing after 4s
Publier l'image Docker / publish (pull_request) Has been skipped
40a897cf1b
The old mobile treatment just reshaped the sidebar into a horizontally
scrolling top bar - easy to miss that there's more to scroll to, and
"Se deconnecter" ended up buried at the far end of it. Explored as
mockups first (compared against a bottom tab bar, a hamburger drawer,
and a polished version of the existing bar) before writing this.

The sheet mirrors the real data shape instead of a flat list: Accueil
and Listes de lecture (when a playlists-type library exists) are fixed
rows bookending a Bibliotheques group, which is the part that actually
varies with whatever the connected Emby server returns - zero new
server work, since getLibraries() already sends collectionType per
library, just unused on the client until now.

The music bar's stacking under the new nav trigger is now structural
(a shared position:fixed flex column) instead of a hardcoded offset,
since the bar's own height isn't constant - its row can wrap on a
narrow screen with a long track/artist name.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
kyuno added 1 commit 2026-09-16 15:55:51 +02:00
Merge remote-tracking branch 'origin/master' into feature/mobile-nav
Some checks failed
Publier l'image Docker / test (pull_request) Failing after 4s
Publier l'image Docker / publish (pull_request) Has been skipped
2f10a46664
# Conflicts:
#	README.md
#	docs/architecture.md
kyuno merged commit e9b6a2541c into master 2026-09-16 15:55:57 +02:00
kyuno deleted branch feature/mobile-nav 2026-09-16 15:55:57 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: kyuno/watchparty#10
No description provided.