Merge pull request 'fix(planning): la grille remplit l'écran, une case ne grandit plus (#110)' (#113) from fix/planning-grid-fluid-height into main
Some checks failed
Some checks failed
This commit is contained in:
commit
d4d1b9eb3a
2 changed files with 75 additions and 0 deletions
|
|
@ -182,6 +182,49 @@ describe("Planning grid", () => {
|
||||||
cy.contains("Semaine du 10 au 16 août 2026").should("be.visible");
|
cy.contains("Semaine du 10 au 16 août 2026").should("be.visible");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Issue #110 — a slot with many recipes used to stretch its `<td>`, and
|
||||||
|
// with it the whole row and the table, past `.planning-grid-wrapper`
|
||||||
|
// into a vertical scroll (the other cells of that row just gaining dead
|
||||||
|
// space). The chip list now scrolls inside its own cell instead.
|
||||||
|
it("keeps a heavy slot's recipes scrolling inside the cell, not stretching the grid", () => {
|
||||||
|
cy.intercept("GET", /\/planning\?/, {
|
||||||
|
statusCode: 200,
|
||||||
|
body: {
|
||||||
|
id: 1,
|
||||||
|
startDate: "2026-08-17T00:00:00.000Z",
|
||||||
|
finishDate: "2026-08-23T00:00:00.000Z",
|
||||||
|
items: Array.from({ length: 14 }, (_, i) => ({
|
||||||
|
id: i + 1,
|
||||||
|
weekDay: "lundi",
|
||||||
|
meal: "dejeuner",
|
||||||
|
portions: 2,
|
||||||
|
recipe: { id: i + 1, name: `Recette ${i + 1}` },
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.visit("/");
|
||||||
|
cy.get(".recipe-chip").should("have.length", 14);
|
||||||
|
|
||||||
|
// The busy cell's own recipe list is now the scroller: it's capped and
|
||||||
|
// scrolls its own overflow instead of stretching the `<td>` (and with
|
||||||
|
// it the whole row, then the table past `.planning-grid-wrapper` into a
|
||||||
|
// tall vertical scroll).
|
||||||
|
cy.get(".meal-cell__recipes").should(($lists) => {
|
||||||
|
const list = [...$lists].find(
|
||||||
|
(el) => el.querySelectorAll(".recipe-chip").length === 14,
|
||||||
|
) as HTMLElement;
|
||||||
|
expect(list, "the 14-recipe cell's list").to.exist;
|
||||||
|
expect(getComputedStyle(list).overflowY).to.be.oneOf(["auto", "scroll"]);
|
||||||
|
expect(list.scrollHeight).to.be.greaterThan(list.clientHeight);
|
||||||
|
expect(list.clientHeight).to.be.lessThan(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get(".planning-grid-wrapper").should(($w) => {
|
||||||
|
expect($w[0].scrollHeight).to.be.lessThan($w[0].clientHeight * 1.25);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("jumps to an arbitrary week by picking a day in the calendar popover", () => {
|
it("jumps to an arbitrary week by picking a day in the calendar popover", () => {
|
||||||
cy.intercept("GET", /\/planning\?/, { statusCode: 200, body: null }).as("getPlanning");
|
cy.intercept("GET", /\/planning\?/, { statusCode: 200, body: null }).as("getPlanning");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,18 @@ table.planning-grid {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
|
|
||||||
|
// Share the wrapper's height evenly across the five meal rows instead of
|
||||||
|
// letting each row size to its own content. A `height` on a table row is
|
||||||
|
// a minimum the browser then stretches to absorb the table's leftover
|
||||||
|
// height; an equal tiny value on every row spreads that leftover evenly,
|
||||||
|
// so the grid genuinely fills the screen rather than being only as tall
|
||||||
|
// as its busiest column (with dead space under the short ones). The
|
||||||
|
// per-cell scroll below is what then keeps a heavy slot from pushing its
|
||||||
|
// row past that share.
|
||||||
|
tbody tr {
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
|
|
@ -178,12 +190,32 @@ table.planning-grid {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-xs);
|
gap: var(--space-xs);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
// The content must not be what defines the row's height: a slot with
|
||||||
|
// several recipes would otherwise stretch its `<td>`, and with it the
|
||||||
|
// whole row (every other day's cell gaining the same dead height under
|
||||||
|
// `vertical-align: top`), then the table past the wrapper into a
|
||||||
|
// vertical scroll. `min-height: 0` lets this flex column shrink to its
|
||||||
|
// share of the row so `.meal-cell__recipes` below can take over the
|
||||||
|
// scrolling.
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.meal-cell__recipes {
|
.meal-cell__recipes {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-xs);
|
gap: var(--space-xs);
|
||||||
|
// A slot only ever holds a handful of recipes in real use; past that the
|
||||||
|
// list scrolls inside the cell instead of stretching the `<td>` (and
|
||||||
|
// with it the whole row, then the table past `.planning-grid-wrapper`
|
||||||
|
// into a vertical scroll — issue #110). A `rem` cap rather than a `%` of
|
||||||
|
// the cell: percentage heights against a `<td>` don't resolve
|
||||||
|
// consistently across engines. `flex: 1` still lets the list use the
|
||||||
|
// row's spare height up to that cap. `.add-recipe-btn` is a flex sibling
|
||||||
|
// (outside this box), so it stays pinned just below, always reachable.
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
max-height: 8.5rem;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipe-chip {
|
.recipe-chip {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue