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:
@@ -134,17 +134,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Top navbar
|
// Top navbar — theme-aware
|
||||||
.app-navbar {
|
.app-navbar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
left: $sidebar-width;
|
left: $sidebar-width;
|
||||||
height: $navbar-height;
|
height: $navbar-height;
|
||||||
background: rgba($dark-bg, 0.8);
|
background: rgba(var(--v-theme-surface), 0.8);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px);
|
||||||
-webkit-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;
|
z-index: $z-navbar;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -181,11 +181,11 @@
|
|||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Footer
|
// Footer — theme-aware
|
||||||
.app-footer {
|
.app-footer {
|
||||||
padding: 16px 24px;
|
padding: 16px 24px;
|
||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
color: rgba(255, 255, 255, 0.4);
|
color: rgba(var(--v-theme-on-surface), 0.4);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Glass morphism cards
|
// Glass morphism cards — theme-aware
|
||||||
.glass-card {
|
.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;
|
border-radius: $radius-lg;
|
||||||
transition: transform $transition-base, box-shadow $transition-base;
|
transition: transform $transition-base, box-shadow $transition-base;
|
||||||
|
|
||||||
@@ -52,9 +55,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animated gradient text
|
// Animated gradient text — theme-aware
|
||||||
.hero-gradient-text {
|
.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-size: 200% auto;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { onMounted } from 'vue'
|
||||||
import { useTheme } from 'vuetify'
|
import { useTheme } from 'vuetify'
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'ezscale-theme'
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const saved = localStorage.getItem(STORAGE_KEY)
|
||||||
|
if (saved === 'light' || saved === 'dark') {
|
||||||
|
theme.global.name.value = saved
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
function toggleTheme(): void {
|
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>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,16 @@ import { themes } from './theme'
|
|||||||
import 'vuetify/styles'
|
import 'vuetify/styles'
|
||||||
|
|
||||||
export default function installVuetify(app: App): void {
|
export default function installVuetify(app: App): void {
|
||||||
// Determine default theme based on subdomain
|
const saved = typeof window !== 'undefined' ? localStorage.getItem('ezscale-theme') : null
|
||||||
const hostname = typeof window !== 'undefined' ? window.location.hostname : ''
|
let defaultTheme: string
|
||||||
const isMarketing = !hostname.startsWith('account.') && !hostname.startsWith('admin.')
|
|
||||||
const defaultTheme = isMarketing ? 'light' : 'dark'
|
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({
|
const vuetify = createVuetify({
|
||||||
defaults,
|
defaults,
|
||||||
|
|||||||
Reference in New Issue
Block a user