mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
Add overlayscrollbars for prettier scrollbars
This commit is contained in:
Generated
+8
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
Vendored
+1
-1
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 {
|
||||
|
||||
Vendored
+14
-1
File diff suppressed because one or more lines are too long
Vendored
+18
-7
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;
|
||||
}
|
||||
@@ -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']
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user