From 4382dc25b2d864dd1c1d65de36a4ed8f26a7648f Mon Sep 17 00:00:00 2001 From: Mark Dumay <61946753+markdumay@users.noreply.github.com> Date: Thu, 9 Jul 2026 09:04:04 +0200 Subject: [PATCH] fix(sidebar): stop overlay scrollbar overlapping sidebar items MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The docs sidebar scrolls inside `.sidebar-overflow`, which sets `scrollbar-gutter: stable`. That gutter is honored only for classic (non-overlay) scrollbars. On macOS, Chrome/Safari default to overlay scrollbars, which take no layout space, so the gutter collapses to 0 and the vertical scrollbar floats over the sidebar content (the group chevrons) — and Chrome fattens it while scrolling. Style the scrollbar so it opts out of overlay mode: it then reserves width and sits in the stable gutter instead of over the content, consistent across browsers. Reuse the existing `scrollbar` mixin with a muted thumb on a transparent track, so it stays subtle and light/dark aware. The mixin lived in `common/scrollbar.scss`, imported after the components, so no component could `@include` it. Move that import ahead of the components block so the shared mixin is available to them. Co-Authored-By: Claude Opus 4.8 (1M context) --- assets/scss/app-dart.scss | 4 +++- assets/scss/app.scss | 4 +++- assets/scss/components/_sidebar.scss | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/assets/scss/app-dart.scss b/assets/scss/app-dart.scss index cecb3cf90..8386a1391 100644 --- a/assets/scss/app-dart.scss +++ b/assets/scss/app-dart.scss @@ -20,6 +20,9 @@ // Include dark mode overrides @import "common/variables-dark.scss"; +// Scrollbar mixin — imported before the components so they can @include it +@import "common/scrollbar.scss"; + // Import Hinode theme styles @import "components/abbr.scss"; @import "components/alert.scss"; @@ -51,7 +54,6 @@ @import "components/lightbox.scss"; @import "common/animation.scss"; @import "common/masonry.scss"; -@import "common/scrollbar.scss"; @import "common/styles.scss"; @import "layouts/reboot.scss"; @import "layouts/type.scss"; diff --git a/assets/scss/app.scss b/assets/scss/app.scss index 5085f1ede..8741c2d0f 100644 --- a/assets/scss/app.scss +++ b/assets/scss/app.scss @@ -18,6 +18,9 @@ // Include dark mode overrides @import "common/variables-dark.scss"; +// Scrollbar mixin — imported before the components so they can @include it +@import "common/scrollbar.scss"; + // Import Hinode theme styles @import "components/abbr.scss"; @import "components/alert.scss"; @@ -49,7 +52,6 @@ @import "components/lightbox.scss"; @import "common/animation.scss"; @import "common/masonry.scss"; -@import "common/scrollbar.scss"; @import "common/styles.scss"; @import "layouts/reboot.scss"; @import "layouts/type.scss"; diff --git a/assets/scss/components/_sidebar.scss b/assets/scss/components/_sidebar.scss index 16ab11f2a..a846618e3 100644 --- a/assets/scss/components/_sidebar.scss +++ b/assets/scss/components/_sidebar.scss @@ -44,6 +44,20 @@ html.sidebar-pre-collapsed .sidebar-collapsible .sidebar-brand { max-height: calc(100vh - var(--navbar-offset)); overflow-y: auto; scrollbar-gutter: stable; + + // `scrollbar-gutter: stable` reserves the gutter only for classic + // scrollbars. On macOS, Chrome/Safari default to overlay scrollbars, + // which take no layout space — so the gutter collapses to 0 and the bar + // floats over the sidebar content (the group chevrons). Styling the + // scrollbar opts the element out of overlay mode, giving a non-overlay bar + // that reserves width and sits in the stable gutter, consistent across + // browsers. A muted thumb on a transparent track keeps it subtle and + // light/dark aware. + @include scrollbar( + $foreground-color: var(--bs-border-color), + $background-color: transparent, + $size: 8px + ); } .sidebar-item {