Skip to content

fix(editor): prevent cursor snap after scrollbar drag#2263

Merged
deadlyjack merged 4 commits into
mainfrom
fix-editor-scrollbar-cursor-snap
Jun 17, 2026
Merged

fix(editor): prevent cursor snap after scrollbar drag#2263
deadlyjack merged 4 commits into
mainfrom
fix-editor-scrollbar-cursor-snap

Conversation

@bajrangCoder

Copy link
Copy Markdown
Member

No description provided.

@greptile-apps

greptile-apps Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the editor cursor snap that occurred after a custom scrollbar drag by introducing a time-bounded scroll-position lock. When the user drags the custom scrollbar, the final scroll position is locked for 1200 ms; any CodeMirror-initiated scroll that deviates from that position is immediately reverted by a new restoreScrollbarScrollLock guard inside handleEditorScroll. The CSS additions (touch-action: none, user-select: none) complement the JS fix by preventing accidental text selection and native scroll gestures on the scrollbar thumb.

  • New lock mechanism (lockScrollbarScrollPosition, clearScrollbarScrollLock, restoreScrollbarScrollLock) tracks the desired scroll position during and after a drag; three extra event listeners (pointerdown, touchstart, wheel) on the scroller clear the lock when the user intentionally scrolls through other means.
  • pointerCursorVisibilityExtension reworked to call clearScrollbarScrollLock() on non-pointer transactions — the broad match (any transaction without a pointer user event) may let background dispatches (lint, autocomplete) prematurely cancel the 1200 ms window.
  • suppressCursorReveal duration extended from 500 ms to 1200 ms to match the new lock duration.

Confidence Score: 5/5

The fix is self-contained and additive — it only runs during custom scrollbar drags and clears itself on user intent. The worst-case failure mode (background transaction prematurely ending the lock) degrades the fix back toward the pre-PR behavior rather than introducing a new regression.

The lock/restore mechanism is well-scoped: it only acts during and briefly after a scrollbar drag, clears on explicit user interaction, and does not touch any persistent state outside the drag window. No data loss or crash paths are introduced.

The pointerCursorVisibilityExtension change in editorManager.js (lines ~200-203) is worth a second look to ensure the lock-clear condition is scoped to user-initiated non-pointer events rather than all CM transactions.

Important Files Changed

Filename Overview
src/lib/editorManager.js Adds scroll-position lock/restore logic (lockScrollbarScrollPosition, clearScrollbarScrollLock, restoreScrollbarScrollLock) plus direct scroller event listeners to prevent cursor snap after scrollbar drag; extends suppressCursorReveal from 500 ms to 1200 ms; extends the pointerCursorVisibilityExtension to clear the lock on non-pointer transactions, which may fire too broadly for background CM activity.
src/components/scrollbar/style.scss Adds touch-action: none, user-select: none, and -webkit-user-select: none to .scrollbar-container to prevent text-selection and default scroll gestures during custom scrollbar drag; also fixes a missing newline at end of file.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant Scrollbar
    participant onscrollV
    participant onscrollVend
    participant handleEditorScroll
    participant restoreScrollbarScrollLock
    participant pointerCursorVisibilityExtension

    User->>Scrollbar: drag thumb
    Scrollbar->>onscrollV: scroll event (repeated)
    onscrollV->>handleEditorScroll: sets scroller.scrollTop
    onscrollV->>onscrollV: lockScrollbarScrollPosition

    User->>Scrollbar: release thumb
    Scrollbar->>onscrollVend: drag end
    onscrollVend->>onscrollVend: lockScrollbarScrollPosition 1200ms
    onscrollVend->>onscrollVend: suppressCursorReveal 1200ms

    Note over handleEditorScroll: CM internally tries scrollIntoView
    handleEditorScroll->>restoreScrollbarScrollLock: on each scroll event
    restoreScrollbarScrollLock-->>handleEditorScroll: reverts if lock active

    alt User taps in editor
        User->>handleEditorScroll: pointerdown clears lock
        pointerCursorVisibilityExtension->>pointerCursorVisibilityExtension: pointer tx scrollCursorIntoView
    else Background CM transaction
        pointerCursorVisibilityExtension->>pointerCursorVisibilityExtension: non-pointer tx clears lock prematurely
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant Scrollbar
    participant onscrollV
    participant onscrollVend
    participant handleEditorScroll
    participant restoreScrollbarScrollLock
    participant pointerCursorVisibilityExtension

    User->>Scrollbar: drag thumb
    Scrollbar->>onscrollV: scroll event (repeated)
    onscrollV->>handleEditorScroll: sets scroller.scrollTop
    onscrollV->>onscrollV: lockScrollbarScrollPosition

    User->>Scrollbar: release thumb
    Scrollbar->>onscrollVend: drag end
    onscrollVend->>onscrollVend: lockScrollbarScrollPosition 1200ms
    onscrollVend->>onscrollVend: suppressCursorReveal 1200ms

    Note over handleEditorScroll: CM internally tries scrollIntoView
    handleEditorScroll->>restoreScrollbarScrollLock: on each scroll event
    restoreScrollbarScrollLock-->>handleEditorScroll: reverts if lock active

    alt User taps in editor
        User->>handleEditorScroll: pointerdown clears lock
        pointerCursorVisibilityExtension->>pointerCursorVisibilityExtension: pointer tx scrollCursorIntoView
    else Background CM transaction
        pointerCursorVisibilityExtension->>pointerCursorVisibilityExtension: non-pointer tx clears lock prematurely
    end
Loading

Reviews (2): Last reviewed commit: "fix" | Re-trigger Greptile

Comment thread src/lib/editorManager.js
Comment thread src/lib/editorManager.js
Comment thread src/lib/editorManager.js
@bajrangCoder

This comment was marked as outdated.

@deadlyjack deadlyjack merged commit d2eb67e into main Jun 17, 2026
9 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in The Code Board - Acode Jun 17, 2026
@deadlyjack deadlyjack deleted the fix-editor-scrollbar-cursor-snap branch June 17, 2026 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants