fix(web): sidebar reste fixe sur page longue, page Liste de courses centrée (#21)
* fix(web): sidebar reste fixe sur page longue, page Liste de courses centrée
- AppLayout: .app-layout passe de min-height:100vh à height:100vh +
overflow:hidden, et .app-content devient le vrai conteneur de scroll
(overflow-y:auto). Avant, une page plus haute que le viewport faisait
défiler tout le document, entraînant la sidebar avec lui au lieu de la
garder fixe.
- ComingSoonPage (page "Liste de courses"): ajoute margin:0 auto, comme
.settings-page, au lieu de rester collée au bord gauche avec un grand
espace vide à droite sur les écrans larges.
* fix(web): la grille recettes stretche le panneau de détail sur toute sa hauteur
Régression révélée par le fix du layout précédent (AppLayout.scss) : tant
que `.app-layout` grandissait sans limite (`min-height: 100vh`), rien
dans la chaîne de hauteurs (.app-content → .recipes-page →
.recipes-page__catalog → .recipe-detail-panel) n'avait de hauteur
réellement définie, donc `.recipe-detail-panel { height: 100% }` ne
contraignait jamais rien — le panneau grandissait pour tout afficher,
masquant silencieusement que sa grille parente (`&__catalog`, display:
grid) n'a jamais eu de `grid-template-rows` explicite.
Avec `.app-layout` maintenant fixé à `height: 100vh`, `&__catalog` a
enfin une hauteur définie — mais sans `grid-template-rows`, sa seule
ligne implicite reste dimensionnée à son contenu (auto) au lieu de
s'étirer sur toute la hauteur disponible, comme l'intention documentée
en commentaire (« both stretched to the same full height ») le disait
déjà. Résultat concret : le panneau de détail recette rendait plus
court que son propre contenu, qui se retrouvait coupé par son
`overflow-y: auto` — repéré via l'échec CI de recipes.cy.ts sur
"opens a recipe's detail alongside the table" (timeout sur la
description, `<p>` non visible car clippée par un parent en overflow).
Vérifié en réinjectant les mêmes fixtures dans le navigateur (mock
fetch temporaire) : le panneau passe de 296px à 448px de haut, la
description reste entièrement dans ses limites.
* fix(web): restaure le layout table+panneau empilé sous 1024px
Le commit précédent (grid-template-rows sur .recipes-page__catalog)
corrigeait bien le layout desktop (2 colonnes, 1 ligne étirée sur
toute la hauteur), mais la même règle s'appliquait aussi telle quelle
au breakpoint mobile/tablette (@media max-width: 1024px), où la grille
passe à 1 seule colonne — donc à 2 lignes empilées (table puis
panneau), pas 1. Forcer ces 2 lignes dans un seul track `minmax(0, 1fr)`
coupait la hauteur disponible en deux et donnait 0px à la ligne du
tableau, dont le contenu se retrouvait entièrement clippé par son
propre `overflow-y: auto` — repéré via le nouvel échec CI de
recipes.cy.ts (Ratatouille non visible), le viewport par défaut de
Cypress (1000×660) tombant sous ce seuil de 1024px.
Réinitialise `grid-template-rows: auto` dans ce même bloc `@media`, à
côté du `height: auto` qui y était déjà (même logique : plus de ligne
unique à hauteur fixe à ce breakpoint). Revérifié dans le navigateur
aux deux largeurs (1000px et 1600px) avec les mêmes fixtures que le
test.
* test(web): agrandit le viewport du test de détail recette
Dernier morceau de la même régression : la grille catalogue+panneau
(master-detail) est un layout desktop, comme la grille de planning
(voir planning-page.cy.ts's `cy.viewport(1600, 900)`, même
justification). Au viewport par défaut de Cypress (1000×660), le
panneau de détail n'a tout simplement pas assez de hauteur pour
afficher photo + en-tête + ingrédients + étapes sans avoir besoin de
scroller en interne — c'est le comportement voulu de
`.recipe-detail-panel` (`overflow-y: auto`, voir son commentaire dans
recipes.scss), pas un bug. Ce n'était jamais visible avant que
`.app-layout` ait une vraie hauteur bornée (voir les 2 commits
précédents) : tout grandissait sans limite, donc rien n'avait jamais
besoin de scroller pour être visible.
Reproduit en rejouant le flow exact du test dans le navigateur (visite
/recettes, clic sur la ligne Omelette, pas juste une navigation directe
vers /recettes/2 — la simple navigation directe ne reproduisait pas
l'échec) : à 1000×660 la description était bien coupée
(descWithinPanel: false) ; à 1600×900 tout rentre.
This commit is contained in:
parent
4b988706cc
commit
c63bc15ea4
4 changed files with 49 additions and 1 deletions
|
|
@ -156,6 +156,14 @@ describe("Recipe catalog", () => {
|
|||
});
|
||||
|
||||
it("opens a recipe's detail alongside the table when its row is selected", () => {
|
||||
// Desktop-only master-detail layout, same reasoning as
|
||||
// planning-page.cy.ts's "Planning grid" tests — wider/taller than
|
||||
// Cypress's default 1000×660, which doesn't leave the detail panel
|
||||
// (photo + header + ingredients + steps) enough height to show
|
||||
// everything without needing its own internal scroll (by design, see
|
||||
// `.recipe-detail-panel` in recipes.scss) — this test asserts full
|
||||
// visibility without scrolling, so it needs the room.
|
||||
cy.viewport(1600, 900);
|
||||
cy.intercept("GET", /\/recipes\?/, { statusCode: 200, body: [ratatouille, omelette] });
|
||||
cy.intercept("GET", "**/recipes/2", { statusCode: 200, body: omeletteDetail }).as("getRecipe");
|
||||
|
||||
|
|
|
|||
|
|
@ -124,12 +124,32 @@
|
|||
min-height: 0;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(35vw, 38vw);
|
||||
// Without this, the grid's single implicit row falls back to
|
||||
// auto-sizing (tall enough for its content), not the full height of
|
||||
// `&__catalog` itself — silently masked as long as `.app-content`'s own
|
||||
// height was `min-height: 100vh` (auto-grew to fit anything, so
|
||||
// nothing downstream ever actually needed to stretch to a fixed
|
||||
// height). Fixing that (see AppLayout.scss) made `&__catalog`'s height
|
||||
// genuinely definite for the first time, which surfaced this: the
|
||||
// detail panel's own `height: 100%; overflow-y: auto` (see
|
||||
// `.recipe-detail-panel` below) had nothing to stretch against, came
|
||||
// out shorter than its content, and silently clipped it.
|
||||
grid-template-rows: minmax(0, 1fr);
|
||||
gap: var(--space-lg);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
&__catalog {
|
||||
grid-template-columns: 1fr;
|
||||
// The single-row `1fr` track above only makes sense for the desktop
|
||||
// side-by-side layout — collapsed to one column, the table and the
|
||||
// detail panel stack into two separate rows instead, so forcing them
|
||||
// both into one `1fr` track split the available height in half and
|
||||
// gave the table row 0px (its own content pushed below the fold,
|
||||
// clipped by its `overflow-y: auto`). Reset to the default `auto`
|
||||
// (each row sized to its content) — matches `height: auto` below,
|
||||
// which already stopped assuming a single fixed-height row here.
|
||||
grid-template-rows: auto;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,14 @@
|
|||
// No `@use` of the theme partial needed here — see HomePage.scss's identical
|
||||
// note: every token below is a CSS custom property, available at runtime.
|
||||
|
||||
// `height` (not `min-height`): the layout must stay pinned to exactly the
|
||||
// viewport, never grow taller than it — otherwise a tall page scrolls the
|
||||
// whole document, dragging the sidebar out of view with it. `overflow:
|
||||
// hidden` backs that up so nothing can force the document itself to grow;
|
||||
// `.app-content` below is the one place that actually scrolls.
|
||||
.app-layout {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
background: var(--color-background);
|
||||
}
|
||||
|
|
@ -27,6 +33,10 @@
|
|||
background: var(--color-surface);
|
||||
border-right: 1px solid var(--color-border);
|
||||
transition: width 0.15s ease;
|
||||
// Own scroll, independent of `.app-content` — only matters on a very
|
||||
// short viewport with a long nav, but keeps the rail from ever forcing
|
||||
// `.app-layout` past 100vh.
|
||||
overflow-y: auto;
|
||||
|
||||
&__top {
|
||||
display: flex;
|
||||
|
|
@ -315,6 +325,11 @@
|
|||
// Content can scroll independently of the sidebar (e.g. a long planning
|
||||
// table) without the fixed-width rail ever needing to shrink.
|
||||
min-width: 0;
|
||||
// The actual scroll container: `.app-layout` is pinned to `height: 100vh`
|
||||
// above, so a page taller than the viewport scrolls in here instead of
|
||||
// scrolling the document (which would drag the sidebar along with it).
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: var(--space-xl);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,13 @@
|
|||
// Styles for ComingSoonPage — shared by every stub section page.
|
||||
// =============================================================================
|
||||
|
||||
// Centered, not pinned to `.app-content`'s left edge — same reasoning as
|
||||
// `.settings-page` (settings-pages.scss): on a wide desktop viewport a
|
||||
// left-aligned `max-width` here just left a lopsided gap down the right
|
||||
// side instead of framing the placeholder copy.
|
||||
.coming-soon-page {
|
||||
max-width: 40rem;
|
||||
margin: 0 auto;
|
||||
|
||||
p {
|
||||
color: var(--color-text-muted);
|
||||
|
|
|
|||
Loading…
Reference in a new issue