fix(design-v2): side rail subtitle + footer signature + theme swatch harbor
CI / test (push) Has been cancelled
CI / test (push) Has been cancelled
Mockup vs live diff revealed: - Side rail brand area: mockup has italic '— home/library/settings' subtitle below WeVisto, live had none. Added via reactive activeSub computed. - Side rail footer: mockup has 'a frame, gifted · v 0.4' italic at the bottom of the rail. Added top-nav__foot element; hidden in horizontal layouts, shown in v2 side rail via design-v2.scss - Side rail mark size: bumped from 36px to 44px to match mockup - Theme swatch harbor preview wasn't winning the cascade fight against Vue scoped styles (equal-specificity tie, Vue cascades later). Adding !important on the few preview properties — v2 is opt-in so this is appropriate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,10 @@
|
||||
<header class="top-nav" aria-label="Main navigation">
|
||||
<RouterLink to="/" class="top-nav__brand">
|
||||
<span class="top-nav__mark"><img :src="markUrl" alt=""></span>
|
||||
<span class="top-nav__wordmark">WeVisto</span>
|
||||
<span class="top-nav__title-group">
|
||||
<span class="top-nav__wordmark">WeVisto</span>
|
||||
<span class="top-nav__sub">— {{ activeSub }}</span>
|
||||
</span>
|
||||
</RouterLink>
|
||||
<nav class="top-nav__tabs">
|
||||
<RouterLink
|
||||
@@ -20,6 +23,7 @@
|
||||
>{{ imagesStore.pendingCount > 9 ? '9+' : imagesStore.pendingCount }}</span>
|
||||
</RouterLink>
|
||||
</nav>
|
||||
<div class="top-nav__foot">a frame, gifted <span class="top-nav__foot-sep">·</span> v 0.4</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
@@ -27,10 +31,22 @@
|
||||
import { useRoute, type RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
import { useImagesStore } from '@/stores/images'
|
||||
|
||||
import { computed } from 'vue'
|
||||
|
||||
const route = useRoute()
|
||||
const imagesStore = useImagesStore()
|
||||
const markUrl = '/build/icons/apple-touch-icon.png'
|
||||
|
||||
// "— home" / "— library" / "— settings" subtitle on the brand area.
|
||||
// Matches the approved mockup; hidden at mobile/tablet via CSS.
|
||||
const activeSub = computed(() => {
|
||||
const p = route.path
|
||||
if (p.startsWith('/library')) return 'library'
|
||||
if (p.startsWith('/settings')) return 'settings'
|
||||
if (p.startsWith('/upload')) return 'add photograph'
|
||||
return 'home'
|
||||
})
|
||||
|
||||
interface Tab {
|
||||
name: string
|
||||
label: string
|
||||
@@ -96,6 +112,12 @@ const tabs: Tab[] = [
|
||||
}
|
||||
&__mark img { width: 100%; height: 100%; display: block; }
|
||||
|
||||
&__title-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
&__wordmark {
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 800;
|
||||
@@ -103,6 +125,29 @@ const tabs: Tab[] = [
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
// Italic subtitle "— home / library / settings" beside the wordmark.
|
||||
// Hidden at horizontal (mobile/tablet) layouts; v2 side rail shows it.
|
||||
&__sub {
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-muted);
|
||||
margin-top: 2px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
// Bottom-of-rail signature — only renders inside the side-rail layout
|
||||
// (positioned absolutely there). Hidden in the horizontal default state.
|
||||
&__foot {
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
color: var(--color-text-muted);
|
||||
text-align: center;
|
||||
padding: 16px 0 4px;
|
||||
border-top: 1px solid var(--color-border);
|
||||
}
|
||||
&__foot-sep { color: var(--brand-yellow, var(--color-primary)); }
|
||||
|
||||
&__tabs {
|
||||
display: flex;
|
||||
gap: var(--space-1);
|
||||
|
||||
@@ -39,8 +39,26 @@
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: 16px;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
align-items: flex-start;
|
||||
}
|
||||
&__mark {
|
||||
width: 44px !important;
|
||||
height: 44px !important;
|
||||
border-radius: 10px !important;
|
||||
}
|
||||
&__wordmark { font-size: var(--text-xl); font-family: var(--font-display-v2); font-weight: 400; }
|
||||
|
||||
&__sub {
|
||||
display: block;
|
||||
font-family: var(--font-accent-v2);
|
||||
}
|
||||
|
||||
&__foot {
|
||||
display: block;
|
||||
margin-top: auto;
|
||||
font-family: var(--font-accent-v2);
|
||||
border-top-color: var(--color-border);
|
||||
}
|
||||
&__wordmark { font-size: var(--text-xl); }
|
||||
|
||||
&__tabs {
|
||||
flex-direction: column;
|
||||
@@ -124,18 +142,22 @@
|
||||
.design-toggle__sub { color: var(--color-text-muted); }
|
||||
|
||||
// ── Theme swatches preview their dusk via the harbor.jpg ───────────
|
||||
// `!important` needed because Vue's scoped style on SettingsView
|
||||
// (.theme-swatch__preview[data-v-xxx] { background: var(--swatch-bg) })
|
||||
// ties on specificity and cascades later. v2 is opt-in so overriding is OK.
|
||||
.theme-swatch {
|
||||
border-color: var(--color-border);
|
||||
background: var(--color-surface);
|
||||
background: var(--color-surface) !important;
|
||||
color: var(--color-text);
|
||||
|
||||
&--active { border-color: var(--brand-yellow); }
|
||||
&__label { color: var(--color-text); }
|
||||
|
||||
&__preview {
|
||||
background-image: url('/build/assets/harbor.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background: transparent !important;
|
||||
background-image: url('/build/assets/harbor.jpg') !important;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
&::after {
|
||||
|
||||
Reference in New Issue
Block a user