Fix theme switcher persistence and hardcoded dark colors in SCSS

- ThemeSwitcher: save user's theme choice to localStorage and restore on mount
- Vuetify plugin: check localStorage before falling back to subdomain default
- _layouts.scss: make navbar and footer theme-aware using CSS custom properties
  (sidebar intentionally stays always-dark per design spec)
- _marketing.scss: make glass-card and hero-gradient-text theme-aware

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Dev
2026-03-14 17:24:51 -04:00
parent 65dcdebd5c
commit 9a12deeed3
4 changed files with 34 additions and 14 deletions

View File

@@ -134,17 +134,17 @@
}
}
// Top navbar
// Top navbar — theme-aware
.app-navbar {
position: fixed;
top: 0;
right: 0;
left: $sidebar-width;
height: $navbar-height;
background: rgba($dark-bg, 0.8);
background: rgba(var(--v-theme-surface), 0.8);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
border-bottom: 1px solid rgba(var(--v-theme-on-surface), 0.06);
z-index: $z-navbar;
display: flex;
align-items: center;
@@ -181,11 +181,11 @@
margin-inline: auto;
}
// Footer
// Footer — theme-aware
.app-footer {
padding: 16px 24px;
font-size: 0.8125rem;
color: rgba(255, 255, 255, 0.4);
color: rgba(var(--v-theme-on-surface), 0.4);
flex-shrink: 0;
}

View File

@@ -40,9 +40,12 @@
}
}
// Glass morphism cards
// Glass morphism cards — theme-aware
.glass-card {
@include glass-morphism(0.08, 20px);
background: rgba(var(--v-theme-surface), 0.6);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
border-radius: $radius-lg;
transition: transform $transition-base, box-shadow $transition-base;
@@ -52,9 +55,9 @@
}
}
// Animated gradient text
// Animated gradient text — theme-aware
.hero-gradient-text {
background: linear-gradient(135deg, $primary-light 0%, $info 50%, $primary-light 100%);
background: linear-gradient(135deg, rgb(var(--v-theme-primary)) 0%, $info 50%, rgb(var(--v-theme-primary)) 100%);
background-size: 200% auto;
background-clip: text;
-webkit-background-clip: text;

View File

@@ -1,10 +1,21 @@
<script lang="ts" setup>
import { onMounted } from 'vue'
import { useTheme } from 'vuetify'
const STORAGE_KEY = 'ezscale-theme'
const theme = useTheme()
onMounted(() => {
const saved = localStorage.getItem(STORAGE_KEY)
if (saved === 'light' || saved === 'dark') {
theme.global.name.value = saved
}
})
function toggleTheme(): void {
theme.global.name.value = theme.global.current.value.dark ? 'light' : 'dark'
const next = theme.global.current.value.dark ? 'light' : 'dark'
theme.global.name.value = next
localStorage.setItem(STORAGE_KEY, next)
}
</script>

View File

@@ -7,10 +7,16 @@ import { themes } from './theme'
import 'vuetify/styles'
export default function installVuetify(app: App): void {
// Determine default theme based on subdomain
const hostname = typeof window !== 'undefined' ? window.location.hostname : ''
const isMarketing = !hostname.startsWith('account.') && !hostname.startsWith('admin.')
const defaultTheme = isMarketing ? 'light' : 'dark'
const saved = typeof window !== 'undefined' ? localStorage.getItem('ezscale-theme') : null
let defaultTheme: string
if (saved === 'light' || saved === 'dark') {
defaultTheme = saved
} else {
const hostname = typeof window !== 'undefined' ? window.location.hostname : ''
const isMarketing = !hostname.startsWith('account.') && !hostname.startsWith('admin.')
defaultTheme = isMarketing ? 'light' : 'dark'
}
const vuetify = createVuetify({
defaults,