Skip to content

feat(overlay): draggable annotation popover (#3) - #12

Merged
seanpk merged 2 commits into
masterfrom
feat/draggable-popover
Jun 16, 2026
Merged

seanpk merged 2 commits into
masterfrom
feat/draggable-popover

Conversation

@seanpk

@seanpk seanpk commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Closes #3.

Drag the comment/edit popover aside by its title bar (grip icon + label) so you can read the surrounding page while composing — complementing ANN-10 (composing isn't dismissed by page interaction).

Behaviour

  • Grab the title bar (visible ⋮⋮ grip for discovery; the whole header is the target) and drag anywhere.
  • Stays fixed on screen while you scroll the page (so you can read other context — it does not follow the element), clamped to the viewport.
  • Dragged position is preserved across re-renders (mode switch, adding a comment) and composing text is never lost; selecting a different element re-anchors it.

Implementation

  • popover.js: title bar is the .mk-drag handle; Pointer Events + setPointerCapture (touch-aware). preventDefault keeps a focused textarea from blurring + stops text selection; stopPropagation keeps the gesture clear of page selection. A draggedPos wins over placePopover(), resets on a new anchor, re-clamps on resize via the shared tracker.
  • geometry.js: new clampBox() keeps a chosen box fully in the viewport (degrades for oversize boxes).
  • styles.js: .mk-pop-head handle (grip + ellipsised label), touch-action:none, .mk-dragging.

Tests

  • Unit: clampBox (test/unit/geometry.test.js).
  • Browser: test/browser/drag.spec.js — move, compose→drag→text-preserved, persist-across-rerender, re-anchor-on-new-selection, viewport clamp.
  • New requirement ANN-11.

🤖 Generated with Claude Code

seanpk and others added 2 commits June 16, 2026 18:58
Let the reviewer drag the popover aside by its title bar to read the
surrounding page while composing — complements ANN-10 (composing is no
longer dismissed by page interaction).

- popover: the title bar (grip icon + label) is a drag handle; Pointer
  Events + setPointerCapture move the box. preventDefault keeps a focused
  textarea from blurring and stops text selection; stopPropagation keeps
  the gesture clear of page selection. The dragged position wins over
  auto-placement so it survives re-renders, and resets when a different
  element is selected. Re-clamps on resize via the shared tracker.
- geometry: new clampBox() keeps a chosen box fully in the viewport.
- styles: .mk-pop-head handle (grip + ellipsised label), touch-action
  none, .mk-dragging.

The popover stays fixed on screen while the page scrolls (so you can read
other context) rather than following the element.

Adds ANN-11; unit test for clampBox and a Playwright drag spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The clamp assertion referenced bare `innerWidth`/`innerHeight` inside a
page.evaluate callback — valid in the browser at runtime but flagged as
no-undef when eslint lints the spec in a Node context (CI lint failure).
Read the box in the browser and compare against page.viewportSize() in
Node instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@seanpk
seanpk merged commit cc8047e into master Jun 16, 2026
4 checks passed
@seanpk
seanpk deleted the feat/draggable-popover branch June 16, 2026 23:05
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.

Draggable annotation popover

1 participant