Skip to content

FE core: OverlayScrollbars — macOS-like overlay scrollbars on all platforms#1487

Open
romanivan-flamingo wants to merge 3 commits into
mainfrom
hotfix/overlayscrollbars-poc
Open

FE core: OverlayScrollbars — macOS-like overlay scrollbars on all platforms#1487
romanivan-flamingo wants to merge 3 commits into
mainfrom
hotfix/overlayscrollbars-poc

Conversation

@romanivan-flamingo

@romanivan-flamingo romanivan-flamingo commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Description

OverlayScrollArea (per-container) + GlobalOverlayScrollbars (body) built on overlayscrollbars-react: native scrolling kept, ODS-themed thumb, autoHide on idle. Fine-pointer devices only — touch keeps native scrollbars. Storybook: UI/OverlayScrollArea.

Task

Settle elevator scrollbars: remove custom track styling, fix layout jumps

Summary by CodeRabbit

  • New Features
    • Added overlay scrollbar support for desktop and fine-pointer devices.
    • Preserved native scrolling on touch-focused devices.
    • Added reusable scroll-area components with customizable behavior.
    • Added global document scrollbar support.
  • Style
    • Introduced a thin, transparent-track scrollbar theme.
  • Documentation
    • Added interactive examples demonstrating vertical, horizontal, and combined scrolling.

romanivan-flamingo and others added 2 commits July 17, 2026 16:38
… on all platforms

OverlayScrollArea (per-container) + GlobalOverlayScrollbars (body) built on
overlayscrollbars-react: native scrolling kept, ODS-themed thumb, autoHide
on idle. Fine-pointer devices only — touch keeps native scrollbars.
Storybook: UI/OverlayScrollArea.

Co-Authored-By: Claude Fable 5 <[email protected]>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@romanivan-flamingo, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ec43eb5-47b5-4277-afee-12c603349ba8

📥 Commits

Reviewing files that changed from the base of the PR and between 73bc098 and 400dd05.

📒 Files selected for processing (13)
  • openframe-frontend-core/src/components/chat/chat-message-list.tsx
  • openframe-frontend-core/src/components/chat/chat-sidebar.tsx
  • openframe-frontend-core/src/components/chat/chat-ticket-list.tsx
  • openframe-frontend-core/src/components/chat/guide-welcome.tsx
  • openframe-frontend-core/src/components/chat/mingo-chat-history.tsx
  • openframe-frontend-core/src/components/chat/mingo-welcome.tsx
  • openframe-frontend-core/src/components/features/notifications/notification-drawer.tsx
  • openframe-frontend-core/src/components/features/time-tracker/time-tracker-panel.tsx
  • openframe-frontend-core/src/components/layout/page-container.tsx
  • openframe-frontend-core/src/components/ui/drawer.tsx
  • openframe-frontend-core/src/components/ui/modal-v2.tsx
  • openframe-frontend-core/src/components/ui/modal.tsx
  • openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx
📝 Walkthrough

Walkthrough

Changes

Overlay scrollbar integration

Layer / File(s) Summary
Responsive scrolling components
openframe-frontend-core/package.json, openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx, openframe-frontend-core/src/components/ui/index.ts
Adds OverlayScrollbars dependencies, fine-pointer detection, responsive local scrolling, document-level initialization, default options, and public exports.
Overlay scrollbar CSS
openframe-frontend-core/src/styles/index.css, openframe-frontend-core/src/styles/vendor-overlayscrollbars.css, openframe-frontend-core/src/styles/overlay-scrollbars-theme.css
Adds vendored OverlayScrollbars layout and state rules plus the ODS theme with transparent tracks and grey handles.
Scrollable component stories
openframe-frontend-core/src/stories/OverlayScrollArea.stories.tsx
Adds vertical, horizontal, and combined overflow Storybook examples.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant useFinePointer
  participant OverlayScrollArea
  participant OverlayScrollbars
  Browser->>useFinePointer: Detect fine-pointer input
  useFinePointer->>OverlayScrollArea: Return pointer capability
  OverlayScrollArea->>OverlayScrollbars: Initialize configured overlay scrolling
Loading

