Skip to content

fix(ui): the graph gets the 60% of the window it always asked for - #77

Merged
youhide merged 1 commit into
mainfrom
d1-graph-gets-its-space
Aug 21, 2026
Merged

fix(ui): the graph gets the 60% of the window it always asked for#77
youhide merged 1 commit into
mainfrom
d1-graph-gets-its-space

Conversation

@youhide

@youhide youhide commented Aug 21, 2026

Copy link
Copy Markdown
Owner

First item of the UI refinement plan, and a defect rather than a preference.

The claim that was not true

UI_SPEC.md's first principle is that the graph is the application — "the centre of the window and the most pixels" — and screen::repository has asked for that since M1 with FillPortion(6) against the detail pane's FillPortion(4).

Measured against the real layout pass: graph 145px, detail 581px in a 727px column. 20/80, not 60/40. The primary surface was a fifth of the window for five milestones.

Why, and why the first hypothesis was wrong

I guessed the root column! was Shrink. It was not — adding .height(Fill) there changed nothing, and measurement showed the content area already filled the window at y=41 h=727.

The real cause is an asymmetry between the two panes:

  • ring() wraps its child in a container to draw the focus border. A container with no height is Shrink in iced, and a FillPortion inside a Shrink never reaches the column meant to divide the space.
  • The graph's portion sat inside its ring. The detail's sat on a container outside its own.
  • So the detail was the only child the column could see asking for a share, and it took everything the shrunk graph did not use.

Moving the graph's portion outside its ring gives 436/291 — exactly the 6:4 the code always requested.

How it is pinned

No text assertion could have caught this, which is why nothing did: the graph is a canvas and carries no text. The test measures the pane below it instead — Target::Text carries its Rectangle and Bounded::bounds is public, so the detail's centred placeholder is found and its midpoint checked against the viewport.

Sabotage: putting the portion back inside the ring fails with the detail pane's midpoint is 477.44 of 768, so it is taking the space the graph asked for.

A technique worth reusing

Simulator::find stops at the first match, but a closure selector that always returns None while pushing into a shared vector visits the whole tree and yields every container rectangle. That is how 145/581 was measured. It is the general tool for asserting layout in this crate, and it should pin the resizable-split work later in the plan.

Screenshots

All four retaken — this changes what every one of them shows. The graph goes from seven visible rows to nineteen.

graph.png The difference is the whole point: compare against the version in main
staging.png Now showing this very change in the working directory
light-theme.png Taken by writing hidegit-light into a throwaway config.toml rather than driving the UI
command-palette.png

Taken the way docs/screenshots/README.md documents: throwaway HOME, HIDEGIT_NO_KEYCHAIN=1, captured by window id.

Docs

UI_SPEC.md principle 1 now states the ratio concretely — six parts graph to four parts detail — and records that it is asserted rather than merely asked for, with a note on why it went unnoticed for five milestones.

Gate

cargo fmt --all -- --check, cargo clippy --workspace --all-targets --all-features --locked -- -D warnings, cargo test --workspace --all-features --locked — 890 tests, all green.

`UI_SPEC`'s first principle is that the graph is the application — "centre of
the window and the most pixels" — and `screen::repository` has asked for that
since M1 with `FillPortion(6)` against the detail pane's `FillPortion(4)`.

It never got it. Measured against the real layout pass, the graph was 145px and
the detail 581px in a 727px column: 20/80, not 60/40.

The cause is an asymmetry between the two panes. `ring` wraps its child in a
container to draw the focus border, and a container with no height is `Shrink`
in iced, so a `FillPortion` inside one never reaches the column that is meant to
divide the space. The graph's portion sat inside its ring; the detail's sat on a
container outside its own. That left the detail as the only child the column
could see asking for a share, so it took everything the shrunk graph did not
use. Moving the graph's portion outside its ring gives 436/291 — the ratio the
code has been requesting all along.

Pinned by a layout assertion rather than a text one, because no text assertion
could ever have caught this: the graph is a canvas and carries no text, so the
test measures the pane *below* it. `Target::Text` carries its `Rectangle` and
`Bounded::bounds` is public, so the detail's centred placeholder can be found
and its midpoint checked against the viewport. Sabotage puts the portion back
inside the ring and the test reports `midpoint is 477.44 of 768`.

Worth recording for the rest of this work: `Simulator::find` stops at the first
match, but a closure selector that always returns `None` while pushing into a
shared vector visits the whole tree and yields every container rectangle. That
is how the 145/581 above was measured, and it is the general tool for asserting
layout in this crate.

The four committed screenshots are retaken, since this changes what all of them
show — the graph goes from seven visible rows to nineteen.
@youhide
youhide force-pushed the d1-graph-gets-its-space branch from 5beb143 to f093ea6 Compare August 21, 2026 01:04
@youhide
youhide merged commit a6ad053 into main Aug 21, 2026
7 checks passed
@youhide
youhide deleted the d1-graph-gets-its-space branch August 21, 2026 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant