Fix code review issues: flash toast dedup, sidebar CSS, pricing card colors

- Fix duplicate flash-to-toast watchers by tracking last shown flash JSON
- Replace inline sidebar margin styles with CSS class-driven approach
- Fix navbar left position to respond to sidebar collapse via CSS nesting
- Replace hardcoded white colors in PricingCard with theme-aware classes

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

View File

@@ -150,10 +150,6 @@
align-items: center; align-items: center;
padding-inline: 24px; padding-inline: 24px;
transition: left $transition-base; transition: left $transition-base;
.app-sidebar--collapsed ~ .app-content-wrapper & {
left: $sidebar-collapsed-width;
}
} }
// Content wrapper // Content wrapper
@@ -165,8 +161,13 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.app-sidebar--collapsed ~ & { // Collapsed sidebar — class-driven from Vue
&--collapsed {
margin-left: $sidebar-collapsed-width; margin-left: $sidebar-collapsed-width;
.app-navbar {
left: $sidebar-collapsed-width;
}
} }
} }

View File

@@ -43,15 +43,15 @@ withDefaults(defineProps<Props>(), {
</VChip> </VChip>
<!-- Plan name --> <!-- Plan name -->
<h3 class="text-h6 font-weight-bold mb-2" style="color: #fff;">{{ name }}</h3> <h3 class="text-h6 font-weight-bold mb-2">{{ name }}</h3>
<p v-if="description" class="text-body-2 mb-4" style="color: rgba(255,255,255,0.6);"> <p v-if="description" class="text-body-2 text-medium-emphasis mb-4">
{{ description }} {{ description }}
</p> </p>
<!-- Price --> <!-- Price -->
<div class="mb-6"> <div class="mb-6">
<span class="text-h3 font-weight-bold" style="color: #fff;">{{ price }}</span> <span class="text-h3 font-weight-bold">{{ price }}</span>
<span class="text-body-2" style="color: rgba(255,255,255,0.5);">{{ period }}</span> <span class="text-body-2 text-medium-emphasis">{{ period }}</span>
</div> </div>
<!-- Features --> <!-- Features -->
@@ -63,14 +63,14 @@ withDefaults(defineProps<Props>(), {
> >
<VIcon <VIcon
:icon="feature.included ? 'tabler-check' : 'tabler-x'" :icon="feature.included ? 'tabler-check' : 'tabler-x'"
:color="feature.included ? '#10b981' : undefined" :color="feature.included ? 'success' : undefined"
:style="{ opacity: feature.included ? 1 : 0.3 }" :style="{ opacity: feature.included ? 1 : 0.3 }"
size="18" size="18"
class="me-3" class="me-3"
/> />
<span <span
class="text-body-2" class="text-body-2"
:style="{ color: feature.included ? 'rgba(255,255,255,0.8)' : 'rgba(255,255,255,0.35)' }" :class="feature.included ? '' : 'text-disabled'"
> >
{{ feature.text }} {{ feature.text }}
</span> </span>

View File

@@ -43,11 +43,15 @@ watch(sidebarCollapsed, (val) => {
}) })
const toastStore = useToastStore() const toastStore = useToastStore()
watch(() => page.props, () => { let lastFlash = ''
const flash = (page.props as unknown as PageProps).flash watch(() => (page.props as unknown as PageProps).flash, (flash) => {
if (flash?.success) toastStore.success(flash.success) if (!flash) return
if (flash?.error) toastStore.error(flash.error) const key = JSON.stringify(flash)
if (flash?.info) toastStore.info(flash.info) if (key === lastFlash) return
lastFlash = key
if (flash.success) toastStore.success(flash.success)
if (flash.error) toastStore.error(flash.error)
if (flash.info) toastStore.info(flash.info)
}, { immediate: true }) }, { immediate: true })
const paletteItems = computed(() => { const paletteItems = computed(() => {
@@ -73,7 +77,7 @@ const paletteItems = computed(() => {
<div <div
class="app-content-wrapper" class="app-content-wrapper"
:style="{ marginLeft: sidebarCollapsed ? '72px' : '260px' }" :class="{ 'app-content-wrapper--collapsed': sidebarCollapsed }"
> >
<AppTopNavbar <AppTopNavbar
@toggle-sidebar="mobileOpen = !mobileOpen" @toggle-sidebar="mobileOpen = !mobileOpen"

View File

@@ -41,13 +41,17 @@ watch(sidebarCollapsed, (val) => {
localStorage.setItem('ezscale-nav-collapsed', String(val)) localStorage.setItem('ezscale-nav-collapsed', String(val))
}) })
// Flash messages to toasts // Flash messages → toasts (track last shown to avoid duplicates)
const toastStore = useToastStore() const toastStore = useToastStore()
watch(() => page.props, () => { let lastFlash = ''
const flash = (page.props as unknown as PageProps).flash watch(() => (page.props as unknown as PageProps).flash, (flash) => {
if (flash?.success) toastStore.success(flash.success) if (!flash) return
if (flash?.error) toastStore.error(flash.error) const key = JSON.stringify(flash)
if (flash?.info) toastStore.info(flash.info) if (key === lastFlash) return
lastFlash = key
if (flash.success) toastStore.success(flash.success)
if (flash.error) toastStore.error(flash.error)
if (flash.info) toastStore.info(flash.info)
}, { immediate: true }) }, { immediate: true })
// Command palette items // Command palette items
@@ -74,7 +78,7 @@ const paletteItems = computed(() => {
<div <div
class="app-content-wrapper" class="app-content-wrapper"
:style="{ marginLeft: sidebarCollapsed ? '72px' : '260px' }" :class="{ 'app-content-wrapper--collapsed': sidebarCollapsed }"
> >
<AppTopNavbar <AppTopNavbar
@toggle-sidebar="mobileOpen = !mobileOpen" @toggle-sidebar="mobileOpen = !mobileOpen"