fix(scrollbars): unify transient overlay behavior - #1286
Merged
Conversation
Use one tokenized 6px thumb in a 12px overlay hit area across native scrollers, dropdowns, CodeMirror, xterm, custom editors, and isolated Canvas documents. Preserve explicit no-scrollbar chat and compact chrome surfaces, and replace per-code-block visibility timers with a bounded app-wide scroll activity controller. Verified with targeted Vitest coverage, typecheck, fast lint, test-placement checks, Sass compilation, and a production webpack build. Pre-commit hook ran. Total eslint: 0, total circular: 0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Visible scrollbar behavior was implemented independently across native overflow regions, dropdowns, CodeMirror/custom editor tracks, xterm, and Canvas documents. Those paths used different colors and widths, some changed size or color on hover, and some reserved layout space. The unlayered global selector could also outrank the existing
scrollbar-hideutility, exposing horizontal bars in chat panes and compact title/tab rows that are intentionally scrollbar-free. Code blocks additionally owned a timer and React state per instance just to detect scrolling.Solution
Introduce one semantic thumb-color token and shared 6px thumb / 12px hit-area / 3px edge-inset geometry. A single app-wide passive capture listener reveals only the currently scrolling surface and clears it after 900ms of inactivity, pauses while the document is hidden, and disposes on HMR. Native scrollers, dropdowns, CodeMirror, custom editor tracks, xterm, and isolated Canvas documents now follow that contract without hover resizing; xterm and custom tracks remain absolute overlays, and the global native rule uses
scrollbar-gutter: auto. Explicitscrollbar-hidepolicy is restored for chat history, compact tab/title/filter rows, and other audited no-scrollbar surfaces.Potential risks
Verification
pnpm exec vitest run --config config/vitest.config.ts src/util/ui/__tests__/transientScrollbars.test.ts src/util/ui/__tests__/scrollbarStyleContract.test.ts src/engines/ChatPanel/blocks/CanvasInlineCard/canvasBuilder.test.ts src/engines/ChatPanel/blocks/CanvasInlineCard/reactArtifactDocument.test.ts src/engines/ChatPanel/blocks/CanvasInlineCard/staticHtmlCanvas.test.ts src/components/Dropdown/tokens.test.ts src/components/SettingsTable/SettingsTablePagination.test.ts src/components/SettingsTable/stickyContract.test.ts src/engines/TerminalCore/components/TerminalInteractive/__tests__/terminalSizing.test.ts— 9 files and 76 tests passed.pnpm run typecheck— passed.pnpm run lint:fast— passed with zero warnings.pnpm run check:test-placement— passed across 495 directories.pnpm exec sass src/index.scss /tmp/orgii-unified-scrollbars.css --load-path=node_modules --no-source-map— compiled successfully; only the repository's existing Sass@importdeprecation warnings were emitted.pnpm run build— production webpack build passed.pnpm exec prettier --check <29 changed files>andgit diff --check— passed.UI audit
CustomScrollbar: 3 pre-existing accessibility/theme fix candidates, 3 keep with reason, 0 abstract. The candidates are documented but intentionally deferred to keep this PR limited to scrollbar appearance, visibility, and lifecycle.Performance guard
Performance verdict: pass.