diff --git a/src/@core/components/ThemeSwitcher.vue b/src/@core/components/ThemeSwitcher.vue index d4cbdf58..0f43d52a 100644 --- a/src/@core/components/ThemeSwitcher.vue +++ b/src/@core/components/ThemeSwitcher.vue @@ -18,10 +18,12 @@ const { name: themeName, global: globalTheme } = useTheme() const savedTheme = ref(localStorage.getItem('theme') ?? themeName) -const { state: currentThemeName, next: getNextThemeName } = useCycleList( - props.themes.map(t => t.name), - { initialValue: savedTheme.value }, -) +const currentThemeName = ref(savedTheme.value) +const getNextThemeName = () => { + const currentIndex = props.themes.findIndex(t => t.name === currentThemeName.value) + const nextIndex = (currentIndex + 1) % props.themes.length + return props.themes[nextIndex].name +} const $toast = useToast() @@ -187,25 +189,47 @@ onMounted(() => { - diff --git a/src/@core/scss/base/_default-layout-w-vertical-nav.scss b/src/@core/scss/base/_default-layout-w-vertical-nav.scss index d8e72477..bb94a28f 100644 --- a/src/@core/scss/base/_default-layout-w-vertical-nav.scss +++ b/src/@core/scss/base/_default-layout-w-vertical-nav.scss @@ -18,6 +18,9 @@ $header: ".layout-navbar"; // Add transition #{$header} { transition: padding 0.2s ease, background-color 0.18s ease; + @extend %default-layout-vertical-nav-scrolled-sticky-elevated-nav; + @extend %default-layout-vertical-nav-floating-navbar-and-sticky-elevated-navbar-scrolled; + margin-bottom: 16px; } // If navbar is contained => Add border radius to header @@ -27,21 +30,20 @@ $header: ".layout-navbar"; } } - // Scrolled styles for sticky navbar + .navbar-blur#{$header} { + @extend %blurry-bg; + } + + // Scrolled styles for sticky navbar (保留原有逻辑,但现在默认就会显示) @at-root { - /* ℹ️ This html selector with not selector is required when: - dialog is opened and window don't have any scroll. This removes window-scrolled class from layout and out style broke - */ html.v-overlay-scroll-blocked:not([style*="--v-body-scroll-y: 0px;"]) .layout-navbar-fixed, &.window-scrolled.layout-navbar-fixed { - #{$header} { - @extend %default-layout-vertical-nav-scrolled-sticky-elevated-nav; - @extend %default-layout-vertical-nav-floating-navbar-and-sticky-elevated-navbar-scrolled; + // 原有样式已在上面默认应用 } .navbar-blur#{$header} { - @extend %blurry-bg; + // 原有样式已在上面默认应用 } } } @@ -56,19 +58,12 @@ $header: ".layout-navbar"; } } - &:not(.layout-navbar-fixed) { - #{$header} { - margin-block-start: variables.$vertical-nav-floating-navbar-top; - } - } - #{$header} { @if variables.$layout-vertical-nav-navbar-is-contained { border-radius: variables.$default-layout-with-vertical-nav-navbar-footer-roundness; } background-color: rgb(var(--v-theme-surface)); - @extend %default-layout-vertical-nav-floating-navbar-and-sticky-elevated-navbar-scrolled; } diff --git a/src/@core/scss/base/_variables.scss b/src/@core/scss/base/_variables.scss index 7c973422..0484725a 100644 --- a/src/@core/scss/base/_variables.scss +++ b/src/@core/scss/base/_variables.scss @@ -40,7 +40,7 @@ $theme-colors-name: ( $default-layout-with-vertical-nav-navbar-footer-roundness: 10px !default; // 👉 Vertical nav -$vertical-nav-background-color-rgb: var(--v-theme-background) !default; +$vertical-nav-background-color-rgb: var(--v-theme-surface) !default; $vertical-nav-background-color: rgb(#{$vertical-nav-background-color-rgb}) !default; // ℹ️ This is used to keep consistency between nav items and nav header left & right margin diff --git a/src/@core/scss/base/_vertical-nav.scss b/src/@core/scss/base/_vertical-nav.scss index 343ce52f..682b111c 100644 --- a/src/@core/scss/base/_vertical-nav.scss +++ b/src/@core/scss/base/_vertical-nav.scss @@ -19,7 +19,7 @@ } } - background-color: variables.$vertical-nav-background-color; + background-color: rgb(var(--v-theme-surface)) !important; // 👉 Nav header .nav-header { @@ -60,9 +60,9 @@ z-index: 1; background: linear-gradient( - rgb(#{variables.$vertical-nav-background-color-rgb}) 5%, - rgba(#{variables.$vertical-nav-background-color-rgb}, 75%) 45%, - rgba(#{variables.$vertical-nav-background-color-rgb}, 20%) 80%, + rgb(var(--v-theme-surface)) 5%, + rgba(var(--v-theme-surface), 75%) 45%, + rgba(var(--v-theme-surface), 20%) 80%, transparent ); block-size: 55px; diff --git a/src/@core/scss/base/placeholders/_default-layout-vertical-nav.scss b/src/@core/scss/base/placeholders/_default-layout-vertical-nav.scss index 0f62c5d1..1d0b606e 100644 --- a/src/@core/scss/base/placeholders/_default-layout-vertical-nav.scss +++ b/src/@core/scss/base/placeholders/_default-layout-vertical-nav.scss @@ -4,10 +4,13 @@ %default-layout-vertical-nav-scrolled-sticky-elevated-nav { background-color: rgb(var(--v-theme-surface)); + border-radius: 12px; + margin: 8px 8px 8px 0; } %default-layout-vertical-nav-floating-navbar-and-sticky-elevated-navbar-scrolled { @include mixins.elevation(variables.$vertical-nav-navbar-elevation); + box-shadow: 0 4px 16px rgba(var(--v-theme-on-surface), 0.08); // If navbar is contained => Squeeze navbar content on scroll @if variables.$layout-vertical-nav-navbar-is-contained { diff --git a/src/@core/scss/template/_placeholders.scss b/src/@core/scss/template/_placeholders.scss new file mode 100644 index 00000000..9b408a42 --- /dev/null +++ b/src/@core/scss/template/_placeholders.scss @@ -0,0 +1,17 @@ +// 更新顶栏浮动风格的样式,增强豆腐块效果 +%default-layout-vertical-nav-floating-navbar-and-sticky-elevated-navbar-scrolled { + padding-block: 0.7rem; + background-color: rgb(var(--v-theme-surface)); + box-shadow: 0 4px 16px rgba(var(--v-theme-on-surface), 0.06) !important; + border-radius: 12px; + margin: 8px 8px 0 0; + width: 100%; + z-index: 10; + position: relative; +} + +// 更新毛玻璃背景效果 +%blurry-bg { + background-color: rgba(var(--v-theme-surface), 0.9) !important; + backdrop-filter: blur(6px); +} \ No newline at end of file diff --git a/src/@layouts/components/VerticalNav.vue b/src/@layouts/components/VerticalNav.vue index c7ccc76a..93001b78 100644 --- a/src/@layouts/components/VerticalNav.vue +++ b/src/@layouts/components/VerticalNav.vue @@ -98,6 +98,11 @@ function handleNavScroll(evt: Event) { transition: transform 0.25s ease-in-out, inline-size 0.25s ease-in-out, box-shadow 0.25s ease-in-out; visibility: hidden; will-change: transform, inline-size; + background-color: rgb(var(--v-theme-surface)); + box-shadow: 0 2px 8px rgba(var(--v-theme-on-surface), 0.08); + border-radius: 0 8px 8px 0; + margin: 8px 0 8px 8px; + max-height: calc(100% - 16px); &:not(.overlay-nav) { visibility: visible; diff --git a/src/@layouts/components/VerticalNavLayout.vue b/src/@layouts/components/VerticalNavLayout.vue index 6d6c8ce3..12d0e295 100644 --- a/src/@layouts/components/VerticalNavLayout.vue +++ b/src/@layouts/components/VerticalNavLayout.vue @@ -116,7 +116,7 @@ export default defineComponent({ .layout-navbar { position: fixed; - width: calc(100vw - variables.$layout-vertical-nav-width - 0.5rem); + width: calc(100vw - variables.$layout-vertical-nav-width - 1rem); z-index: variables.$layout-vertical-nav-layout-navbar-z-index; inset-block-start: 0; @@ -171,7 +171,7 @@ export default defineComponent({ } &:not(.layout-overlay-nav) .layout-content-wrapper { - padding-inline-start: variables.$layout-vertical-nav-width; + padding-inline-start: calc(variables.$layout-vertical-nav-width + 8px); } // Adjust right column pl when vertical nav is collapsed @@ -203,7 +203,16 @@ export default defineComponent({ .layout-wrapper.layout-nav-type-vertical.layout-overlay-nav { .layout-navbar { - width: 100%; + width: calc(100% - 0px); + margin-left: 8px; + padding-left: 0; } } + +.layout-page-content { + margin-top: calc(variables.$layout-vertical-nav-navbar-height - 42px); + padding-top: 0px; + position: relative; + z-index: 1; +} \ No newline at end of file diff --git a/src/@layouts/components/VerticalNavLink.vue b/src/@layouts/components/VerticalNavLink.vue index 2bcb7fa4..eae5ac64 100644 --- a/src/@layouts/components/VerticalNavLink.vue +++ b/src/@layouts/components/VerticalNavLink.vue @@ -9,7 +9,7 @@ defineProps<{ + + diff --git a/src/styles/styles.scss b/src/styles/styles.scss index 9f409536..f0b5cb82 100644 --- a/src/styles/styles.scss +++ b/src/styles/styles.scss @@ -261,22 +261,19 @@ html.v-overlay-scroll-blocked body { } .v-overlay__content .v-list{ - /* stylelint-disable-next-line property-no-vendor-prefix */ - -webkit-backdrop-filter: blur(6px); - backdrop-filter: blur(6px); - background-color: rgb(var(--v-theme-surface), 0.9) !important; + background-color: rgb(var(--v-theme-surface)) !important; + border-radius: 8px !important; + box-shadow: none !important; + padding: 4px !important; + margin: 0 !important; } .v-overlay__content .v-card:not(.bg-primary){ - /* stylelint-disable-next-line property-no-vendor-prefix */ - -webkit-backdrop-filter: blur(8px); - backdrop-filter: blur(8px); - background-color: rgb(var(--v-theme-surface), 0.95) !important; + background-color: rgb(var(--v-theme-surface)) !important; + border-radius: 8px !important; + box-shadow: none !important; .v-list, .v-table { - /* stylelint-disable-next-line property-no-vendor-prefix */ - -webkit-backdrop-filter: none; - backdrop-filter: none; background-color: transparent !important; } } @@ -294,3 +291,73 @@ html.v-overlay-scroll-blocked body { content: ''; inset: 0; } + +/* 菜单项样式 */ +.v-list-item { + border-radius: 4px !important; + margin: 2px 0 !important; + transition: background-color 0.15s ease; +} + +.v-list-item:hover { + background-color: rgba(var(--v-theme-on-surface), 0.04) !important; +} + +/* 下拉菜单整体样式 */ +.v-menu > .v-overlay__content { + border-radius: 8px !important; + box-shadow: 0 4px 12px rgba(var(--v-theme-on-surface), 0.08) !important; + overflow: hidden; +} + +/* 通知弹窗样式 */ +.notification-menu .v-overlay__content { + border-radius: 8px !important; + box-shadow: 0 4px 12px rgba(var(--v-theme-on-surface), 0.08) !important; + overflow: hidden; +} + +/* 主题切换菜单样式 */ +.theme-menu .v-overlay__content { + border-radius: 8px !important; + box-shadow: 0 4px 12px rgba(var(--v-theme-on-surface), 0.08) !important; +} + +/* 用户菜单样式 */ +.user-menu .v-overlay__content { + border-radius: 8px !important; + box-shadow: 0 4px 12px rgba(var(--v-theme-on-surface), 0.08) !important; +} + +/* 菜单按钮交互效果 */ +.v-btn.v-btn--icon { + transition: opacity 0.15s ease; +} + +.v-btn.v-btn--icon:hover { + opacity: 0.85; +} + +/* 菜单弹出动画优化 */ +.v-overlay__content { + transition: opacity 0.2s ease !important; +} + +/* 菜单卡片和列表 */ +.v-overlay__content .v-list{ + background-color: rgb(var(--v-theme-surface)) !important; + border-radius: 8px !important; + box-shadow: none !important; + padding: 4px !important; + margin: 0 !important; +} + +.v-overlay__content .v-card:not(.bg-primary){ + background-color: rgb(var(--v-theme-surface)) !important; + border-radius: 8px !important; + box-shadow: none !important; + + .v-list, .v-table { + background-color: transparent !important; + } +}