Add overlayscrollbars for prettier scrollbars

This commit is contained in:
Raj Siva-Rajah
2025-07-14 12:28:26 +00:00
parent 3250e8603f
commit 2ba2ed53bd
10 changed files with 271 additions and 10 deletions
+8
View File
@@ -83,6 +83,7 @@
"mime": "^4.0.4",
"nouislider": "^15.8.1",
"npm-run-all": "^4.1.5",
"overlayscrollbars": "^2.11.4",
"prettier": "^3.1.1",
"prettier-plugin-blade": "v2.0.0",
"prettier-plugin-tailwindcss": "^0.6.10",
@@ -10467,6 +10468,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/overlayscrollbars": {
"version": "2.11.4",
"resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.11.4.tgz",
"integrity": "sha512-GKYQo3OZ1QWnppNjQVv5hfpn+glYUxc6+ufW+ivdXUyLWFNc01XoH2Z36KGM4I8e5pXYeA3ElNItcXiLvmUhnQ==",
"dev": true,
"license": "MIT"
},
"node_modules/own-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+1
View File
@@ -91,6 +91,7 @@
"mime": "^4.0.4",
"nouislider": "^15.8.1",
"npm-run-all": "^4.1.5",
"overlayscrollbars": "^2.11.4",
"prettier": "^3.1.1",
"prettier-plugin-blade": "v2.0.0",
"prettier-plugin-tailwindcss": "^0.6.10",
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -139,7 +139,6 @@
.fi-sidebar-nav {
@apply flex grow flex-col gap-y-7 overflow-x-hidden overflow-y-auto px-6 py-8;
scrollbar-gutter: stable;
}
.fi-sidebar-nav-groups {
+14 -1
View File
File diff suppressed because one or more lines are too long
+18 -7
View File
File diff suppressed because one or more lines are too long
@@ -0,0 +1,129 @@
/* Hide native scrollbars for elements that will use OverlayScrollbars */
.fi-scrollbar,
.fi-scrollbar-thin,
.fi-scrollbar-always,
[data-overlayscrollbars-initialize] {
scrollbar-width: none; /* Firefox */
&::-webkit-scrollbar {
@apply hidden; /* Chrome, Safari, Edge */
}
}
/* Filament light theme */
.os-theme-filament-light {
@apply box-border;
--os-size: 10px;
--os-padding-perpendicular: 2px;
--os-padding-axis: 2px;
--os-track-border-radius: 10px;
--os-track-bg: none;
--os-track-bg-hover: none;
--os-track-bg-active: none;
--os-track-border: none;
--os-track-border-hover: none;
--os-track-border-active: none;
--os-handle-border-radius: 10px;
--os-handle-bg: theme('colors.gray.400 / 50%');
--os-handle-bg-hover: theme('colors.gray.500 / 50%');
--os-handle-bg-active: theme('colors.gray.600 / 50%');
--os-handle-border: none;
--os-handle-border-hover: none;
--os-handle-border-active: none;
--os-handle-min-size: 33px;
--os-handle-max-size: none;
--os-handle-perpendicular-size: 100%;
--os-handle-perpendicular-size-hover: 100%;
--os-handle-perpendicular-size-active: 100%;
--os-handle-interactive-area-offset: 4px;
}
/* Filament dark theme */
.os-theme-filament-dark {
@apply box-border;
--os-size: 10px;
--os-padding-perpendicular: 2px;
--os-padding-axis: 2px;
--os-track-border-radius: 10px;
--os-track-bg: none;
--os-track-bg-hover: none;
--os-track-bg-active: none;
--os-track-border: none;
--os-track-border-hover: none;
--os-track-border-active: none;
--os-handle-border-radius: 10px;
--os-handle-bg: theme('colors.gray.500 / 30%');
--os-handle-bg-hover: theme('colors.gray.400 / 40%');
--os-handle-bg-active: theme('colors.gray.300 / 50%');
--os-handle-border: none;
--os-handle-border-hover: none;
--os-handle-border-active: none;
--os-handle-min-size: 33px;
--os-handle-max-size: none;
--os-handle-perpendicular-size: 100%;
--os-handle-perpendicular-size-hover: 100%;
--os-handle-perpendicular-size-active: 100%;
--os-handle-interactive-area-offset: 4px;
}
/* Filament thin theme - light */
.os-theme-filament-thin-light {
@apply box-border;
--os-size: 6px;
--os-padding-perpendicular: 1px;
--os-padding-axis: 1px;
--os-track-border-radius: 6px;
--os-track-bg: none;
--os-track-bg-hover: none;
--os-track-bg-active: none;
--os-track-border: none;
--os-track-border-hover: none;
--os-track-border-active: none;
--os-handle-border-radius: 6px;
--os-handle-bg: theme('colors.gray.400 / 40%');
--os-handle-bg-hover: theme('colors.gray.500 / 50%');
--os-handle-bg-active: theme('colors.gray.600 / 60%');
--os-handle-border: none;
--os-handle-border-hover: none;
--os-handle-border-active: none;
--os-handle-min-size: 33px;
--os-handle-max-size: none;
--os-handle-perpendicular-size: 100%;
--os-handle-perpendicular-size-hover: 100%;
--os-handle-perpendicular-size-active: 100%;
--os-handle-interactive-area-offset: 4px;
}
/* Filament thin theme - dark */
.os-theme-filament-thin-dark {
@apply box-border;
--os-size: 6px;
--os-padding-perpendicular: 1px;
--os-padding-axis: 1px;
--os-track-border-radius: 6px;
--os-track-bg: none;
--os-track-bg-hover: none;
--os-track-bg-active: none;
--os-track-border: none;
--os-track-border-hover: none;
--os-track-border-active: none;
--os-handle-border-radius: 6px;
--os-handle-bg: theme('colors.gray.500 / 20%');
--os-handle-bg-hover: theme('colors.gray.400 / 30%');
--os-handle-bg-active: theme('colors.gray.300 / 40%');
--os-handle-border: none;
--os-handle-border-hover: none;
--os-handle-border-active: none;
--os-handle-min-size: 33px;
--os-handle-max-size: none;
--os-handle-perpendicular-size: 100%;
--os-handle-perpendicular-size-hover: 100%;
--os-handle-perpendicular-size-active: 100%;
--os-handle-interactive-area-offset: 4px;
}
/* z-index adjustments for overlay contexts */
.fi-modal .os-scrollbar,
.fi-dropdown-panel .os-scrollbar {
@apply z-10;
}
+1
View File
@@ -26,6 +26,7 @@
@import './components/loading-section.css' layer(components);
@import './components/modal.css' layer(components);
@import './components/pagination.css' layer(components);
@import './components/scrollbar.css' layer(components);
@import './components/section.css' layer(components);
@import './components/tabs.css' layer(components);
@import './components/toggle.css' layer(components);
@@ -0,0 +1,95 @@
import { OverlayScrollbars } from 'overlayscrollbars'
export default () => {
const isDarkMode = () => document.documentElement.classList.contains('dark')
const initOverlayScrollbars = () => {
// Config for different scrollbar types
const configs = {
'fi-scrollbar': {
scrollbars: {
theme: isDarkMode()
? 'os-theme-filament-dark'
: 'os-theme-filament-light',
autoHide: 'move',
autoHideDelay: 1000,
clickScroll: true
}
},
'fi-scrollbar-thin': {
scrollbars: {
theme: isDarkMode()
? 'os-theme-filament-thin-dark'
: 'os-theme-filament-thin-light',
autoHide: 'scroll',
autoHideDelay: 1000,
clickScroll: true
}
},
'fi-scrollbar-always': {
scrollbars: {
theme: isDarkMode()
? 'os-theme-filament-dark'
: 'os-theme-filament-light',
autoHide: 'never',
clickScroll: true
}
}
}
// Initialize elements with data attribute
Object.entries(configs).forEach(([className, config]) => {
document.querySelectorAll(`.${className}[data-overlayscrollbars-initialize]`).forEach(element => {
const existing = OverlayScrollbars(element)
if (!existing) {
OverlayScrollbars(element, config)
} else {
// Update existing instance config
existing.options(config)
}
})
})
}
// Initialize on DOM ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initOverlayScrollbars)
} else {
initOverlayScrollbars()
}
// Re-initialize after Livewire updates
document.addEventListener('livewire:navigated', () => {
setTimeout(initOverlayScrollbars, 0)
})
// Handle dark mode changes
const observer = new MutationObserver(() => {
document.querySelectorAll('[data-overlayscrollbars]').forEach(el => {
const instance = OverlayScrollbars(el)
if (instance) {
const currentOptions = instance.options()
const currentTheme = currentOptions.scrollbars?.theme || ''
let newTheme = currentTheme
if (currentTheme.includes('filament-thin')) {
newTheme = isDarkMode() ? 'os-theme-filament-thin-dark' : 'os-theme-filament-thin-light'
} else {
newTheme = isDarkMode() ? 'os-theme-filament-dark' : 'os-theme-filament-light'
}
instance.options({
scrollbars: {
...currentOptions.scrollbars,
theme: newTheme
}
})
}
})
})
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
})
}
+4
View File
@@ -7,11 +7,13 @@ import Tooltip from '@ryangjchandler/alpine-tooltip'
import dropdown from './components/dropdown.js'
import formButton from './components/form-button.js'
import modal from './components/modal.js'
import scrollbar from './components/scrollbar.js'
import './partials.js'
import pluralize from './utilities/pluralize.js'
import 'tippy.js/dist/tippy.css'
import 'tippy.js/themes/light.css'
import 'overlayscrollbars/overlayscrollbars.css'
document.addEventListener('alpine:init', () => {
window.Alpine.plugin(AlpineFloatingUI)
@@ -22,6 +24,8 @@ document.addEventListener('alpine:init', () => {
window.Alpine.data('filamentDropdown', dropdown)
window.Alpine.data('filamentFormButton', formButton)
window.Alpine.data('filamentModal', modal)
scrollbar()
})
window.jsMd5 = md5