diff options
| author | Adam Malczewski <[email protected]> | 2026-09-05 17:49:57 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-09-05 17:49:57 +0900 |
| commit | e3d5f3df3577f91b933d7ad51a339dbb05ba53dd (patch) | |
| tree | 53f8583b7a2e245944ef8d21c8bd6174c3a88663 /src/features | |
| parent | 254f90a4081a3f15dfe54277da922579dbaee254 (diff) | |
| download | dispatch-web-e3d5f3df3577f91b933d7ad51a339dbb05ba53dd.tar.gz dispatch-web-e3d5f3df3577f91b933d7ad51a339dbb05ba53dd.zip | |
fix(layout): keep chat transcript region full-height when empty (composer pinned to bottom)
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/layout/ui/TileRoot.test.ts | 13 | ||||
| -rw-r--r-- | src/features/layout/ui/TileStack.svelte | 8 |
2 files changed, 20 insertions, 1 deletions
diff --git a/src/features/layout/ui/TileRoot.test.ts b/src/features/layout/ui/TileRoot.test.ts index 27b8e0a..aba22a9 100644 --- a/src/features/layout/ui/TileRoot.test.ts +++ b/src/features/layout/ui/TileRoot.test.ts @@ -193,6 +193,19 @@ describe("TileRoot", () => { expect(natural?.getAttribute("style")).toContain("flex: 0 0 auto"); }); + it("the stack column is full-height so a grow child fills it even when empty", () => { + // jsdom can't compute flex layout — the honest seam is the CSS class. + // WITHOUT `h-full` the stack column's height is content-based, so the + // grow child's `flex: 1 1 0%` has no space to fill: an EMPTY chat leaf + // collapses to ~0 and the composer below it rides to the top (instead of + // staying pinned at the bottom of the column). + const { container } = render(TileRoot, { + props: { tree: defaultTestTree(), collapse: createCollapseStore() }, + }); + const stackColumn = container.querySelector("[data-testid='fixture-a']")?.closest(".flex-col"); + expect(stackColumn).toHaveClass("h-full"); + }); + it("the dropdown lists panel-eligible views only (decision 5)", () => { render(TileRoot, { props: { tree: panelsOnlyTree("fix-b"), collapse: createCollapseStore() } }); const select = screen.getByRole("combobox", { name: "Select a view" }); diff --git a/src/features/layout/ui/TileStack.svelte b/src/features/layout/ui/TileStack.svelte index 13dab09..ac7091a 100644 --- a/src/features/layout/ui/TileStack.svelte +++ b/src/features/layout/ui/TileStack.svelte @@ -3,6 +3,12 @@ * A plain vertical container (today's left column). `grow` children flex * (`flex: grow 1 0%` — the chat region scrolls internally, exactly like * today's `flex-1`); children without grow take natural height. + * + * `h-full` keeps the container's main size DEFINITE (the parent is the + * split-child wrapper, cross-stretched to the full-height split row). With + * an indefinite height, `flex: 1 1 0%` degenerates to content sizing — an + * EMPTY grow child collapses to ~0 and the siblings below it (composer) + * ride to the top instead of staying pinned at the bottom. */ import type { LayoutOp, Path, StackNode } from "@dispatch/layout-contract"; import type { CollapseStore } from "../logic/collapse"; @@ -23,7 +29,7 @@ } = $props(); </script> -<div class="flex min-h-0 min-w-0 flex-col overflow-hidden"> +<div class="flex h-full min-h-0 min-w-0 flex-col overflow-hidden"> {#each node.children as child, i (i)} <div class="min-h-0 min-w-0" style={"flex: " + (child.grow ?? 0) + (child.grow === undefined ? " 0 auto" : " 1 0%")}> <TileNode node={child.node} path={[...path, i]} {ports} {collapse} {onEdit} /> |
