mobile hero category wiring

This commit is contained in:
Dorian
2026-04-24 15:54:14 +01:00
parent cbc1a4e739
commit 55d2bd3dee
10 changed files with 55 additions and 69 deletions

File diff suppressed because one or more lines are too long

1
dist/assets/CartDrawer-C4QVm0QX.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
import{B as e,C as t,G as n,S as r,c as i,j as a,lt as o,m as s,p as c,s as l}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as u}from"./Icon-BCRRMV3J.js";import{t as d}from"./i18n-CH9FW6EE.js";import{a as f,i as p,n as m,o as h,r as g,t as _}from"./api-DbjChhCZ.js";import{t as v}from"./Button-DkdaDkuf.js";import{t as y}from"./CartDrawer-B6sAbDnc.js";import{t as b}from"./SectionShell-Cd_Fu3uI.js";var x={class:`eyebrow mb-5`},S={class:`rounded-md border border-line bg-paper p-6 flex flex-col sm:flex-row sm:items-center gap-4`},C={class:`text-[13px] text-muted`},w={class:`eyebrow mb-5`},T={class:`text-[15px] text-muted leading-relaxed mb-4 max-w-2xl`},E={class:`eyebrow mb-5`},D={__name:`CartDrawerSection`,setup(D){let{t:O}=d(),k=h(),A=e(!1);async function j(){await m(),await _(`kaiser-natron-pulver-250-g-grosspackung`,2),await _(`kaiser-natron-bad-500-g`,1),A.value=!0}async function M({productId:e,quantity:t}){await f(e,t)}async function N(e){await p(e)}return r(()=>{g()}),(e,r)=>(t(),i(b,{eyebrow:n(O)(`ds.eyebrow.components`),title:n(O)(`ds.cartDrawer.title`),description:n(O)(`ds.cartDrawer.description`)},{default:a(()=>[l(`section`,null,[l(`h2`,x,o(n(O)(`ds.heading.default`)),1),l(`div`,S,[s(v,{variant:`primary`,onClick:j},{before:a(()=>[s(u,{name:`cart`,size:18})]),default:a(()=>[c(` `+o(n(O)(`ds.cartDrawer.demoLabel`)),1)]),_:1}),l(`p`,C,o(n(O)(`ds.cartDrawer.demoHint`)),1)])]),l(`section`,null,[l(`h2`,w,o(n(O)(`ds.cartDrawer.integrationTitle`)),1),l(`p`,T,o(n(O)(`ds.cartDrawer.integrationBody`)),1),r[2]||=l(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[l(`pre`,{class:`whitespace-pre-wrap`},`import {
import{B as e,C as t,G as n,S as r,c as i,j as a,lt as o,m as s,p as c,s as l}from"./runtime-core.esm-bundler-BD0e4RlP.js";import{t as u}from"./Icon-BCRRMV3J.js";import{t as d}from"./i18n-CH9FW6EE.js";import{a as f,i as p,n as m,o as h,r as g,t as _}from"./api-DbjChhCZ.js";import{t as v}from"./Button-DkdaDkuf.js";import{t as y}from"./CartDrawer-C4QVm0QX.js";import{t as b}from"./SectionShell-Cd_Fu3uI.js";var x={class:`eyebrow mb-5`},S={class:`rounded-md border border-line bg-paper p-6 flex flex-col sm:flex-row sm:items-center gap-4`},C={class:`text-[13px] text-muted`},w={class:`eyebrow mb-5`},T={class:`text-[15px] text-muted leading-relaxed mb-4 max-w-2xl`},E={class:`eyebrow mb-5`},D={__name:`CartDrawerSection`,setup(D){let{t:O}=d(),k=h(),A=e(!1);async function j(){await m(),await _(`kaiser-natron-pulver-250-g-grosspackung`,2),await _(`kaiser-natron-bad-500-g`,1),A.value=!0}async function M({productId:e,quantity:t}){await f(e,t)}async function N(e){await p(e)}return r(()=>{g()}),(e,r)=>(t(),i(b,{eyebrow:n(O)(`ds.eyebrow.components`),title:n(O)(`ds.cartDrawer.title`),description:n(O)(`ds.cartDrawer.description`)},{default:a(()=>[l(`section`,null,[l(`h2`,x,o(n(O)(`ds.heading.default`)),1),l(`div`,S,[s(v,{variant:`primary`,onClick:j},{before:a(()=>[s(u,{name:`cart`,size:18})]),default:a(()=>[c(` `+o(n(O)(`ds.cartDrawer.demoLabel`)),1)]),_:1}),l(`p`,C,o(n(O)(`ds.cartDrawer.demoHint`)),1)])]),l(`section`,null,[l(`h2`,w,o(n(O)(`ds.cartDrawer.integrationTitle`)),1),l(`p`,T,o(n(O)(`ds.cartDrawer.integrationBody`)),1),r[2]||=l(`div`,{class:`rounded-md border border-line bg-paper p-6 font-mono text-[12px] text-ink`},[l(`pre`,{class:`whitespace-pre-wrap`},`import {
fetchCart,
addToCart,
updateCartItem,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/index.html vendored
View File

@@ -12,13 +12,13 @@
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-CE-8HSQ-.js"></script>
<script type="module" crossorigin src="/assets/index-CTSKceZg.js"></script>
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-BOai-rQB.js">
<link rel="modulepreload" crossorigin href="/assets/runtime-core.esm-bundler-BD0e4RlP.js">
<link rel="modulepreload" crossorigin href="/assets/runtime-dom.esm-bundler-CcSFQHoC.js">
<link rel="modulepreload" crossorigin href="/assets/pinia-DQoUg3qR.js">
<link rel="modulepreload" crossorigin href="/assets/vue-router-QRVDVSxc.js">
<link rel="stylesheet" crossorigin href="/assets/index-CfcW0yqE.css">
<link rel="stylesheet" crossorigin href="/assets/index-CeYmbJUR.css">
</head>
<body>
<div id="app"></div>

View File

@@ -199,18 +199,14 @@ function onRemove(line) {
</ul>
</div>
<!-- Footer — mirrors the mobile menu overlay: primary action takes
the width, close icon sits to its right so the thumb has both
controls in the bottom cluster. -->
<!-- Footer padding reserves room for the mobile floating
close button (bottom-5 right-5 + size-lg ≈ 76 px tall
hit-box). Right-padding shifts the checkout CTA left
on mobile so the close never overlaps the button. On
md+ the floating close is hidden, so the extra right
padding collapses. -->
<!-- Footer — mirrors the mobile menu overlay: checkout takes
the width, close icon sits to its right so the thumb
reaches both controls in the bottom cluster. On md+
the inline close hides (desktop has the header X);
mobile gets the paired row. -->
<footer
v-if="hasItems"
class="shrink-0 border-t border-line px-6 py-5 flex flex-col gap-4 pr-24 md:pr-6"
class="shrink-0 border-t border-line px-6 py-5 flex flex-col gap-4"
style="padding-bottom: calc(env(safe-area-inset-bottom) + 1.25rem);"
>
<div class="flex items-baseline justify-between">
@@ -219,55 +215,39 @@ function onRemove(line) {
{{ formatPrice(subtotal) }}
</span>
</div>
<!-- Checkout takes the full width. The mobile close button
is rendered outside the drawer as a floating IconButton
at the exact `bottom-5 right-5` position that the
page's menu-open button uses, so opening/closing feels
like the same control. -->
<Button
variant="primary"
size="lg"
block
@click="$emit('checkout')"
>
<template #after><Icon name="arrow-right" :size="18" /></template>
{{ t('cart.checkout') }}
</Button>
<div class="flex items-center gap-3">
<!-- Checkout stretches to fill the row on mobile and
spans the full footer on desktop (close hidden). -->
<Button
variant="primary"
size="lg"
block
class="flex-1 min-w-0"
@click="$emit('checkout')"
>
<template #after><Icon name="arrow-right" :size="18" /></template>
{{ t('cart.checkout') }}
</Button>
<!-- Mobile close sits in-row at the right — same edge
margin as the page's menu-open IconButton (footer
px-6 + IconButton size-lg places its right edge
~20 px from the drawer edge, matching
`right-5`). Wrapped so IconButton's internal
`relative` doesn't fight the flex sizing. -->
<div class="md:hidden shrink-0">
<IconButton
icon="close"
variant="float"
size="lg"
:icon-size="24"
:icon-stroke-width="2"
:aria-label="t('menu.close')"
@click="close"
/>
</div>
</div>
</footer>
</aside>
</Transition>
<!-- Mobile floating close — lives OUTSIDE the drawer Transition
(which requires a single root child) so it can fade
independently with its own transition. Sits at
`bottom-5 right-5` to overlay the page's menu-open
IconButton exactly, matching the menu overlay's close
position for muscle-memory consistency across the two
mobile overlays. -->
<Transition
enter-active-class="transition-opacity duration-base ease-out"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="transition-opacity duration-base ease-out"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div
v-if="modelValue"
class="md:hidden fixed bottom-5 right-5 z-[70]"
style="padding-bottom: env(safe-area-inset-bottom);"
>
<IconButton
icon="close"
variant="float"
size="lg"
:icon-size="24"
:icon-stroke-width="2"
:aria-label="t('menu.close')"
@click="close"
/>
</div>
</Transition>
</Teleport>
</template>

View File

@@ -55,10 +55,16 @@ const navSecondaryItems = [
// pills that point at the shop's top-level use-cases. Labels are
// translated through the page i18n so the German/English splits stay
// in sync with the rest of the site copy.
// Mobile hero category pills — deep-link into the Shop page's
// matching use-case section (`/shop#cook`, `/shop#clean`,
// `/shop#care`). The router's `scrollBehavior` resolves the hash
// after navigation so the user lands directly on the section.
// Same targets the desktop top-nav uses, so the two entry points
// stay consistent.
const heroCategories = computed(() => [
{ label: t('home.categories.clean'), href: '#clean' },
{ label: t('home.categories.cook'), href: '#cook' },
{ label: t('home.categories.care'), href: '#care' },
{ label: t('home.categories.clean'), href: '/shop#clean' },
{ label: t('home.categories.cook'), href: '/shop#cook' },
{ label: t('home.categories.care'), href: '/shop#care' },
])
// Bundles sidebar copy resolves through the page's own i18n namespace so