Skip to content

The measure, in characters this time, and a divider that moves (0.23.0) - #1281

Merged
feder-cr merged 1 commit into
mainfrom
feat/the-measure
Sep 8, 2026
Merged

The measure, in characters this time, and a divider that moves (0.23.0)#1281
feder-cr merged 1 commit into
mainfrom
feat/the-measure

Conversation

@feder-cr

@feder-cr feder-cr commented Sep 8, 2026

Copy link
Copy Markdown
Owner

ch is not a character. It is the advance width of the digit zero, which in a proportional font is much wider than an average letter, so a cap written in ch reads like a character count and is not one. Measured on this font with a canvas, on real prose in both languages this interface serves: 0 is 7.55px at 14px system-ui, the average character of a sentence is 6.11px. One ch is 1.24 characters.

That number has now been wrong twice, the same way both times. The cap started at 72ch believing it was 72 characters; minus the indent an answer carries it was 83. It was then widened to 84ch to make up for that indent, in ch again, and became 98 - past 65-72 (chat design guidance), 75 (Baymard's upper bound) and 80 (WCAG 2.1 AAA, SC 1.4.8). 66ch is 75 characters, read off the running page. The conversion is now a test that reads the page rather than a comment beside it.

Three more had been written down in this project's own layout and typography research and never applied:

  • the text sizes were absolute, so a default font size somebody set in their browser to read more comfortably did nothing here. In rem now: identical at the default 16px root, different for anybody who changed it;
  • 1.6 leading on the prose blocks, which is what the guidance for long-form answers asks and what this pane is for. The rest of the app keeps 1.55;
  • the left pane's width is derived from its own reading measure instead of a raw percentage, so the surplus goes to the picture, which improves with every pixel, rather than to a column that stops improving at its cap.

And the strongest recommendation was that the ratio is not this file's to choose: reading a long answer wants one, watching a form get filled wants another. The divider is a real separator now - dragged, moved with the arrow keys, double-clicked back to the default, remembered per browser, and clamped against the window on both sides so neither pane can be dragged away.

Found by clicking it, which nothing in the suite does: preventDefault on pointerdown stops a drag from selecting the text beside it, and it also stops the browser from focusing what was pressed. The divider dragged fine and then the arrow keys did nothing.

Gates

The splitter's clamp is EXECUTED under node against a small DOM, the way the markdown renderer is, because the failure it prevents is invisible to a string scan: a width dragged wide on a big monitor and remembered would strand the browser pane to nothing on a laptop, and the page would still parse, still draw, still drag.

Five known-bads, all killed: no floor, no ceiling, a ceiling computed from a constant instead of the window, a restore that writes itself back, and the missing focus call.

478 tests green.

⛔ `ch` IS NOT A CHARACTER. It is the advance width of the digit zero, which in
a proportional font is much wider than an average letter, so a cap written in
`ch` reads like a character count and is not one. Measured on this font with a
canvas, on real prose in both languages this interface serves: `0` is 7.55px at
14px system-ui, the average character of a sentence is 6.11px. One ch is 1.24
characters.

That number has now been wrong twice, the same way both times. The cap started
at 72ch believing it was 72 characters; minus the indent an answer carries it
was 83. It was then widened to 84ch to make up for that indent, in `ch` again,
and became 98 - past 65-72 (chat design guidance), 75 (Baymard's upper bound)
and 80 (WCAG 2.1 AAA). 66ch is 75 characters, read off the running page. The
conversion is now a test that reads the page rather than a comment beside it.

Three more come from this project's own layout and typography research, which
had them written down and never applied:

* the text sizes were absolute, so a default font size somebody set in their
  browser to read more comfortably did nothing here. In rem now, identical at
  the default 16px root and different for anybody who changed it;
* 1.6 leading on the prose blocks, which is what the guidance for long-form
  answers asks and what this pane is for. The rest of the app keeps 1.55;
* the left pane's width is derived from its own reading measure instead of a
  raw percentage, so the surplus goes to the picture, which improves with every
  pixel, rather than to a column that stops improving at its cap.

And the strongest recommendation was that the ratio is not this file's to
choose: reading a long answer wants one, watching a form get filled wants
another. So the divider is a real separator now - dragged, moved with the arrow
keys, double-clicked back to the default, remembered per browser, clamped
against the window on both sides so neither pane can be dragged away.

Found by clicking it, which nothing in this suite does: preventDefault on
pointerdown stops a drag from selecting the text beside it, and it also stops
the browser from focusing what was pressed. The divider dragged fine and then
the arrow keys did nothing.

Five known-bads on the new gates, all killed: no floor, no ceiling, a ceiling
that ignores the window, a restore that writes itself back, and the missing
focus call.
@feder-cr
feder-cr merged commit 32dfa2b into main Sep 8, 2026
22 of 23 checks passed
@feder-cr
feder-cr deleted the feat/the-measure branch September 8, 2026 20:27
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