Scroll-sync the review preview with the source editor #32

Open
opened 2026-06-12 08:09:12 +00:00 by benstull · 0 comments
Owner

Scroll-sync the review preview with the source editor

Summary

Keep the F10 review preview and the source markdown editor scroll-synchronized,
so scrolling one moves the other to the corresponding position.

Problem / pain

The review preview opens beside the source editor (ViewColumn.Beside), but the
two panes scroll independently. On a long document the reviewer scrolls the preview
to a change, then has to manually hunt for the same place in the editor to act on
it (or vice-versa). VS Code's built-in markdown preview scroll-syncs by default, so
the absence here reads as a regression from the familiar behavior.

Who feels it

The human coauthor (PP-1) reviewing/editing a long markdown document — the
longer the doc, the more the lost sync costs.

Desired outcome / value

Scrolling the editor moves the preview to the matching content, and scrolling the
preview moves the editor — the two stay aligned so the reviewer never loses their
place crossing between "review on the right" and "write on the left."

Acceptance — "done right"

  • Scrolling the source editor scrolls the preview to the corresponding rendered
    content (block-level alignment is sufficient — exact pixel parity is not
    required).
  • Scrolling the preview scrolls the editor to the corresponding source line.
  • Sync does not fight the user (no oscillation/feedback loop between the two
    scroll events).
  • The webview stays sealed (INV-21): sync is driven by postMessage between host
    and webview; no new network or document-mutation surface.

Scope / non-goals

In scope: bidirectional scroll-sync between the F10 preview webview and its
source editor.

Non-goals: cursor/selection sync; editing in the preview; any change to the
render engine or the accept/reject path.

Assumptions · constraints · dependencies

  • Builds on F10 (#29, shipped). Requires a source-line↔rendered-block mapping; the
    preview already splits the document into blocks with source ranges
    (splitBlocksWithRanges), which can seed the mapping.
  • Constraint: the webview is sealed — scroll position is exchanged via host↔webview
    postMessage, debounced to avoid loops.

Source / signal

Self-originated — capture session vscode-cowriting-plugin-0031 (2026-06-12),
from the F10 spec's open-questions list. Spec:
specs/coauthoring-interactive-review.md §1.7 (out of scope for F10) / §9
("OPEN → later: preview→source scroll-sync"). Builds on F10 #29.

Priority (WSJF)

Provisional: Value low–medium (a quality-of-life parity feature) ·
Time-criticality low · Opportunity low ÷ Size small–medium
provisional priority/P3. (Decision aid, not auto-scored.)

Decomposition

Single increment (Feature, small–medium). Slice checklist:

  • Source-line ↔ rendered-block mapping exposed to the webview.
  • Editor scroll → preview scroll (host listens to onDidChangeTextEditorVisibleRanges, posts target block).
  • Preview scroll → editor scroll (webview posts visible block, host reveals the source range).
  • Debounce/guard to prevent feedback oscillation.
  • Manual smoke on a long doc (E2E can't assert webview scroll).

Solution notes (optional — NOT a design)

Non-binding: VS Code's built-in markdown preview is the reference behavior; the
block-range data F10 already computes is the natural anchor for the mapping. A
Solution Design should precede implementation if the mapping proves non-trivial.

<!-- Set the type/* label: type/feature --> # Scroll-sync the review preview with the source editor ## Summary Keep the F10 review preview and the source markdown editor **scroll-synchronized**, so scrolling one moves the other to the corresponding position. ## Problem / pain The review preview opens beside the source editor (`ViewColumn.Beside`), but the two panes scroll independently. On a long document the reviewer scrolls the preview to a change, then has to manually hunt for the same place in the editor to act on it (or vice-versa). VS Code's built-in markdown preview scroll-syncs by default, so the absence here reads as a regression from the familiar behavior. ## Who feels it The **human coauthor** (PP-1) reviewing/editing a **long** markdown document — the longer the doc, the more the lost sync costs. ## Desired outcome / value Scrolling the editor moves the preview to the matching content, and scrolling the preview moves the editor — the two stay aligned so the reviewer never loses their place crossing between "review on the right" and "write on the left." ## Acceptance — "done right" - Scrolling the source editor scrolls the preview to the corresponding rendered content (block-level alignment is sufficient — exact pixel parity is not required). - Scrolling the preview scrolls the editor to the corresponding source line. - Sync does not fight the user (no oscillation/feedback loop between the two scroll events). - The webview stays sealed (INV-21): sync is driven by `postMessage` between host and webview; no new network or document-mutation surface. ## Scope / non-goals **In scope:** bidirectional scroll-sync between the F10 preview webview and its source editor. **Non-goals:** cursor/selection sync; editing in the preview; any change to the render engine or the accept/reject path. ## Assumptions · constraints · dependencies - Builds on F10 (#29, shipped). Requires a source-line↔rendered-block mapping; the preview already splits the document into blocks with source ranges (`splitBlocksWithRanges`), which can seed the mapping. - Constraint: the webview is sealed — scroll position is exchanged via host↔webview `postMessage`, debounced to avoid loops. ## Source / signal Self-originated — **capture session vscode-cowriting-plugin-0031** (2026-06-12), from the F10 spec's open-questions list. Spec: `specs/coauthoring-interactive-review.md` §1.7 (out of scope for F10) / §9 ("OPEN → later: preview→source scroll-sync"). Builds on F10 `#29`. ## Priority (WSJF) Provisional: Value **low–medium** (a quality-of-life parity feature) · Time-criticality **low** · Opportunity **low** ÷ Size **small–medium** → **provisional priority/P3**. (Decision aid, not auto-scored.) ## Decomposition Single increment (Feature, small–medium). Slice checklist: - [ ] Source-line ↔ rendered-block mapping exposed to the webview. - [ ] Editor scroll → preview scroll (host listens to `onDidChangeTextEditorVisibleRanges`, posts target block). - [ ] Preview scroll → editor scroll (webview posts visible block, host reveals the source range). - [ ] Debounce/guard to prevent feedback oscillation. - [ ] Manual smoke on a long doc (E2E can't assert webview scroll). ## Solution notes (optional — NOT a design) Non-binding: VS Code's built-in markdown preview is the reference behavior; the block-range data F10 already computes is the natural anchor for the mapping. A Solution Design should precede implementation if the mapping proves non-trivial.
benstull added the type/featurepriority/P3 labels 2026-06-12 08:09:12 +00:00
benstull added priority/P2 and removed priority/P3 labels 2026-06-26 20:12:27 +00:00
Sign in to join this conversation.