From a07058d656219927a867cd8bb6642f3a6eb14ff2 Mon Sep 17 00:00:00 2001 From: Dorian Date: Tue, 21 Apr 2026 11:44:15 +0100 Subject: [PATCH] feat: add Hero component to design system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Responsive hero for home + category tops (390→1280px), composed from Button, Badge, and the Icon/Logo primitives already in the DS. - Two layouts — split (copy left / product right on lg, stacked below) and centered — and three surface tones — cream, paper, brand. On the brand-green surface the secondary CTA is rendered with a cream outline pill since Button's ghost/secondary variants read dark-on-dark there. - Decorative disc + soft glow behind the product cutout give the image a focal point without needing a photographed backdrop. - Headline can be passed as a string prop or as a slot (so consumers can mix in the italic `text-brand-soft` emphasis used on the home page). - Ships with a /design/hero showcase page that renders the component in the DevicePreview iframe across mobile / tablet / desktop, plus layout and tone tabs and a usage snippet. Preview route is /design/preview/hero so the iframe can include the live Navbar. - i18n keys added to DE + EN; AT inherits from DE. Co-Authored-By: Claude Opus 4.7 --- src/design-system/components/Hero.vue | 198 ++++++++++++++++++++++ src/i18n/messages.js | 25 +++ src/pages/design/DesignLayout.vue | 1 + src/pages/design/HeroSection.vue | 103 +++++++++++ src/pages/design/previews/HeroPreview.vue | 44 +++++ src/router/index.js | 7 + 6 files changed, 378 insertions(+) create mode 100644 src/design-system/components/Hero.vue create mode 100644 src/pages/design/HeroSection.vue create mode 100644 src/pages/design/previews/HeroPreview.vue diff --git a/src/design-system/components/Hero.vue b/src/design-system/components/Hero.vue new file mode 100644 index 0000000..160edc0 --- /dev/null +++ b/src/design-system/components/Hero.vue @@ -0,0 +1,198 @@ + + + diff --git a/src/i18n/messages.js b/src/i18n/messages.js index 194c593..81f5b6c 100644 --- a/src/i18n/messages.js +++ b/src/i18n/messages.js @@ -30,6 +30,7 @@ const de = { 'ds.nav.inputs': 'Eingabefelder', 'ds.nav.cards': 'Karten', 'ds.nav.products': 'Produktkarten', + 'ds.nav.hero': 'Hero', 'ds.nav.navbar': 'Navigation', 'ds.nav.language': 'Sprachwahl', @@ -176,6 +177,18 @@ const de = { 'ds.product.outOfStock': 'Nicht verfügbar', 'ds.product.added': 'Hinzugefügt', + // Hero + 'ds.hero.title': 'Hero', + 'ds.hero.description': 'Ganzflächiger Bühnenbereich für die Startseite und Kategorie-Auftakte. Eyebrow, Display-Headline mit optionaler Kursiv-Hervorhebung, Unterzeile, Produkt-Cutout auf dekorativer Scheibe und ein Primary/Secondary-CTA-Paar. Responsiv von 390 bis 1280 px, drei Flächen­töne, zwei Layouts.', + 'ds.hero.variant.label': 'Layout', + 'ds.hero.variant.split': 'Split', + 'ds.hero.variant.centered': 'Zentriert', + 'ds.hero.eyebrow': 'Neu im Shop', + 'ds.hero.headline.a': 'Kaiser-Natron', + 'ds.hero.headline.em': 'für alles', + '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.', + // Navbar section 'ds.navbar.title': 'Navigation', 'ds.navbar.description': 'Logo + Nav + Warenkorb, in drei Flächentönen. Auf Mobilgeräten behält die obere Leiste das Logo, Menü + Warenkorb wechseln in ein ergonomisches bodennahes rechtes Floating-Cluster. Das Menü öffnet ein vollflächiges markengrünes Overlay.', @@ -244,6 +257,7 @@ const en = { 'ds.nav.inputs': 'Inputs', 'ds.nav.cards': 'Cards', 'ds.nav.products': 'Product cards', + 'ds.nav.hero': 'Hero', 'ds.nav.navbar': 'Navbar', 'ds.nav.language': 'Language', @@ -377,6 +391,17 @@ const en = { 'ds.product.outOfStock': 'Out of stock', 'ds.product.added': 'Added', + 'ds.hero.title': 'Hero', + 'ds.hero.description': 'Full-bleed stage for the home page and category tops. Eyebrow, display headline with optional italic emphasis, subheadline, product cutout on a decorative disc, and a primary/secondary CTA pair. Responsive from 390 to 1280px, three surface tones, two layouts.', + 'ds.hero.variant.label': 'Layout', + 'ds.hero.variant.split': 'Split', + 'ds.hero.variant.centered': 'Centered', + 'ds.hero.eyebrow': 'New in shop', + 'ds.hero.headline.a': 'Kaiser Natron', + 'ds.hero.headline.em': 'for everything', + '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.', + 'ds.navbar.title': 'Navbar', 'ds.navbar.description': 'Logo + nav + cart, in three surface tones. On mobile, the top bar keeps the logo and the menu + cart move to an ergonomic bottom-right floating cluster. The menu opens a full-screen brand-green overlay.', 'ds.navbar.tone': 'Navbar tone', diff --git a/src/pages/design/DesignLayout.vue b/src/pages/design/DesignLayout.vue index 69ba554..eb924fb 100644 --- a/src/pages/design/DesignLayout.vue +++ b/src/pages/design/DesignLayout.vue @@ -32,6 +32,7 @@ const groups = computed(() => [ { name: 'ds-inputs', label: t('ds.nav.inputs') }, { name: 'ds-cards', label: t('ds.nav.cards') }, { name: 'ds-products', label: t('ds.nav.products') }, + { name: 'ds-hero', label: t('ds.nav.hero') }, { name: 'ds-navbar', label: t('ds.nav.navbar') }, { name: 'ds-language', label: t('ds.nav.language') }, ], diff --git a/src/pages/design/HeroSection.vue b/src/pages/design/HeroSection.vue new file mode 100644 index 0000000..f0c6abb --- /dev/null +++ b/src/pages/design/HeroSection.vue @@ -0,0 +1,103 @@ + + + diff --git a/src/pages/design/previews/HeroPreview.vue b/src/pages/design/previews/HeroPreview.vue new file mode 100644 index 0000000..df0afae --- /dev/null +++ b/src/pages/design/previews/HeroPreview.vue @@ -0,0 +1,44 @@ + + + diff --git a/src/router/index.js b/src/router/index.js index b1fb6b6..d5b9c8a 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -13,6 +13,12 @@ const routes = [ component: () => import('@/pages/design/previews/NavbarPreview.vue'), meta: { layout: 'none', preview: true }, }, + { + path: '/design/preview/hero', + name: 'ds-preview-hero', + component: () => import('@/pages/design/previews/HeroPreview.vue'), + meta: { layout: 'none', preview: true }, + }, { path: '/design', component: () => import('@/pages/design/DesignLayout.vue'), @@ -29,6 +35,7 @@ const routes = [ { path: 'inputs', name: 'ds-inputs', component: () => import('@/pages/design/InputsSection.vue') }, { path: 'cards', name: 'ds-cards', component: () => import('@/pages/design/CardsSection.vue') }, { path: 'products', name: 'ds-products', component: () => import('@/pages/design/ProductsSection.vue') }, + { path: 'hero', name: 'ds-hero', component: () => import('@/pages/design/HeroSection.vue') }, { path: 'navbar', name: 'ds-navbar', component: () => import('@/pages/design/NavbarSection.vue') }, { path: 'language', name: 'ds-language', component: () => import('@/pages/design/LanguageSwitcherSection.vue') }, { path: 'icons', name: 'ds-icons', component: () => import('@/pages/design/IconsSection.vue') },