From 422aba8d0e6f473830c26c05b475e0d49459aeae Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Mon, 3 Aug 2026 07:02:18 +0800 Subject: [PATCH] fix(layout): align scrollbar and navbar behavior (#626) --- src/@core/scss/libs/perfect-scrollbar.scss | 13 ------- src/@layouts/components/VerticalNavLayout.vue | 4 +- .../__tests__/glassOverlayMaterial.spec.ts | 1 - src/styles/common.scss | 37 ++++++++----------- src/styles/themes/glass.scss | 19 ---------- src/views/dashboard/AnalyticsScheduler.vue | 7 +++- src/views/dashboard/MediaServerLatest.vue | 7 +++- src/views/dashboard/MediaServerLibrary.vue | 7 +++- src/views/dashboard/MediaServerPlaying.vue | 7 +++- 9 files changed, 37 insertions(+), 65 deletions(-) diff --git a/src/@core/scss/libs/perfect-scrollbar.scss b/src/@core/scss/libs/perfect-scrollbar.scss index 38110726..e9a5ebba 100644 --- a/src/@core/scss/libs/perfect-scrollbar.scss +++ b/src/@core/scss/libs/perfect-scrollbar.scss @@ -33,16 +33,3 @@ $ps-track-size: 0.5rem; .ps__rail-y:hover > .ps__thumb-y { inline-size: $ps-hover-size; } - -// 滚动条只反馈实际滚动状态,鼠标经过容器或键盘聚焦不应让轨道常驻。 -.ps:hover > .ps__rail-x, -.ps:hover > .ps__rail-y, -.ps--focus > .ps__rail-x, -.ps--focus > .ps__rail-y { - opacity: 0 !important; -} - -.ps.ps--scrolling-x > .ps__rail-x, -.ps.ps--scrolling-y > .ps__rail-y { - opacity: 0.6 !important; -} diff --git a/src/@layouts/components/VerticalNavLayout.vue b/src/@layouts/components/VerticalNavLayout.vue index fac6abb2..9667d26f 100644 --- a/src/@layouts/components/VerticalNavLayout.vue +++ b/src/@layouts/components/VerticalNavLayout.vue @@ -213,7 +213,7 @@ export default defineComponent({ // 单独提升顶栏图层可避免导航栏短暂上移到安全区下方。 backface-visibility: hidden; block-size: var(--layout-navbar-block-size); - inline-size: calc(100vw - variables.$layout-vertical-nav-width - 0.5rem); + inline-size: calc(100% - variables.$layout-vertical-nav-width); inset-block-start: 0; transform: translate3d(0, 0, 0); @@ -277,7 +277,7 @@ export default defineComponent({ } &.layout-vertical-nav-collapsed .layout-navbar { - inline-size: calc(100vw - variables.$layout-vertical-nav-collapsed-width - 0.5rem); + inline-size: calc(100% - variables.$layout-vertical-nav-collapsed-width); } &.layout-vertical-nav-collapsed .layout-vertical-nav:not(.overlay-nav) { diff --git a/src/styles/__tests__/glassOverlayMaterial.spec.ts b/src/styles/__tests__/glassOverlayMaterial.spec.ts index 0921f793..dad8e991 100644 --- a/src/styles/__tests__/glassOverlayMaterial.spec.ts +++ b/src/styles/__tests__/glassOverlayMaterial.spec.ts @@ -61,7 +61,6 @@ describe('glass overlay material styles', () => { expect(mainBackplateRule).toBeDefined() expect(mainBackplateRule).not.toMatch(/transition:\s*clip-path/u) expect(overlayBackplateRule).toMatch(/transition:\s*clip-path 0\.25s ease-in-out/u) - expect(styles).toMatch(/\.layout-vertical-nav \.ps__rail-y\s*\{[\s\S]*?inset-inline-end:\s*0\.5rem !important;/) }) it('shares the same light frost when glass navbars overlap scrolled content', () => { diff --git a/src/styles/common.scss b/src/styles/common.scss index 9a2567b6..34df0666 100644 --- a/src/styles/common.scss +++ b/src/styles/common.scss @@ -1420,32 +1420,25 @@ html[data-theme='transparent'].transparent-glass-realtime .v-theme--transparent } } -// 滚动条样式 -::-webkit-scrollbar { - block-size: 4px; - inline-size: 4px; - opacity: 0; - transition: opacity 0.3s; -} - -::-webkit-scrollbar-thumb { - border-radius: 2px; - background: rgb(var(--v-theme-perfect-scrollbar-thumb)); - box-shadow: inset 0 0 10px rgba(0, 0, 0, 20%); - - @media (hover) { - &:hover { - background: #a1a1a1; - } +// 原生滚动条沿用浏览器的几何与显隐行为,只统一窄宽度和主题色。 +@supports (scrollbar-width: thin) { + * { + scrollbar-color: rgba(var(--v-theme-perfect-scrollbar-thumb), 60%) transparent; + scrollbar-width: thin; } } -*:hover::-webkit-scrollbar { - opacity: 1; -} +// 旧版 WebKit 不支持标准滚动条属性,仅保留基础几何与主题色。 +@supports not (scrollbar-width: thin) { + ::-webkit-scrollbar { + block-size: 4px; + inline-size: 4px; + } -*:active::-webkit-scrollbar { - opacity: 1; + ::-webkit-scrollbar-thumb { + border-radius: 2px; + background: rgb(var(--v-theme-perfect-scrollbar-thumb)); + } } // 组件样式 diff --git a/src/styles/themes/glass.scss b/src/styles/themes/glass.scss index b4a824b5..989ce7e7 100644 --- a/src/styles/themes/glass.scss +++ b/src/styles/themes/glass.scss @@ -491,25 +491,6 @@ html[data-theme='glass'] { } } - // 滚动条与导航材质边界保持间距,避免窄轨道参与全高背板的合成。 - .layout-vertical-nav .ps__rail-y { - inset-inline-end: 0.5rem !important; - transition: opacity 120ms linear; - } - - .layout-vertical-nav .ps__thumb-y, - .layout-vertical-nav .ps__rail-y:focus > .ps__thumb-y, - .layout-vertical-nav .ps__rail-y:hover > .ps__thumb-y, - .layout-vertical-nav .ps__rail-y.ps--clicking .ps__thumb-y { - background-color: rgba(255, 255, 255, 28%) !important; - inline-size: 2px !important; - inset-inline-end: 0.1875rem; - } - - .layout-vertical-nav .nav-items.ps--scrolling-y > .ps__rail-y { - opacity: 0.42; - } - .layout-vertical-nav .nav-link > .router-link-exact-active { border: var(--glass-nav-active-border); background: var(--glass-nav-active-background) !important; diff --git a/src/views/dashboard/AnalyticsScheduler.vue b/src/views/dashboard/AnalyticsScheduler.vue index d1550197..9162ef50 100644 --- a/src/views/dashboard/AnalyticsScheduler.vue +++ b/src/views/dashboard/AnalyticsScheduler.vue @@ -183,6 +183,7 @@ useDataRefresh( flex: 1 1 auto; min-block-size: 0; overscroll-behavior: contain; + scrollbar-width: none; } .background-task-item { @@ -242,8 +243,10 @@ useDataRefresh( min-block-size: 0; } -.card-list::-webkit-scrollbar { - display: none; +@supports not (scrollbar-width: none) { + .card-list::-webkit-scrollbar { + display: none; + } } @keyframes background-task-rotate { diff --git a/src/views/dashboard/MediaServerLatest.vue b/src/views/dashboard/MediaServerLatest.vue index 4408b1c7..73579f4e 100644 --- a/src/views/dashboard/MediaServerLatest.vue +++ b/src/views/dashboard/MediaServerLatest.vue @@ -229,9 +229,12 @@ onActivated(() => { flex-direction: column; min-block-size: 0; overflow: auto; + scrollbar-width: none; } -.dashboard-media-content::-webkit-scrollbar { - display: none; +@supports not (scrollbar-width: none) { + .dashboard-media-content::-webkit-scrollbar { + display: none; + } } diff --git a/src/views/dashboard/MediaServerLibrary.vue b/src/views/dashboard/MediaServerLibrary.vue index da3281c3..4ec98c41 100644 --- a/src/views/dashboard/MediaServerLibrary.vue +++ b/src/views/dashboard/MediaServerLibrary.vue @@ -185,9 +185,12 @@ onActivated(() => { flex-direction: column; min-block-size: 0; overflow: auto; + scrollbar-width: none; } -.dashboard-media-content::-webkit-scrollbar { - display: none; +@supports not (scrollbar-width: none) { + .dashboard-media-content::-webkit-scrollbar { + display: none; + } } diff --git a/src/views/dashboard/MediaServerPlaying.vue b/src/views/dashboard/MediaServerPlaying.vue index 08a7a84b..2abf8c3e 100644 --- a/src/views/dashboard/MediaServerPlaying.vue +++ b/src/views/dashboard/MediaServerPlaying.vue @@ -229,9 +229,12 @@ onActivated(() => { flex-direction: column; min-block-size: 0; overflow: auto; + scrollbar-width: none; } -.dashboard-media-content::-webkit-scrollbar { - display: none; +@supports not (scrollbar-width: none) { + .dashboard-media-content::-webkit-scrollbar { + display: none; + } }