Refine glass navbar and file browser surface materials

This commit is contained in:
jxxghp
2026-07-30 15:25:45 +08:00
parent f761c59637
commit 4362e76ca0
3 changed files with 48 additions and 17 deletions
+2 -2
View File
@@ -75,7 +75,7 @@ const storageObject = computed(() => {
// 切换存储 // 切换存储
function changeStorage(code: string) { function changeStorage(code: string) {
if (inProps.item.storage!== code) { if (inProps.item.storage !== code) {
emit('storagechanged', code) emit('storagechanged', code)
} }
} }
@@ -147,7 +147,7 @@ defineExpose({
</script> </script>
<template> <template>
<VToolbar flat dense class="rounded-t-lg border-b overflow-hidden"> <VToolbar flat dense class="file-browser-toolbar rounded-t-lg border-b overflow-hidden" data-glass-optical-surface>
<VToolbarItems class="overflow-hidden"> <VToolbarItems class="overflow-hidden">
<VMenu v-if="storages?.length || 0 > 1" offset-y> <VMenu v-if="storages?.length || 0 > 1" offset-y>
<template #activator="{ props }"> <template #activator="{ props }">
@@ -43,6 +43,18 @@ describe('glass overlay material styles', () => {
expect(styles).toMatch(/\.layout-vertical-nav \.ps__rail-y\s*\{[\s\S]*?inset-inline-end:\s*0\.5rem !important;/) 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', () => {
const styles = readFileSync(resolve(cwd(), 'src/styles/themes/glass.scss'), 'utf8')
expect(styles).toContain('--glass-navbar-scrolled-backdrop-filter: blur(3px) saturate(115%)')
expect(styles).toMatch(
/:is\(\[data-glass-appearance='clear'\], \[data-glass-appearance='tinted'\]\)[\s\S]*?\.layout-wrapper\.window-scrolled\.layout-navbar-fixed \.layout-navbar,[\s\S]*?backdrop-filter:\s*var\(--glass-navbar-scrolled-backdrop-filter\)\s*!important;/,
)
expect(styles).toMatch(
/\[data-glass-appearance='frosted'\][\s\S]*?\.layout-wrapper\.window-scrolled\.layout-navbar-fixed \.layout-navbar,[\s\S]*?\.layout-horizontal-nav-scrolled[\s\S]*?backdrop-filter:\s*var\(--glass-navbar-scrolled-backdrop-filter\)\s*!important;/,
)
})
it('uses the shared hover-card contract instead of a Dashboard-specific shadow rule', () => { it('uses the shared hover-card contract instead of a Dashboard-specific shadow rule', () => {
const styles = readFileSync(resolve(cwd(), 'src/styles/themes/glass.scss'), 'utf8') const styles = readFileSync(resolve(cwd(), 'src/styles/themes/glass.scss'), 'utf8')
@@ -71,12 +83,21 @@ describe('glass overlay material styles', () => {
expect(styles).toContain('--glass-native-surface-backdrop-filter') expect(styles).toContain('--glass-native-surface-backdrop-filter')
expect(styles).toContain('blur(calc(16px * var(--glass-frost-blur-scale, 1))) saturate(162%)') expect(styles).toContain('blur(calc(16px * var(--glass-frost-blur-scale, 1))) saturate(162%)')
expect(styles).toContain('blur(calc(10px * var(--glass-frost-blur-scale, 1))) saturate(154%)') expect(styles).toContain('blur(calc(10px * var(--glass-frost-blur-scale, 1))) saturate(154%)')
expect(styles).toMatch(
/\[data-glass-appearance='frosted'\][\s\S]*?\[data-glass-renderer-state='ready'\]\s*\{[\s\S]*?--glass-surface-backdrop-filter:\s*var\(--glass-native-surface-backdrop-filter\);/,
)
expect(styles).toMatch( expect(styles).toMatch(
/\[data-glass-scroll-presentation='native'\][\s\S]*?\.glass-optical-layer--scroll\s*\{\s*opacity:\s*0\s*!important;/, /\[data-glass-scroll-presentation='native'\][\s\S]*?\.glass-optical-layer--scroll\s*\{\s*opacity:\s*0\s*!important;/,
) )
expect(styles).toMatch( expect(styles).toMatch(
/\[data-glass-renderer-state='ready'\][\s\S]*?\.app-hover-lift-card:not\(\.media-card--image-loaded\)[\s\S]*?backdrop-filter:\s*var\(--glass-native-surface-backdrop-filter\)\s*!important;/, /\[data-glass-renderer-state='ready'\][\s\S]*?\.app-hover-lift-card:not\(\.media-card--image-loaded\)[\s\S]*?backdrop-filter:\s*var\(--glass-native-surface-backdrop-filter\)\s*!important;/,
) )
expect(styles).toMatch(
/\.settings-section-card\.app-grouped-list\s*\{[\s\S]*?backdrop-filter:\s*var\(--glass-native-surface-backdrop-filter\)\s*!important;/,
)
expect(styles).toMatch(
/\.file-browser-toolbar\.v-toolbar\s*\{[\s\S]*?backdrop-filter:\s*var\(--glass-surface-backdrop-filter\)\s*!important;/,
)
expect(styles).not.toMatch( expect(styles).not.toMatch(
/\[data-glass-scroll-presentation='native'\][\s\S]*?:where\([\s\S]*?--glass-native-surface-backdrop-filter/, /\[data-glass-scroll-presentation='native'\][\s\S]*?:where\([\s\S]*?--glass-native-surface-backdrop-filter/,
) )
+25 -15
View File
@@ -49,6 +49,7 @@ html[data-theme='glass'] {
--glass-control-backdrop-filter: none; --glass-control-backdrop-filter: none;
--glass-control-prominent-backdrop-filter: none; --glass-control-prominent-backdrop-filter: none;
--glass-navbar-backdrop-filter: var(--glass-raised-backdrop-filter); --glass-navbar-backdrop-filter: var(--glass-raised-backdrop-filter);
--glass-navbar-scrolled-backdrop-filter: blur(3px) saturate(115%);
--glass-overlay-surface: rgba(11, 19, 34, calc(0.1 + var(--glass-surface-density, 0.62) * 0.22)); --glass-overlay-surface: rgba(11, 19, 34, calc(0.1 + var(--glass-surface-density, 0.62) * 0.22));
--glass-overlay-blur: 3px; --glass-overlay-blur: 3px;
--glass-overlay-saturate: 115%; --glass-overlay-saturate: 115%;
@@ -623,17 +624,19 @@ html[data-theme='glass'] {
transform: none; transform: none;
} }
// 透明材质在内容上滚后复用移动底栏材质,顶部时保持原有透光感。 // 透明与色调材质在内容上滚后增强顶栏表面,顶部时保持原有透光感。
&[data-glass-appearance='clear'] { &:is([data-glass-appearance='clear'], [data-glass-appearance='tinted']) {
.layout-wrapper.window-scrolled.layout-navbar-fixed .layout-navbar, .layout-wrapper.window-scrolled.layout-navbar-fixed .layout-navbar,
.layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed .layout-navbar { .layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed .layout-navbar {
border-color: var(--glass-border-raised) !important; border-color: var(--glass-border-raised) !important;
-webkit-backdrop-filter: var(--glass-overlay-backdrop-filter) !important; -webkit-backdrop-filter: var(--glass-navbar-scrolled-backdrop-filter) !important;
backdrop-filter: var(--glass-overlay-backdrop-filter) !important; backdrop-filter: var(--glass-navbar-scrolled-backdrop-filter) !important;
background-color: var(--glass-overlay-surface) !important; background-color: var(--glass-overlay-surface) !important;
background-image: var(--glass-sheen) !important; background-image: var(--glass-sheen) !important;
} }
}
&[data-glass-appearance='clear'] {
// contained navbar 会把 %blurry-bg 扩展到内部容器,透明材质不生成这层滚动磨砂。 // contained navbar 会把 %blurry-bg 扩展到内部容器,透明材质不生成这层滚动磨砂。
.navbar-blur.layout-navbar .navbar-content-container::before { .navbar-blur.layout-navbar .navbar-content-container::before {
display: none !important; display: none !important;
@@ -941,6 +944,12 @@ html[data-theme='glass'] {
// “更多”应用列表的分组卡片存在局部固定模糊,需要在完整小屏区间跟随玻璃材质。 // “更多”应用列表的分组卡片存在局部固定模糊,需要在完整小屏区间跟随玻璃材质。
.settings-section-card.app-grouped-list { .settings-section-card.app-grouped-list {
-webkit-backdrop-filter: var(--glass-native-surface-backdrop-filter) !important;
backdrop-filter: var(--glass-native-surface-backdrop-filter) !important;
}
// 文件地址栏与下方内容卡属于同一工作表面,不使用更强的 raised 材质。
.file-browser-toolbar.v-toolbar {
-webkit-backdrop-filter: var(--glass-surface-backdrop-filter) !important; -webkit-backdrop-filter: var(--glass-surface-backdrop-filter) !important;
backdrop-filter: var(--glass-surface-backdrop-filter) !important; backdrop-filter: var(--glass-surface-backdrop-filter) !important;
} }
@@ -1187,7 +1196,7 @@ html[data-glass-renderer-state='ready'] .app-wrapper--login-glass-high .glass-op
opacity: 1; opacity: 1;
} }
// 光学档位下顶栏滚动前后共用同一 filter,避免滚动态重新叠加高强度模糊 // 光学档位先交由 renderer 接管标准表面;各材质在后续规则恢复必要的原生背板
html[data-theme='glass']:is( html[data-theme='glass']:is(
[data-glass-quality='balanced'], [data-glass-quality='balanced'],
[data-glass-quality='high'] [data-glass-quality='high']
@@ -1202,6 +1211,8 @@ html[data-theme='glass'][data-glass-appearance='frosted']:is(
[data-glass-quality='balanced'], [data-glass-quality='balanced'],
[data-glass-quality='high'] [data-glass-quality='high']
)[data-glass-renderer-state='ready'] { )[data-glass-renderer-state='ready'] {
// 标准表面始终保留稳定磨砂基底;renderer 只叠加折射与交互动态,静态页面也遵守同一材质契约。
--glass-surface-backdrop-filter: var(--glass-native-surface-backdrop-filter);
--glass-navbar-backdrop-filter: none; --glass-navbar-backdrop-filter: none;
} }
@@ -1219,7 +1230,7 @@ html:is([data-glass-quality='balanced'], [data-glass-quality='high'])[data-glass
} }
} }
// 磨砂材质的散射由 renderer 统一完成,避免 CSS 再次模糊折射结果 // 磨砂顶栏在页面顶部不重复采样;内容上滚到其下方后仅补一层轻量原生磨砂以保护可读性
html[data-glass-appearance='frosted']:is( html[data-glass-appearance='frosted']:is(
[data-glass-quality='balanced'], [data-glass-quality='balanced'],
[data-glass-quality='high'] [data-glass-quality='high']
@@ -1230,20 +1241,19 @@ html[data-glass-appearance='frosted']:is(
-webkit-backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
backdrop-filter: none !important; backdrop-filter: none !important;
} }
.layout-wrapper.window-scrolled.layout-navbar-fixed .layout-navbar,
.layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed .layout-navbar {
-webkit-backdrop-filter: var(--glass-navbar-scrolled-backdrop-filter) !important;
backdrop-filter: var(--glass-navbar-scrolled-backdrop-filter) !important;
}
} }
// 滚动表面始终由原生 backdrop 持有壁纸基底;GPU 层只叠加局部动态折射。 // 滚动表面始终由原生 backdrop 持有壁纸基底;GPU 层只叠加局部动态折射。
html:is( html:is([data-glass-quality='balanced'], [data-glass-quality='high'])[data-glass-renderer-state='ready']
[data-glass-quality='balanced'],
[data-glass-quality='high']
)[data-glass-renderer-state='ready']
body[data-theme='glass'] { body[data-theme='glass'] {
.dashboard-grid-item-content > .dashboard-grid-auto-size > .dashboard-grid-content-measure > .v-card, .dashboard-grid-item-content > .dashboard-grid-auto-size > .dashboard-grid-content-measure > .v-card,
.dashboard-grid-item-content .dashboard-grid-item-content > .dashboard-grid-auto-size > .dashboard-grid-content-measure > :first-child > .v-card,
> .dashboard-grid-auto-size
> .dashboard-grid-content-measure
> :first-child
> .v-card,
[data-glass-optical-surface], [data-glass-optical-surface],
.app-hover-lift-card:not(.media-card--image-loaded) { .app-hover-lift-card:not(.media-card--image-loaded) {
-webkit-backdrop-filter: var(--glass-native-surface-backdrop-filter) !important; -webkit-backdrop-filter: var(--glass-native-surface-backdrop-filter) !important;