Repository navigation
Give the bottom panels one row, and let the rail be stowed - #41
Merged
Merged
Conversation
The last two items of the layout work, and both are about width and height the workspace was spending on things nobody had asked to see. Enum types, Functions and Drafts each collapsed themselves, so all three shut cost the workspace three rows below the pane row the rest of this work spent its time giving a definite height to. Measured in the built app at the default 1280x840 window, a shut panel is 34px of that. They now share one row that names whichever of them this database has something for, and the row is 23px whether it holds one name or two. Opening one gives it the workspace and collapses the pane row - the same switch the Data tab makes rather than a division of the row, and the control that shuts it stays on screen below. The pane row goes out of the flow entirely, floor and all: hidden while keeping its 460px the body comes out at 7px of visible area, a scroll box with nothing in view, which the workspace absorbs by squeezing rather than by spilling. That is the shape of defect the rail's own floor comment was written about, and it is what the height assertion in the e2e is for - `toBeVisible()` and a page-overflow check both accept 7px. Releasing that floor is also what left the open body with nothing under it, which the review of this commit found and this commit now fixes: a scroll container in a squeezed flex column has no floor of its own, and measured at a 1280x460 window with Settings open the body was 0px of visible height against 34px of content, with the page not overflowing either - so no scroll anywhere reached the list. It has 8rem now, and past that the page scrolls, which the pane row and the rail already document as the accepted degradation. Whether a panel is open is decided the way the Data tab's width is, in `lib/expansion` and for the same reason: an open panel has collapsed the only other thing in the workspace, so a panel whose content went away underneath it - the drafts cleared, another profile inspected - would leave an empty box and no button to shut it. A panel the row cannot offer is not shown, and the row only offers what it has something to put in. That rule was not enough on its own. A panel every database can offer survives a change of database, so a search hit in another one landed on whatever was open - measured, the detail pane came back at 0px with an enum list on screen, in a database the operator had not been looking at. Naming a relation and changing database now both shut it: the first is a request for the pane the panel collapsed, and the second is a different workspace. Drafting a statement opens the drafts panel. Emitting asks for the surface that holds what was emitted, the same way opening Data asks for the width; a statement generated into a row the operator has to think to click is one they have no reason to believe exists. The rail stows from the header. It says nothing but which databases exist, and the selected one is named in the bar above the workspace, so between switches it is 13rem spent on a list nobody is reading. Manual only - what was asked for is a menu that stows, not a width that guesses; folding at a narrow window is a separate question and stays where it was. The width it gives up goes to the map, and that needed no new arithmetic: the detail column is stated against the viewport, so it does not move, and the map has the row's `1fr`. Measured at 1280px: the map goes from 529px to 751px and the detail column is unchanged. The e2e asserts those widths rather than the rail's absence, because "the rail is gone" would pass while the width went nowhere. The button stays in the header while stowed because a control that hides something cannot sit inside what it hides - the rail is not the only way to change database, the search jumps across them and a card selects one, but it is the only place they are all listed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
takashi-matsuyama
force-pushed
the
feat/workspace-bottom-row-and-rail-fold
branch
from
August 10, 2026 15:53
8b0ca67 to
541da51
Compare
takashi-matsuyama
added a commit
that referenced
this pull request
Aug 10, 2026
The bottom-panel height guard from #41 went red on main's `macos-e2e`, which is the only job that runs it: the runner's screen is shorter than the 840px window this app asks for, so the pane row was pinned to its 460px floor and the open body came out at 309px against the 456 the guard demanded. The product did what it is documented to do. The floor's own comment says the row keeps 460px when the window cannot pay for it, the content then overflows and the page scrolls, and that is the accepted degradation rather than a failure; the body's floor comment says the body gets 8rem and scrolls past that, for the same reason. The guard asserted `body >= paneHeight - 4` unconditionally, so it went red in a state the design allows - which is the rule stated 100 lines above it in this same file, about the map pane, and the new guard had broken it. What the body actually gets is the pane row's height less the part of it the window never had. Measured at seven window heights (812, 772, 740, 712, 672, 612 and 532px of viewport), `paneHeight - unpaid` is not an approximation of the body but exactly it: 0px of slack at every one, while `paneHeight - 4` holds at 812 and nowhere below. `unpaid` is `.workspace`'s own overflow, `scrollHeight - clientHeight`, read while the row is still shut - both because it is the shut state's shortfall that the open body does not inherit, and because a break in the open state then cannot inflate the allowance to let itself pass. Driving this test at a 676px window reproduces the runner exactly, body and all: 309px. Broken four ways from there: the floor left in place at the default window (469 wanted, 128 given, the body falling to its own 8rem), the floor left in place at 676 (305 wanted, 128), the old form at 676 (456 wanted, 309 - the CI failure, locally), and the fixed form at 676, which passes. So the guard still fails for the defect it exists for, in both regimes, and no longer fails for the window. One measurement in the comment above it was also stale: `7px of 477` was taken before the body had a floor of its own, and the same break lands on that floor now. Both numbers are named. Test-only. No product code changed. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The last two items of the layout work (
decision_01KZ8JJTWW), both about width and height the workspace was spending on things nobody had asked to see. Sits on top of #38.One row for the bottom panels
Enum types, Functions and Drafts each collapsed themselves, so all three shut cost three rows below the pane row the rest of this work spent its time giving a definite height to — measured in the built app at 1280x840, a shut panel is 34px of that. They now share one row that names whichever of them this database has something for, and the row is 23px whether it holds one name or two.
Opening one gives it the workspace and collapses the pane row — the same switch the Data tab makes rather than a division of the row — and the control that shuts it stays on screen below. The pane row goes out of the flow entirely, floor and all: hidden while keeping its 460px, the body comes out at 7px of visible area, a scroll box with nothing in view, which the workspace absorbs by squeezing rather than spilling. That is the shape of defect the rail's own floor comment was written about, and it is what the height assertion in the e2e is for —
toBeVisible()and a page-overflow check both accept 7px.Releasing that floor is also what left the open body with nothing under it, found by the review of this commit and fixed in it: a scroll container in a squeezed flex column has no floor of its own, and measured at 1280x460 with Settings open the body was 0px of visible height against 34px of content, with the page not overflowing either — so no scroll anywhere reached the list. It has
8remnow, and past that the page scrolls, which the pane row and the rail already document as the accepted degradation.Whether a panel is open is decided in
lib/expansion, the way the Data tab's width is, and for the same reason: an open panel has collapsed the only other thing in the workspace, so a panel whose content went away underneath it (drafts cleared, another profile inspected) would leave an empty box and no button to shut it. A panel the row cannot offer is not shown, and the row only offers what it has something to put in.That rule was not enough alone. A panel every database can offer survives a change of database, so a search hit in another one landed on whatever was open — measured, the detail pane came back at 0px with an enum list on screen, in a database the operator had not been looking at. Naming a relation and changing database both shut it: the first is a request for the pane the panel collapsed, the second is a different workspace. Drafting a statement opens the drafts panel — emitting asks for the surface that holds what was emitted, the same way opening Data asks for the width.
The rail stows
From the header. The rail says nothing but which databases exist, and the selected one is named in the bar above the workspace, so between switches it is 13rem spent on a list nobody is reading. Manual only — what was asked for is a menu that stows, not a width that guesses; folding at a narrow window is a separate question and stays where it was.
The width goes to the map with no new arithmetic. Measured at 1280px: the map goes 529px → 751px, detail column unchanged. The e2e asserts those widths rather than the rail's absence, because "the rail is gone" would pass while the width went nowhere. The button stays in the header while stowed because a control that hides something cannot sit inside what it hides — the rail is not the only way to change database (search jumps across them, a card selects one), but it is the only place they are all listed.
Local:
typecheck/lint/test:unit(341) /test:e2e(9) green afterpnpm build.Deferred, not fixed — including one falsehood
--detail-wis amin(): measured, +6px at 620px and +20px at 560px. The README is not wrong, because it states the window width it measured at. Left in the message rather than amended; say the word and I will amend it.aria-expandedapplies, and therail-togglein the same commit uses it correctly — so this is a self-inconsistency, and the cheapest of these to fix.EnumsPanelbranch leaves it green.showAi.Design-challenge candidates raised by review and blocked (operator's call)
Reported rather than applied — all four reverse a settled choice:
bottomOpenper-profile.railFolded.Closes
Merging this completes
decision_01KZ8JJTWW(layout overhaul). Card slimming was dropped separately underdecision_01KZNH04MC.