Skip to content

feat(browser): notes follow their element: reveal on open, clip to scrolling boxes, hover tween - #957

Merged
omartelo merged 2 commits into
mainfrom
feat/browser-notes-follow
Oct 28, 2026
Merged

omartelo merged 2 commits into
mainfrom
feat/browser-notes-follow

Conversation

@omartelo

@omartelo omartelo commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Three follow-ups to the notes on the page (#952).

1. A note opened from the tray or its pin scrolls its element into view

browser.Locate takes an optional Reveal selector (one options struct, contract golden updated). The page scrolls that element into view first, unless it already shows whole (inside the viewport and not cut by a scrolling box): centered, or block start when it is taller than the viewport; inline: 'nearest' so a wide page does not jump sideways. The scroll is behavior: 'instant', so the boxes the same call answers are where the element stops and the popover follows them through the existing relocate. On the window side, the tray row and the pin both go through openListed, which asks the next lookup to reveal and runs it right away; a reveal is queued unmerged so the plain lookups behind it cannot drop it.

2. Pins and outlines are cut to the scrolling boxes they sit in

visibleScript, shared by locateScript and elementScript, intersects the element's box with the client box of every ancestor whose overflow is not visible, stopping at a position: fixed ancestor and at body/html. Fully hidden answers the empty box, which the pane already does not draw.

Partially visible: clip, not empty. The part that shows is what the person sees and points at, so the ring and pin stay on it; returning empty would make a note vanish while half its element is still on screen, and keeping the full box is the bug this fixes (ring drawn over the neighbour). hidden and clip count as well as auto/scroll: they cut what the page draws the same way.

Known limits, written in docs/ceilings.md: an absolutely positioned element that escapes a non-positioned clipping ancestor is cut anyway, and an element a sibling covers keeps its pin.

3. The pick's outline slides between elements

While picking, the hover outline slides from the element it left to the one under the pointer in 160 ms, easeInOutQuad (noteHoverGlide). A move mid-slide starts the next one from where the outline stands; the probe answering the same element again does not restart it. The window redraws every frame only during the slide, since the dashes' march is paced at 20 frames a second. Chosen from a mockup over today's jump, a 100 ms slide and a 120 ms cross-fade.

Test plan

  • New live tests in internal/browser/notes_live_test.go, failing before the change: a row scrolled out of an overflow list answered {Y:160 H:40} (now empty), a half-visible row answered its full 40px (now the 20px that show), ElementAt boxes only the visible part, and Reveal brings a row into its list and a far button to the middle of the viewport, leaving it in place when already whole.
  • Native unit tests: a note opened from the tray asks for a reveal on the next lookup, right away, and the popover follows the box it answers; a note picked under the pointer asks for none.
  • Native unit test: the outline starts on the first element at once, leaves from the old one, stands half way at half time, lands on the new one, continues from mid-slide on a further move, and does not restart when the same element answers again.
  • Local gate: backend and native/ gofmt, vet and tests green.

Opening a note from the tray or its pin asks browser.Locate to scroll its
element into view first (Reveal), instant and centered, so the popover
opens beside it. Boxes from browser.Locate and browser.ElementAt are cut
to every ancestor that clips its overflow, up to a fixed one: a row a
scrolling list hides answers an empty box instead of a pin over its
neighbour.
While picking, the hover outline slides from the element it left to the
one under the pointer in 160 ms, ease-in-out, starting from where it
stands when the pointer moves mid-slide. The maintainer chose it from a
mockup over the jump, a 100 ms slide and a cross-fade.
@omartelo
omartelo merged commit 01aa01d into main Oct 28, 2026
7 checks passed
@omartelo
omartelo deleted the feat/browser-notes-follow branch October 28, 2026 13:30
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