Skip to content

feat(ui): add theme-aware native scrollbars - #332

Open
samheutmaker wants to merge 1 commit into
developmentfrom
feat/native-scrollbars
Open

samheutmaker wants to merge 1 commit into
developmentfrom
feat/native-scrollbars

Conversation

@samheutmaker

@samheutmaker samheutmaker commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add shared StyleX native-scrollbar styling: 9px tracks, rounded inset thumbs, theme-aware colors, and stronger hover feedback.
  • Apply it to chat/reading lists, the session sidebar, shared ScrollArea, dialog viewports, and workspace content without replacing native scrolling or changing scroll state.
  • Use standard thin/color styling only as the Firefox fallback; keep platform defaults for touch and forced colors and preserve intentionally hidden tab-strip scrollbars.
  • Add a Storybook example, production-browser regression fixture, and frontend documentation.

Validation

  • UI and app TypeScript checks; production web build
  • Full web test suite: 1,380 tests
  • UI unit tests: 38 tests
  • New scrollbar browser checks: Chromium, Firefox, and WebKit (geometry, themes, keyboard/wheel, both axes, hover where observable, touch/forced-color fallbacks, and strict CSP)
  • Existing strict-CSP suite: Chromium, Firefox, and Safari
  • Storybook production build
  • Git diff whitespace check

Remaining manual check

Native thumb dragging on macOS: synthetic drags did not scroll even an unstyled native control in this environment, so manual validation is still needed. Keyboard/wheel behavior is covered. No new dependency or custom scrollbar DOM was introduced.


Note

Low Risk
Presentation-only CSS on native scroll containers; scroll behavior, virtualization, and touch/forced-color fallbacks are explicitly preserved and regression-tested.

Overview
Adds shared theme-aware native scrollbar styling via @whip/ui/scrollbar.stylex (scrollbarStyles.native): 9px WebKit thumbs with rounded transparent insets, foreground-based color-mix colors, and stronger hover on fine-pointer desktops; Firefox gets scrollbar-width/scrollbar-color only when WebKit pseudo-elements are unsupported. Touch and forced-colors keep platform defaults.

Applies the style to existing scroll owners—ScrollArea, dialog/alert viewports, workspace pane content, chat reading list, and session sidebar—without new wrappers or scroll logic. The sidebar drops its ad hoc scrollbarWidth: 'thin'.

Adds package export scrollbar.stylex, npm run test:scrollbars, a Playwright regression across Chromium/Firefox/WebKit (geometry, themes, keyboard/wheel, CSP), Storybook WHIP/Scrollbars, and docs in features.md / frontend.md.

Reviewed by Cursor Bugbot for commit 25dfcc1. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 25dfcc1. Configure here.

<div
ref={viewport}
{...stylex.props(styles.viewport, chatFollow ? styles.chatEdges : styles.topEdge)}
{...stylex.props(styles.viewport, scrollbarStyles.native, chatFollow ? styles.chatEdges : styles.topEdge)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mask fades chat scrollbar thumb

Medium Severity

scrollbarStyles.native is applied on the same ReadingList viewport as maskImage / WebkitMaskImage. Those fades clip the element’s painted output, including classic ::-webkit-scrollbar thumbs. In chat-follow mode the thumb sits in the bottom 40px fade, so the new control is weakest at the default pinned position.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 25dfcc1. Configure here.

This branch has not been deployed

No deployments
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