Skip to content

Make the chrome fit every window, and every colour - #30

Merged
joshlin2201 merged 2 commits into
mainfrom
chrome-that-fits-every-window
Aug 27, 2026
Merged

Make the chrome fit every window, and every colour#30
joshlin2201 merged 2 commits into
mainfrom
chrome-that-fits-every-window

Conversation

@joshlin2201

Copy link
Copy Markdown
Owner

Four reports from driving the app, and each one turned out to be something the code already claimed to do.

Tooltips cut their own text in half. The chip measured itself for one line and drew three, then clipped the rest with its own rounded rectangle. The bug hid itself: every size assertion in TooltipRenderTests bounded the chip from above, so each line that went missing made the checks pass more comfortably. What replaced them is a check that a longer sentence makes a taller chip. There were also two tooltip layers with two rules, and the rail's was not really a rule — it offset the chip by a constant, so hovering the ninth tool put the answer beside the first.

The header ran off the right edge. The window can be dragged to 560pt; the row needed 647pt with no filename in it. Share, Duplicate, the Guide and the zoom were outside the window with nothing to say they were there — two numbers that had never been compared. HeaderFit steps down a ladder, and every rung drops a run whose commands have another door, which inverts the obvious answer: cut/copy/paste go before the drag-out handle, because they have three chords every Mac already knows and it has none.

The rail hid its colour block. The whole rail sat in one scroller with its indicators off — in a file that has claimed since it was written that the loaded colours must never be cut. That was a comment, not a behaviour. The bottom bar had no shedding at all and ran 878pt of bar into a 548pt window.

Six controls were still a stock AppKit slider, in a panel whose every other control is drawn by hand. Two live bugs came out with them: the accessibility step was the entire range on any 0-to-1 fraction, so Ink, Opacity and Strength had two reachable values each; and t skipped its clamp on the linear path, so an out-of-range value painted past the end of its own trough.

A transparent colour did nothing in twelve of thirteen tools — including the eraser, which paints Colour 2, so the most obvious route to transparency was the one that was dead. Five compositors take a destination-out branch now, not the two it first looked like. The colour popover is gone with it: the system Colors panel is better at every part of that job, and what replaces the keystroke is a visible More colours button in the run the swap button used to hold alone, so the rail is not a point thicker.

Checking

  • Clean release build: 345 engine tests (with the performance budgets) and 168 app tests.
  • Both new geometry suites render the real views and measure the picture rather than re-summing the tokens, which is docs/CHECKS_THAT_MISS.md §1 — and this file's own previous height check had exactly that shape.
  • Every new check was watched failing against the old behaviour before it was trusted to pass.

CI is the judge on the actor-isolation changes: this was written on a beta Xcode, and a green local build is not evidence there.

Josh Lin added 2 commits August 27, 2026 01:53
The app has carried alpha end to end since the first build: the picker offers it,
the file format keeps it, and the bucket has always meant "knock a hole in this".
Every other tool disagreed, and disagreed silently. Source-over compositing with a
fully transparent source is arithmetically out = dst, so the pencil, the brush,
the shapes, the text and the eraser did precisely nothing and said nothing about
it.

The eraser is the one that mattered. It paints Colour 2, and a transparent
Colour 2 is exactly what somebody loads when they want a hole, so the app's most
obvious route to transparency was the one route that was dead.

Five compositors take a destination-out branch now, not the two it first looked
like: the brush stamp, the antialiased stroke that the shipping default round
brush actually uses, the shape fill, the airbrush, and the text — which needs a
blend mode, because Core Graphics cannot say "erase" with a colour. Scaling a
premultiplied destination by the inverse of the brush's coverage IS
destination-out, so a soft brush erases softly for nothing.

The first version of the test pressed and released on one pixel, which only
reaches beginStroke's direct stamp. It passed with the whole antialiased path
still dead — a transparent colour rubbed out one dot under the press and then did
nothing for the rest of the drag, which is worse than doing nothing at all
because the first dot proves the feature works. It drags now, across three tools,
and it was watched failing before it was trusted to pass.
Four reports, and each one turned out to be a thing the code claimed to do
already.

Tooltips cut their own text in half. The chip measured itself for one line and
drew three, then clipped the rest away with its own rounded rectangle — because
.fixedSize proposes a nil width, and under a nil proposal .frame(maxWidth:) let
the text report the height of one unbroken line. The bug hid itself: every size
assertion in TooltipRenderTests bounded the chip from above, so each line that
went missing made the checks pass more comfortably. What replaced them is a check
that a longer sentence makes a taller chip.

There were also two tooltip layers with two rules, and the rail's was not really
a rule — it offset the chip by a constant, so hovering the ninth tool put the
answer up beside the first. One layer now, one rule: the chip's near edge sits on
a fixed line beside the chrome it explains and slides along that line to follow
the control.

The header ran off the right edge. The window can be dragged to 560pt and the row
needed 647pt to draw itself with no filename in it, so Share, Duplicate, the
Guide and the zoom were outside the window with nothing to say they were there.
Two numbers that had never been compared. HeaderFit steps down a ladder, and
every rung drops a run whose commands have another door — which inverts the
obvious answer, because cut/copy/paste have three chords every Mac already has
and the drag-out handle has none. The filename also had a layout priority but no
ceiling, and the centred cluster is not in its stack, so a long name was handed
the whole row and drawn over the zoom controls.

The rail hid its colour block. The whole rail sat in one scroller with its
indicators off, so the loaded pair and the edge toggle went below the fold — in a
file that has claimed since it was written that the colours are the part that must
never be cut. That was a comment, not a behaviour. RailFit sheds palette columns
first and then scrolls only the tool run, cut at a real cell boundary rather than
an average pitch, which is right only until the fold crosses a group rule. The
bottom bar had no shedding at all and ran 878pt of bar into a 548pt window.

Six controls in the options panel were still a stock AppKit slider, in a panel
whose every other control was drawn by hand — the giveaway Mark's own doc comment
complains about. They are marks now, each naming itself on its caption line, and
OptionSlider is gone. Two live bugs came with it: the accessibility step was
max(range/100, 1), which is the entire range on any 0-to-1 fraction, so Ink,
Opacity and Strength had two reachable values each; and t skipped its clamp on
the linear path, so an out-of-range value painted past the end of its own trough.

The colour popover is gone. It was a weaker copy of the system Colors panel,
which has an opacity slider, an eyedropper, saved swatches and a recents row that
survives quitting. What replaces it is visible chrome rather than a keystroke: a
More colours button in the run the swap button used to hold alone, so the rail is
not a point thicker and the palette does not lose a column to it. Chips draw the
canvas's own checkerboard when their colour is not solid, and only then, because
a texture that is always there is a texture people stop seeing.

Geometry is asked of the shipping arithmetic now rather than of a copy of it, and
the two new geometry suites render the real views and measure the picture. Both
were watched failing against the old behaviour first.
@joshlin2201
joshlin2201 merged commit 236c6f2 into main Aug 27, 2026
3 checks passed
@joshlin2201 joshlin2201 mentioned this pull request Aug 27, 2026
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