brand hero: render i18n calls reactively

Hero copy was reading translations via const = t('key') in setup,
which captures the string at first paint and never updates when the
user switches locale. Calls now happen inline in the template so
Vue's reactivity system tracks state.locale access during render and
re-runs the binding when DE/AT/EN flips.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-05-04 09:52:25 +01:00
parent 8bc18edaf6
commit 97bda17c3d
6 changed files with 19 additions and 23 deletions

1
dist/assets/HomePage-CRHQMhVo.css vendored Normal file
View File

@@ -0,0 +1 @@
@property --hero-feather{syntax:"<percentage>";inherits:false;initial-value:12%}.brand-hero__svg--bg[data-v-f4c612f3]{--hero-feather:12%;-webkit-mask-image:linear-gradient(to right, transparent 0%, #000 var(--hero-feather), #000 calc(100% - var(--hero-feather)), transparent 100%);-webkit-mask-image:linear-gradient(to right, transparent 0%, #000 var(--hero-feather), #000 calc(100% - var(--hero-feather)), transparent 100%);mask-image:linear-gradient(to right, transparent 0%, #000 var(--hero-feather), #000 calc(100% - var(--hero-feather)), transparent 100%);transition:--hero-feather .7s 1.15s;display:block}.brand-hero.go .brand-hero__svg--bg[data-v-f4c612f3]{--hero-feather:0%}.brand-hero__svg--portrait[data-v-f4c612f3]{width:100%;height:auto;max-height:56svh;margin:0 auto;display:block}.left-m[data-v-f4c612f3],.right-m[data-v-f4c612f3]{fill:#b5d8b6}.mound-m[data-v-f4c612f3]{fill:#fff}.layer.left-m[data-v-f4c612f3]{opacity:0;transition:transform .8s cubic-bezier(.22,.61,.36,1) .15s,opacity .6s .15s;transform:translate(-14%)}.layer.right-m[data-v-f4c612f3]{opacity:0;transition:transform .8s cubic-bezier(.22,.61,.36,1) .15s,opacity .6s .15s;transform:translate(14%)}.layer.mound-m[data-v-f4c612f3]{opacity:0;transition:opacity .55s .7s}.brand-hero__copy[data-v-f4c612f3]{opacity:0;transition:opacity .7s 1.15s}.brand-hero.go .layer.left-m[data-v-f4c612f3],.brand-hero.go .layer.right-m[data-v-f4c612f3]{opacity:1;transform:none}.brand-hero.go .layer.mound-m[data-v-f4c612f3],.brand-hero.go .brand-hero__copy[data-v-f4c612f3]{opacity:1}@media (prefers-reduced-motion:reduce){.layer.left-m[data-v-f4c612f3],.layer.right-m[data-v-f4c612f3],.layer.mound-m[data-v-f4c612f3],.brand-hero__copy[data-v-f4c612f3]{opacity:1!important;transition:none!important;transform:none!important}}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
@property --hero-feather{syntax:"<percentage>";inherits:false;initial-value:12%}.brand-hero__svg--bg[data-v-e9619974]{--hero-feather:12%;-webkit-mask-image:linear-gradient(to right, transparent 0%, #000 var(--hero-feather), #000 calc(100% - var(--hero-feather)), transparent 100%);-webkit-mask-image:linear-gradient(to right, transparent 0%, #000 var(--hero-feather), #000 calc(100% - var(--hero-feather)), transparent 100%);mask-image:linear-gradient(to right, transparent 0%, #000 var(--hero-feather), #000 calc(100% - var(--hero-feather)), transparent 100%);transition:--hero-feather .7s 1.15s;display:block}.brand-hero.go .brand-hero__svg--bg[data-v-e9619974]{--hero-feather:0%}.brand-hero__svg--portrait[data-v-e9619974]{width:100%;height:auto;max-height:56svh;margin:0 auto;display:block}.left-m[data-v-e9619974],.right-m[data-v-e9619974]{fill:#b5d8b6}.mound-m[data-v-e9619974]{fill:#fff}.layer.left-m[data-v-e9619974]{opacity:0;transition:transform .8s cubic-bezier(.22,.61,.36,1) .15s,opacity .6s .15s;transform:translate(-14%)}.layer.right-m[data-v-e9619974]{opacity:0;transition:transform .8s cubic-bezier(.22,.61,.36,1) .15s,opacity .6s .15s;transform:translate(14%)}.layer.mound-m[data-v-e9619974]{opacity:0;transition:opacity .55s .7s}.brand-hero__copy[data-v-e9619974]{opacity:0;transition:opacity .7s 1.15s}.brand-hero.go .layer.left-m[data-v-e9619974],.brand-hero.go .layer.right-m[data-v-e9619974]{opacity:1;transform:none}.brand-hero.go .layer.mound-m[data-v-e9619974],.brand-hero.go .brand-hero__copy[data-v-e9619974]{opacity:1}@media (prefers-reduced-motion:reduce){.layer.left-m[data-v-e9619974],.layer.right-m[data-v-e9619974],.layer.mound-m[data-v-e9619974],.brand-hero__copy[data-v-e9619974]{opacity:1!important;transition:none!important;transform:none!important}}

File diff suppressed because one or more lines are too long

2
dist/index.html vendored
View File

@@ -12,7 +12,7 @@
href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,200;0,9..144,400;0,9..144,600;0,9..144,700;1,9..144,200;1,9..144,400;1,9..144,600&family=DM+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400&display=swap"
rel="stylesheet"
/>
<script type="module" crossorigin src="/assets/index-BU2-m5yd.js"></script>
<script type="module" crossorigin src="/assets/index-CdX6CEGk.js"></script>
<link rel="modulepreload" crossorigin href="/assets/preload-helper-ca-nBW7U.js">
<link rel="modulepreload" crossorigin href="/assets/runtime-core.esm-bundler-DTXUv7Wx.js">
<link rel="modulepreload" crossorigin href="/assets/runtime-dom.esm-bundler-CXLmyuFK.js">

View File

@@ -61,14 +61,14 @@
stays predictable across breakpoints. -->
<div class="brand-hero__copy flex w-1/2 items-center justify-start pl-4 md:pl-6 lg:pl-8">
<div class="w-full max-w-md xl:max-w-lg 2xl:max-w-xl text-left">
<p class="mb-4 md:mb-5 text-sm md:text-base tracking-label uppercase text-cream/75">{{ since }}</p>
<p class="mb-4 md:mb-5 text-sm md:text-base tracking-label uppercase text-cream/75">{{ t('home.brand.since') }}</p>
<h1 class="font-display font-normal leading-[1.06] tracking-tight text-cream text-[1.75rem] md:text-[2.25rem] lg:text-[2.5rem] xl:text-[2.75rem] 2xl:text-[3.25rem]">
{{ headlineA }}
<em class="italic font-light text-accent-soft">{{ headlineEm }}</em>
{{ headlineB }}
{{ t('home.brand.headline.a') }}
<em class="italic font-light text-accent-soft">{{ t('home.brand.headline.em') }}</em>
{{ t('home.brand.headline.b') }}
</h1>
<RouterLink to="/shop" class="mt-7 md:mt-8 inline-flex">
<Button variant="accent" size="lg">{{ shopLabel }}</Button>
<Button variant="accent" size="lg">{{ t('nav.shop') }}</Button>
</RouterLink>
</div>
</div>
@@ -98,13 +98,13 @@
<div class="brand-hero__copy flex flex-col items-center text-center">
<h1 class="max-w-3xl font-display font-normal leading-[1.08] tracking-tight text-cream text-[1.5rem] sm:text-[2rem]">
{{ headlineA }}
<em class="italic font-light text-accent-soft">{{ headlineEm }}</em>
{{ headlineB }}
{{ t('home.brand.headline.a') }}
<em class="italic font-light text-accent-soft">{{ t('home.brand.headline.em') }}</em>
{{ t('home.brand.headline.b') }}
</h1>
<p class="mt-4 text-[0.95rem] tracking-label uppercase text-cream/75">{{ since }}</p>
<p class="mt-4 text-[0.95rem] tracking-label uppercase text-cream/75">{{ t('home.brand.since') }}</p>
<RouterLink to="/shop" class="mt-6 inline-flex">
<Button variant="accent" size="lg">{{ shopLabel }}</Button>
<Button variant="accent" size="lg">{{ t('nav.shop') }}</Button>
</RouterLink>
</div>
</div>
@@ -154,15 +154,11 @@ onBeforeUnmount(() => {
}
})
// `t` is invoked inline in the template (not cached as setup
// constants) so the headline / SINCE 1881 / Shop button update
// reactively when the user switches locale via the navbar — calls
// resolved at setup time freeze the value at first paint.
const { t } = useI18n()
const headlineA = t('home.brand.headline.a')
const headlineEm = t('home.brand.headline.em')
const headlineB = t('home.brand.headline.b')
const since = t('home.brand.since')
// Reuses the navbar's "Shop" / "Shop" label — keeps the wording in
// step with the top-nav entry point so the user sees the same word
// for the same destination.
const shopLabel = t('nav.shop')
</script>
<style scoped>