Add accordion + active-filter chip bar for mobile repertoire

- repertoire-index.php: wrap each filter column in rep-accordion with toggle
  button, chevron, badge (active filter count); add rep-chip-bar with
  removable active-filter chips above the columns
- repertoire.css: mobile (≤640px) accordion mode — columns collapse to
  single-open accordion sections with 48px touch targets; chip bar becomes
  sticky; desktop/tablet layout unchanged via display:none on toggle elements
- repertoire.php: JS for single-accordion-open behavior on mobile, HTMX
  re-init after swap, resize-breakpoint cleanup
- docs/repertoire-mobile-propositions.md: analysis + 4 architecture proposals
This commit is contained in:
Pontoporeia
2026-06-22 15:45:58 +02:00
parent cca3d08f05
commit ecb90ba5dd
5 changed files with 529 additions and 45 deletions

View File

@@ -0,0 +1,111 @@
# Répertoire — Mobile Responsive Propositions
> Date: 2026-06-22
> Context: Adapting the interactive 6-column filter model to mobile viewports
## Current Architecture
- `repertoire.php` — page wrapper, loads HTMX + popover JS
- `repertoire-index.php` — 6-column filter index (also served as HTMX partial on filter toggles)
- `repertoire.css` — all styling, 3 breakpoints: 1024px → 3 cols, 600px → 1 col
**Desktop interactive model:**
1. **6-column filter grid** — years, AP, orientations, finality, students, keywords. Each entry is a `<button>` with `hx-get` swapping `#repertoire-index` via HTMX.
2. **Hover-to-preview** on student names — `hx-get` on `mouseenter`, renders `<div id="student-popover">` positioned via JS.
3. **Pure CSS hamburger menu** in global header, separate from this page.
## Problems on Mobile
1. **Column overload** — Six vertically-stacked scrollable lists, each with independent `overflow-y: auto`, create deeply nested scrolling. Hostile UX — scroll hijacking, content below hard to discover.
2. **Hover-based preview impossible on touch**`mouseenter`/`mouseleave` has no equivalent on touch devices. Student links navigate to `/tfe?id=…` on tap, but preview popover never fires.
3. **HTMX navigation cost** — Each filter tap triggers full HTTP round-trip + grid re-render. On mobile networks, latency is perceptible. pushState doubles the fetch on back-navigation.
4. **Touch targets** — Filter entries use `padding: var(--space-3xs) 0` (~5px vertical). Tapping "Design et Politique du Multiple" without mis-hitting neighbors is error-prone.
5. **No filter state visibility** — Once scrolled past the first 2-3 sections, selected filter states are invisible (buried in scroll regions).
6. **Header search bar competition**`header-search-wrap` renders above main, competing for vertical space with the full-height column layout.
---
## Proposition A — Accordion + Active Filters Bar (minimal JS)
Each of the 6 filter columns becomes a collapsible accordion section. A persistent "active filters" bar shows selected filters as removable chips. Students column becomes a tap-to-open drawer (replaces hover).
**Implementation:**
- `<details>` + `<summary>` on each section heading for no-JS baseline. Enhanced with a tiny JS toggle for smooth animation if desired.
- On mobile, only one accordion section open at a time. On desktop, all remain open (unchanged).
- Extract selected filters into a horizontal chip bar above the accordion — each chip fires the same HTMX toggle URL to de-select.
- Replace hover popover with a click-to-open bottom sheet: tap a student name → slide-up panel shows thesis cards.
- Years column optionally becomes a horizontal pill bar (scannable horizontally).
**Pros:** Progressive enhancement, works without JS (details/summary), low structural change to PHP partial.
**Cons:** Opening/closing accordions to scan filters is slower than the all-visible desktop model.
---
## Proposition B — Tab Bar with Filter View Switcher
The 6 filter dimensions become horizontal tabs (scrollable on small screens). Tapping a tab shows only that dimension's list full-width. A "Résultats" badge in the header shows match count.
**Implementation:**
- `<nav role="tablist">` across the top, horizontally scrollable (CSS `scroll-snap`).
- Each tab panel renders one `<section>` at full width. Single filter column, no nested scroll — the list scrolls with the page.
- Students tab replaces hover popover with inline cards: tap a name → inline expand to show thesis previews.
- Selected filter count shown as a badge on each tab.
- Active filter chips in a persistent bar.
**Pros:** Single scroll context, excellent for scanning one dimension at a time, familiar mobile pattern.
**Cons:** Significant PHP restructuring — each tab panel excludes the other 5 columns. Needs JS for tab switching (or HTMX per tab). Separates filters from each other visually.
---
## Proposition C — Drawer/Panel Pattern (most native-feeling)
Results-first view with a filter drawer. A "Filtres" button opens a side panel / bottom sheet containing all filter columns. Applying filters updates results and closes the drawer.
**Implementation:**
- Mobile: fixed "Filtres (N)" button at the top. Tap → sliding bottom sheet with all 6 filter columns in a single scrollable panel.
- Tapping an entry applies the filter via HTMX, optionally closes the sheet (or stays open for multi-filtering).
- Count badge shows active filter count.
- Desktop: unchanged — 6-column grid remains.
- Students: scrollable list in main content area below filter button, tap-to-expand cards.
- Popover JS deleted entirely.
**Pros:** Extensively tested pattern (maps apps, e-commerce). Closest to native mobile filter UX. Desktop unchanged. Single scroll container — no nested scrolling.
**Cons:** Needs new drawer/sheet component. Results-first approach changes the page's purpose — currently the page *is* the filters, not a results view.
---
## Proposition D — Hybrid: Filter Bar + Scrollable Carousel Sections
Keep the 6-column structure but transform into a horizontally scrollable carousel on mobile. Sections sit in a horizontal scroll container with snap points.
**Implementation:**
- `@media (max-width: 640px)`: `.repertoire-index` grid becomes flex row with `overflow-x: auto; scroll-snap-type: x mandatory`.
- Each `.repertoire-col` becomes `scroll-snap-align: start; min-width: 85vw`.
- Heading acts as sticky within each snap panel.
- Students column moves to full-width below the carousel.
- Navigation dots or scroll hint at the bottom.
- Popover becomes long-press or tap-and-hold on students.
**Pros:** Preserves "browse everything" mental model. Low structural change — just CSS. Sections independently scannable.
**Cons:** Horizontal carousels have discoverability issues. Popover still needs touch replacement. Horizontal+vertical scroll nesting creates gesture conflicts.
---
## Recommended Approach
**Proposition A (Accordion + Chip Bar)** is the most pragmatic starting point:
1. Least structural PHP changes
2. Eliminates nested scrolling (the #1 problem)
3. Provides clear filter-state visibility via chips
4. Degrades gracefully (details/summary works without JS)
5. Same HTMX endpoints work — only container shape changes
### Phased Implementation
1. **Phase 1:** Accordion sections + active filter chip bar (mobile only via CSS media query). Desktop unchanged.
2. **Phase 2:** Replace student hover popover with tap-to-open bottom sheet (touch-aware JS, keep hover for desktop).
3. **Phase 3:** Polish — touch target sizing (min 44px), filtered count badges, scroll-position memory on HTMX swap.