addded banner placeholder
This commit is contained in:
@@ -7,7 +7,11 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--color-surface);
|
||||
/* Match the last visible section on the home page (cream) so browser
|
||||
overscroll + any empty space below content blends with the banner
|
||||
instead of showing a seam. Design-system pages override with
|
||||
`bg-surface` on their own root wrapper, so they're unaffected. */
|
||||
background: var(--color-cream);
|
||||
color: var(--color-ink);
|
||||
font-family: var(--font-sans);
|
||||
line-height: 1.55;
|
||||
|
||||
@@ -30,6 +30,10 @@ const props = defineProps({
|
||||
default: 'cream',
|
||||
validator: (t) => ['cream', 'paper', 'brand'].includes(t),
|
||||
},
|
||||
/** Only affects the split variant. When true, the image sits on the left
|
||||
* and copy on the right from `lg` up. Mobile order is unchanged (image
|
||||
* on top, copy below) to preserve reading order. */
|
||||
reverse: { type: Boolean, default: false },
|
||||
})
|
||||
|
||||
defineEmits(['cta', 'secondary'])
|
||||
@@ -76,11 +80,17 @@ const layout = computed(() => {
|
||||
// `order-*` flips the stacking order below lg without changing DOM order.
|
||||
// On lg, let the grid stretch items to the row height and then `justify-center`
|
||||
// the copy column so its headline/CTA block sits at the image's vertical midpoint.
|
||||
// `reverse` swaps the desktop columns so the image sits on the left.
|
||||
return {
|
||||
root: 'grid gap-10 md:gap-14 lg:grid-cols-[1.05fr_1fr]',
|
||||
copy: 'order-2 lg:order-1 max-w-xl mx-auto lg:mx-0 items-center text-center lg:items-start lg:text-left lg:justify-center',
|
||||
root: props.reverse
|
||||
? 'grid gap-10 md:gap-14 lg:grid-cols-[1fr_1.05fr]'
|
||||
: 'grid gap-10 md:gap-14 lg:grid-cols-[1.05fr_1fr]',
|
||||
copy: [
|
||||
'order-2 max-w-xl mx-auto lg:mx-0 items-center text-center lg:justify-center',
|
||||
props.reverse ? 'lg:order-2 lg:items-start lg:text-left' : 'lg:order-1 lg:items-start lg:text-left',
|
||||
].join(' '),
|
||||
actions: 'justify-center lg:justify-start',
|
||||
media: 'order-1 lg:order-2',
|
||||
media: props.reverse ? 'order-1 lg:order-1' : 'order-1 lg:order-2',
|
||||
mediaSize: 'w-[221px] sm:w-[289px] md:w-[357px] lg:w-full lg:max-w-[442px]',
|
||||
}
|
||||
})
|
||||
|
||||
@@ -230,6 +230,13 @@ const de = {
|
||||
'ds.hero.headline.b': 'was glänzen soll.',
|
||||
'ds.hero.sub': 'Reinigt, backt und neutralisiert Gerüche. Die 250-g-Großpackung für den Haushalt, der sich auf das Original verlässt.',
|
||||
|
||||
// Home page – second-fold banner
|
||||
'home.banner.eyebrow': 'Vielseitig einsetzbar',
|
||||
'home.banner.headline.a': 'Ein Pulver,',
|
||||
'home.banner.headline.em': 'hundert Anwendungen',
|
||||
'home.banner.headline.b': 'im Haushalt.',
|
||||
'home.banner.sub': 'Vom Kuchen über das Bad bis zur Wäsche – Kaiser-Natron leistet überall still und zuverlässig seine Arbeit.',
|
||||
|
||||
// Search section
|
||||
'ds.search.title': 'Produktsuche',
|
||||
'ds.search.description': 'Suchknopf rechts in der Navbar (links der Sprachwahl) und links unten als Floating-Button auf dem Telefon. Klick öffnet ein Full-Screen-Overlay auf Mobilgeräten bzw. ein zentriertes Panel auf dem Desktop. Eingabefeld ist autofokussiert, Ergebnisliste aktualisiert sich beim Tippen, Pfeiltasten / Enter / Esc werden unterstützt.',
|
||||
@@ -507,6 +514,13 @@ const en = {
|
||||
'ds.hero.headline.b': 'that should shine.',
|
||||
'ds.hero.sub': 'Cleans, bakes, and neutralises odours. The 250 g large pack for the household that trusts the original.',
|
||||
|
||||
// Home page – second-fold banner
|
||||
'home.banner.eyebrow': 'Truly versatile',
|
||||
'home.banner.headline.a': 'One powder,',
|
||||
'home.banner.headline.em': 'a hundred uses',
|
||||
'home.banner.headline.b': 'around the home.',
|
||||
'home.banner.sub': 'From baking to bathing to laundry — Kaiser Natron quietly does its work wherever you need it.',
|
||||
|
||||
'ds.search.title': 'Product search',
|
||||
'ds.search.description': 'Search trigger on the right of the navbar (left of the language switcher) and bottom-left as a floating button on mobile. Tapping it opens a full-screen overlay on mobile and a centered panel on desktop. The input auto-focuses, the results list updates as you type, and arrow keys / Enter / Esc are supported.',
|
||||
'ds.search.demo.label': 'Open demo',
|
||||
|
||||
@@ -22,11 +22,21 @@ const imgPulver250 =
|
||||
|
||||
const heroProductId = 'kaiser-natron-pulver-250-g-grosspackung'
|
||||
|
||||
// Second-fold banner — cream tone, image-left split, alternate cutout.
|
||||
const imgBanner =
|
||||
'/products/cutouts/kaiser-natron-pulver-250-g-gro%C3%9Fpackung-removebg-preview%20%281%29.png'
|
||||
const bannerProductId = 'kaiser-natron-pulver-250-g-grosspackung'
|
||||
|
||||
async function onHeroAdd() {
|
||||
await addToCart(heroProductId, 1)
|
||||
cartOpen.value = true
|
||||
}
|
||||
|
||||
async function onBannerAdd() {
|
||||
await addToCart(bannerProductId, 1)
|
||||
cartOpen.value = true
|
||||
}
|
||||
|
||||
async function onQty({ productId, quantity }) {
|
||||
await updateCartItem(productId, quantity)
|
||||
}
|
||||
@@ -84,8 +94,57 @@ onMounted(() => {
|
||||
</template>
|
||||
</Hero>
|
||||
</div>
|
||||
|
||||
<!-- Wave divider from brand-green → cream. Fill uses the next
|
||||
section's background so the curve reads as the bottom edge of
|
||||
the green fold. `preserveAspectRatio="none"` lets the SVG
|
||||
stretch across any viewport width while keeping a consistent
|
||||
vertical amplitude. -->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="block w-full h-12 md:h-16 shrink-0"
|
||||
viewBox="0 0 1440 64"
|
||||
preserveAspectRatio="none"
|
||||
>
|
||||
<path
|
||||
d="M0,40 C320,4 520,60 720,32 C920,4 1120,60 1440,24 L1440,64 L0,64 Z"
|
||||
fill="var(--color-cream)"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- Second-fold product banner — same Hero component, cream surface,
|
||||
split layout reversed so the product sits on the left. -->
|
||||
<Hero
|
||||
variant="split"
|
||||
tone="cream"
|
||||
reverse
|
||||
:eyebrow="t('home.banner.eyebrow')"
|
||||
:subheadline="t('home.banner.sub')"
|
||||
:image="imgBanner"
|
||||
image-alt="Kaiser-Natron Pulver 250 g Großpackung"
|
||||
:cta-label="t('ds.buttons.addToCart')"
|
||||
:secondary-label="t('ds.buttons.learnMore')"
|
||||
secondary-href="/anwendungen"
|
||||
@cta="onBannerAdd"
|
||||
>
|
||||
<template #headline>
|
||||
{{ t('home.banner.headline.a') }}
|
||||
<em class="italic font-light text-brand-soft">{{ t('home.banner.headline.em') }}</em>
|
||||
{{ t('home.banner.headline.b') }}
|
||||
</template>
|
||||
</Hero>
|
||||
|
||||
<!-- Bottom clearance for the mobile floating cluster (search / cart / menu).
|
||||
Cluster sits at bottom-5 (20px) + safe-area, is 56px tall, and needs a
|
||||
24px breathing gap above it: 20 + 56 + 24 = 100px, plus the device's
|
||||
safe-area inset. Desktop hides the cluster, so no spacer there. -->
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="md:hidden"
|
||||
style="height: calc(100px + env(safe-area-inset-bottom));"
|
||||
/>
|
||||
|
||||
<CartDrawer
|
||||
v-model="cartOpen"
|
||||
:items="cart.items"
|
||||
|
||||
@@ -14,10 +14,16 @@ const variant = computed(() =>
|
||||
const tone = computed(() =>
|
||||
['cream', 'paper', 'brand'].includes(route.query.tone) ? route.query.tone : 'cream',
|
||||
)
|
||||
const reverse = computed(() => route.query.reverse === '1')
|
||||
|
||||
const navVariant = computed(() => (tone.value === 'brand' ? 'brand' : tone.value))
|
||||
const imgPulver250 =
|
||||
'/products/cutouts/kaiser-natron-pulver-250-g-gro%C3%9Fpackung-removebg-preview-2.png'
|
||||
const imgBad = '/products/kaiser-natron-bad-500-g.jpg'
|
||||
const image = computed(() => (reverse.value ? imgBad : imgPulver250))
|
||||
const imageAlt = computed(() =>
|
||||
reverse.value ? 'Kaiser-Natron Bad 500 g' : 'Kaiser-Natron Pulver 250 g Großpackung',
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -26,18 +32,26 @@ const imgPulver250 =
|
||||
<Hero
|
||||
:variant="variant"
|
||||
:tone="tone"
|
||||
:eyebrow="t('ds.hero.eyebrow')"
|
||||
:subheadline="t('ds.hero.sub')"
|
||||
:image="imgPulver250"
|
||||
image-alt="Kaiser-Natron Pulver 250 g Großpackung"
|
||||
:badge="t('ds.badges.featured')"
|
||||
:reverse="reverse"
|
||||
:eyebrow="reverse ? t('home.banner.eyebrow') : t('ds.hero.eyebrow')"
|
||||
:subheadline="reverse ? t('home.banner.sub') : t('ds.hero.sub')"
|
||||
:image="image"
|
||||
:image-alt="imageAlt"
|
||||
:badge="reverse ? '' : t('ds.badges.featured')"
|
||||
:cta-label="t('ds.buttons.addToCart')"
|
||||
:secondary-label="t('ds.buttons.learnMore')"
|
||||
>
|
||||
<template #headline>
|
||||
{{ t('ds.hero.headline.a') }}
|
||||
<em class="italic font-light text-brand-soft">{{ t('ds.hero.headline.em') }}</em>
|
||||
{{ t('ds.hero.headline.b') }}
|
||||
<template v-if="reverse">
|
||||
{{ t('home.banner.headline.a') }}
|
||||
<em class="italic font-light text-brand-soft">{{ t('home.banner.headline.em') }}</em>
|
||||
{{ t('home.banner.headline.b') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ t('ds.hero.headline.a') }}
|
||||
<em class="italic font-light text-brand-soft">{{ t('ds.hero.headline.em') }}</em>
|
||||
{{ t('ds.hero.headline.b') }}
|
||||
</template>
|
||||
</template>
|
||||
</Hero>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user