feat: integrate OverlayScrollbars with theme-aware styling

This commit is contained in:
2026-01-29 01:05:19 -06:00
parent 67d7c81ef4
commit 62d4f4620f
4 changed files with 55 additions and 0 deletions
+8
View File
@@ -4,6 +4,10 @@
"workspaces": { "workspaces": {
"": { "": {
"name": "banner-web", "name": "banner-web",
"dependencies": {
"overlayscrollbars": "^2.14.0",
"overlayscrollbars-svelte": "^0.5.5",
},
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.4", "@biomejs/biome": "^1.9.4",
"@fontsource-variable/inter": "^5.2.5", "@fontsource-variable/inter": "^5.2.5",
@@ -382,6 +386,10 @@
"nwsapi": ["nwsapi@2.2.23", "", {}, "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ=="], "nwsapi": ["nwsapi@2.2.23", "", {}, "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ=="],
"overlayscrollbars": ["overlayscrollbars@2.14.0", "", {}, "sha512-RjV0pqc79kYhQLC3vTcLRb5GLpI1n6qh0Oua3g+bGH4EgNOJHVBGP7u0zZtxoAa0dkHlAqTTSYRb9MMmxNLjig=="],
"overlayscrollbars-svelte": ["overlayscrollbars-svelte@0.5.5", "", { "peerDependencies": { "overlayscrollbars": "^2.0.0", "svelte": "^5.0.0" } }, "sha512-+dRW3YZSvFbKi5vDCpnUOHuoPLLSdu0BUVVMYZdmfVghu7XkafDRebG2y91/ImPqj6YDAUsz1rcWVYhCJSS/pQ=="],
"parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
+4
View File
@@ -31,5 +31,9 @@
"typescript": "^5.7.2", "typescript": "^5.7.2",
"vite": "^6.3.5", "vite": "^6.3.5",
"vitest": "^3.0.5" "vitest": "^3.0.5"
},
"dependencies": {
"overlayscrollbars": "^2.14.0",
"overlayscrollbars-svelte": "^0.5.5"
} }
} }
+14
View File
@@ -1,6 +1,8 @@
<script lang="ts"> <script lang="ts">
import "overlayscrollbars/overlayscrollbars.css";
import "./layout.css"; import "./layout.css";
import { onMount } from "svelte"; import { onMount } from "svelte";
import { OverlayScrollbars } from "overlayscrollbars";
import { Tooltip } from "bits-ui"; import { Tooltip } from "bits-ui";
import ThemeToggle from "$lib/components/ThemeToggle.svelte"; import ThemeToggle from "$lib/components/ThemeToggle.svelte";
import { themeStore } from "$lib/stores/theme.svelte"; import { themeStore } from "$lib/stores/theme.svelte";
@@ -9,6 +11,18 @@ let { children } = $props();
onMount(() => { onMount(() => {
themeStore.init(); themeStore.init();
const osInstance = OverlayScrollbars(document.body, {
scrollbars: {
autoHide: "leave",
autoHideDelay: 800,
theme: themeStore.isDark ? "os-theme-dark" : "os-theme-light",
},
});
return () => {
osInstance?.destroy();
};
}); });
</script> </script>
+29
View File
@@ -76,6 +76,35 @@ body * {
mix-blend-mode: normal; mix-blend-mode: normal;
} }
/* OverlayScrollbars — custom handle colors per theme */
:root .os-scrollbar {
--os-handle-bg: rgba(0, 0, 0, 0.25);
--os-handle-bg-hover: rgba(0, 0, 0, 0.35);
--os-handle-bg-active: rgba(0, 0, 0, 0.45);
}
.dark .os-scrollbar {
--os-handle-bg: rgba(255, 255, 255, 0.35);
--os-handle-bg-hover: rgba(255, 255, 255, 0.45);
--os-handle-bg-active: rgba(255, 255, 255, 0.55);
}
.os-scrollbar-handle {
border-radius: 4px;
}
/* Hide native scrollbars on body — OverlayScrollbars takes over */
html,
body {
scrollbar-width: none;
-ms-overflow-style: none;
}
html::-webkit-scrollbar,
body::-webkit-scrollbar {
display: none;
}
@keyframes pulse { @keyframes pulse {
0%, 0%,
100% { 100% {