Suggested reviewers: pavlo-flamingo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding OverlayScrollbars with a macOS-like appearance.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hotfix/overlayscrollbars-poc

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx`:
- Around line 26-35: Update useFinePointer and the overlay scroll container so
the host element remains stable across pointer detection, initializing or
destroying OverlayScrollbars in place instead of swapping or remounting the
container after mount. Preserve the existing native behavior when overlay
scrollbars are inactive, and deep-merge the nested scrollbars options so
caller-provided values retain ODS_SCROLLBAR_OPTIONS defaults.
- Around line 75-79: Update the options construction in
OverlayScrollbarsComponent so options.scrollbars is merged with
ODS_SCROLLBAR_OPTIONS.scrollbars instead of being replaced by caller-provided
values. Preserve all other top-level option overrides and ensure the default
theme and auto-hide settings remain when options.scrollbars is partial.

In `@openframe-frontend-core/src/styles/overlay-scrollbars-theme.css`:
- Around line 5-7: Replace the hardcoded scrollbar dimensions in the overlay
scrollbar theme variables, including --os-size, --os-padding-perpendicular, and
--os-padding-axis and the additional flagged values, with existing ODS
spacing/radius tokens or newly defined semantic scrollbar tokens. Preserve the
current sizing behavior while ensuring no raw pixel values remain.

In `@openframe-frontend-core/src/styles/vendor-overlayscrollbars.css`:
- Around line 1-3: Exclude the vendored overlayscrollbars stylesheet from
Stylelint using the project’s existing file-level or Stylelint configuration
mechanism. Keep the upstream-generated CSS unchanged, preserving the wholesale
replacement workflow described in its header.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 713def7e-50ad-43b8-82a6-cec562b02ab5

📥 Commits

Reviewing files that changed from the base of the PR and between 5a7c454 and 73bc098.

📒 Files selected for processing (7)
  • openframe-frontend-core/package.json
  • openframe-frontend-core/src/components/ui/index.ts
  • openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx
  • openframe-frontend-core/src/stories/OverlayScrollArea.stories.tsx
  • openframe-frontend-core/src/styles/index.css
  • openframe-frontend-core/src/styles/overlay-scrollbars-theme.css
  • openframe-frontend-core/src/styles/vendor-overlayscrollbars.css

Comment thread openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx
Comment on lines +75 to +79
return (
<OverlayScrollbarsComponent
className={className}
options={{ ...ODS_SCROLLBAR_OPTIONS, ...options }}
{...props}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the component and related scrollbar defaults.
git ls-files 'openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx' \
             'openframe-frontend-core/src/components/ui/*' \
             'openframe-frontend-core/src/**/*' | sed -n '1,200p'

echo '--- outline ---'
ast-grep outline openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx --view expanded || true

echo '--- file excerpt ---'
nl -ba openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx | sed -n '1,180p'

echo '--- search for ODS_SCROLLBAR_OPTIONS ---'
rg -n "ODS_SCROLLBAR_OPTIONS|scrollbars:" openframe-frontend-core/src -S

Repository: flamingo-stack/openframe-oss-lib

Length of output: 13076


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check OverlayScrollbars option semantics in local docs if present.
rg -n "scrollbars|autoHide|theme" . -g '!*node_modules*' -g '!*.lock' | sed -n '1,200p'

Repository: flamingo-stack/openframe-oss-lib

Length of output: 26875


🏁 Script executed:

#!/bin/bash
set -euo pipefail

nl -ba openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx | sed -n '1,220p'

echo '---'
rg -n "const ODS_SCROLLBAR_OPTIONS|ODS_SCROLLBAR_OPTIONS\\s*=|scrollbars\\s*:" openframe-frontend-core/src -S

Repository: flamingo-stack/openframe-oss-lib

Length of output: 210


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

path = Path('openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx')
text = path.read_text()
for i, line in enumerate(text.splitlines(), 1):
    if 1 <= i <= 180:
        print(f"{i:4}: {line}")
PY

Repository: flamingo-stack/openframe-oss-lib

Length of output: 4808


Deep-merge options.scrollbars here. options={{ ...ODS_SCROLLBAR_OPTIONS, ...options }} replaces the nested scrollbar defaults when callers pass options.scrollbars, dropping the ODS theme and auto-hide settings. openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx:75-79

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openframe-frontend-core/src/components/ui/overlay-scroll-area.tsx` around
lines 75 - 79, Update the options construction in OverlayScrollbarsComponent so
options.scrollbars is merged with ODS_SCROLLBAR_OPTIONS.scrollbars instead of
being replaced by caller-provided values. Preserve all other top-level option
overrides and ensure the default theme and auto-hide settings remain when
options.scrollbars is partial.

Comment on lines +5 to +7
--os-size: 8px;
--os-padding-perpendicular: 2px;
--os-padding-axis: 2px;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Replace raw scrollbar dimensions with ODS tokens.

These hand-written 8px, 2px, 4px, and 33px values violate the source-style contract. Reference existing spacing/radius tokens or introduce semantic scrollbar tokens.

As per coding guidelines: “Do not use hardcoded styles… raw hex colors, pixel sizes, and font shorthands are not allowed.” <coding_guidelines>

Also applies to: 14-14, 18-18

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openframe-frontend-core/src/styles/overlay-scrollbars-theme.css` around lines
5 - 7, Replace the hardcoded scrollbar dimensions in the overlay scrollbar theme
variables, including --os-size, --os-padding-perpendicular, and
--os-padding-axis and the additional flagged values, with existing ODS
spacing/radius tokens or newly defined semantic scrollbar tokens. Preserve the
current sizing behavior while ensuring no raw pixel values remain.

Source: Coding guidelines

Comment on lines +1 to +3
/* Vendored from [email protected] (styles/overlayscrollbars.css).
Do not edit — replace wholesale on package upgrade. ODS theme lives in
./overlay-scrollbars-theme.css */

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Exclude the immutable vendor stylesheet from Stylelint.

The vendored copy currently triggers four Stylelint errors at Lines 200, 235, 286, and 350. Since the header requires wholesale upstream replacement, add a file-level/stylelint configuration exclusion instead of modifying generated rules.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openframe-frontend-core/src/styles/vendor-overlayscrollbars.css` around lines
1 - 3, Exclude the vendored overlayscrollbars stylesheet from Stylelint using
the project’s existing file-level or Stylelint configuration mechanism. Keep the
upstream-generated CSS unchanged, preserving the wholesale replacement workflow
described in its header.

Source: Linters/SAST tools

…containers

OverlayScrollArea now renders its own stable viewport div (passed to
OverlayScrollbars via elements.viewport): children stay its direct
children, refs/onScroll/observer logic work unchanged, overlay handles
live on the non-scrolling host. Swapped: DrawerBody, Modal/ModalV2
content, PageContainer detail scroller, notification drawer list,
time-tracker panel, chat sidebar/ticket list/history, guide & mingo
welcome columns, chat message list.

Co-Authored-By: Claude Fable 5 <[email protected]>
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