Block selection tint covers exactly its block (#397) #576

Closed
kayg wants to merge 0 commits from issue/397-tint-geometry into dev
Owner

Fixes the block-selection tint being drawn in the wrong place (#397), on the phone (swipe) and on the desktop (Esc, Vim V).

Root cause

The tints were laid out from CodeMirror's height map, which does not include the margin of a block widget: the tag chips row under a title and a day's date heading both have margin-bottom: 14px. Everything below them is drawn lower than the map says, so the tint sat that much too high: over the end of the previous block, short of the bottom of the selected one. Notes with no tags and no day heading (all the earlier checks) agreed with the map.

Fix

  • packages/editor/src/blocks/box.ts: one blockBox that measures the block's own .cm-line elements as drawn (wrapped rows, chips and tags are inside the line), plus the approved insets: 8 px sideways, a 2 px gap to neighbours, a heading's padding not covered.
  • picked.ts (tint, circles), follow.ts (pull tint) and selected.ts (desktop tint) all use it. The map is no longer used for drawing.
  • watchLayout measures again on resize, font load, wrapping changes and the picked slide, via a resize observer that only exists while a tint shows. Nothing is read per animation frame.

Tests

apps/web/e2e/tint.spec.ts, on plain notes, notes with tags and day notes, with a long wrapped log line (time range, link chips, tag), a heading with an emoji, a nested item, a to-do, an item with a soft continuation line and plain paragraphs. It asserts that the tint holds every client rect of the block's text (1 px), reaches 8 px sideways, is not far taller than the block, does not touch neighbours' text, and keeps a gap between adjacent selections. Phone: swipe (390). Desktop: Esc, Vim V, V + j (1440). Light and dark (?theme=). It fails on dev for the tagged and day notes.

Run: chromium-390, webkit-390, chromium-1440, webkit-1440: tint, touch-select, vim, editor, bar-focus/rest/stable/stays/taps specs: 222 passed, 0 failed (178 skipped by width). Editor unit tests 186 passed, tsc and svelte-check 0 errors. iPhone simulator: checked with real wrapped log lines in a day note (shots on #397).

Esc on desktop selects only the caret's line (not the whole list item with its continuation line); that is unchanged here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01U5oTUycqAh7DT72mdSUztk

Fixes the block-selection tint being drawn in the wrong place (#397), on the phone (swipe) and on the desktop (Esc, Vim `V`). ## Root cause The tints were laid out from CodeMirror's height map, which does not include the margin of a block widget: the tag chips row under a title and a day's date heading both have `margin-bottom: 14px`. Everything below them is drawn lower than the map says, so the tint sat that much too high: over the end of the previous block, short of the bottom of the selected one. Notes with no tags and no day heading (all the earlier checks) agreed with the map. ## Fix - `packages/editor/src/blocks/box.ts`: one `blockBox` that measures the block's own `.cm-line` elements as drawn (wrapped rows, chips and tags are inside the line), plus the approved insets: 8 px sideways, a 2 px gap to neighbours, a heading's padding not covered. - `picked.ts` (tint, circles), `follow.ts` (pull tint) and `selected.ts` (desktop tint) all use it. The map is no longer used for drawing. - `watchLayout` measures again on resize, font load, wrapping changes and the picked slide, via a resize observer that only exists while a tint shows. Nothing is read per animation frame. ## Tests `apps/web/e2e/tint.spec.ts`, on plain notes, notes with tags and day notes, with a long wrapped log line (time range, link chips, tag), a heading with an emoji, a nested item, a to-do, an item with a soft continuation line and plain paragraphs. It asserts that the tint holds every client rect of the block's text (1 px), reaches 8 px sideways, is not far taller than the block, does not touch neighbours' text, and keeps a gap between adjacent selections. Phone: swipe (390). Desktop: Esc, Vim `V`, `V` + `j` (1440). Light and dark (`?theme=`). It fails on dev for the tagged and day notes. Run: chromium-390, webkit-390, chromium-1440, webkit-1440: tint, touch-select, vim, editor, bar-focus/rest/stable/stays/taps specs: 222 passed, 0 failed (178 skipped by width). Editor unit tests 186 passed, `tsc` and `svelte-check` 0 errors. iPhone simulator: checked with real wrapped log lines in a day note (shots on #397). Esc on desktop selects only the caret's line (not the whole list item with its continuation line); that is unchanged here. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01U5oTUycqAh7DT72mdSUztk
Block selection tint covers exactly its block (#397)
Some checks failed
CI / web (pull_request) Failing after 9s
CI / server (pull_request) Successful in 20s
CI / rust (pull_request) Successful in 1m48s
76e5912e4c
The tint was laid out from CodeMirror's height map, which does not know a block
widget's margin (the tag chips row under a title, a day's date heading). Everything
below such a widget sat lower on screen than the map said, so the tint landed above
its block. One function (blocks/box.ts) now measures the block's own lines as drawn,
for the phone's picked look and the desktop's Esc / Vim V look, and measures again
when the page lays out differently (resize, fonts, wrapping, the picked slide).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U5oTUycqAh7DT72mdSUztk
Author
Owner

Landed in train AB, #580.

Train AB ran the full suite: fmt, clippy, workspace tests (502 passed, 0 failed), the build, svelte-check, and every Playwright project in parallel shards.

  • First run discarded: the Rust steps hadn't compiled (a broken shared environment file), so e2e had used an old binary. The train script now stops at the first failing Rust step.
  • Rerun: every shard passed except two tests that failed under load:
    • swipe-rows:116 passed 60 of 60 repeated alone;
    • missing-links:155 (page closed) passed 54 of 54.
  • webkit-390 shard 3/3: it collided on a port, was rerun alone, and passed 94 of 94.

Contents:

  • #576: the block-selection tint covers exactly its block;
  • #578: the phone layout never scrolls sideways;
  • #575: swipe rows;
  • #573: narrow handle and link pill padding;
  • #574: saves no longer copy the whole note, with the independent review's crash tests.
Landed in train AB, #580. Train AB ran the full suite: fmt, clippy, workspace tests (502 passed, 0 failed), the build, svelte-check, and every Playwright project in parallel shards. - **First run discarded:** the Rust steps hadn't compiled (a broken shared environment file), so e2e had used an old binary. The train script now stops at the first failing Rust step. - **Rerun:** every shard passed except two tests that failed under load: - `swipe-rows:116` passed 60 of 60 repeated alone; - `missing-links:155` (page closed) passed 54 of 54. - **webkit-390 shard 3/3:** it collided on a port, was rerun alone, and passed 94 of 94. Contents: - #576: the block-selection tint covers exactly its block; - #578: the phone layout never scrolls sideways; - #575: swipe rows; - #573: narrow handle and link pill padding; - #574: saves no longer copy the whole note, with the independent review's crash tests.
kayg closed this pull request 2026-10-18 12:07:44 +00:00
Some checks failed
CI / web (pull_request) Failing after 9s
CI / server (pull_request) Successful in 20s
CI / rust (pull_request) Successful in 1m48s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!576
No description provided.