9e5532be63
- New /shop overview, /cart (real cart state via useSyncExternalStore), /versand (shipping policy page with TOC) and /newsletter detail page - Cart: quantity/removal, order summary, related-products cross-sell with randomized picks, VersandModal quick-reference instead of navigating away, MwSt. disclosure next to unit prices - Add-to-cart UX: inline success feedback (green state) plus a fly-to-navbar-cart-icon animation (CartFlyProvider) with a delayed badge count-up; AddToCartButton no longer navigates straight to /cart - Shared lib/products.ts catalog and lib/shipping.ts constants (cost, free-shipping threshold, handling/transit days) so cart, trust badges and the versand page can never drift apart - Fix Navbar smooth-scroll easing (ease-out instead of ease-in-out, no more perceived start delay); compress newsletter modal photo 2.4MB -> 85KB to fix first-open jank
88 lines
3.6 KiB
TypeScript
88 lines
3.6 KiB
TypeScript
import { Reveal } from "./Reveal";
|
|
|
|
type NewsletterProps = {
|
|
title?: string;
|
|
description?: string;
|
|
};
|
|
|
|
/**
|
|
* Reused as-is (same bordered/muted panel + icon-decoration + form
|
|
* pattern) on both Home and /newsletter (the "Impulse & Tipps" page) —
|
|
* their Figma frames use the exact same newsletter-inner component
|
|
* instance, just with different copy, so title/description are props
|
|
* instead of a second near-duplicate component.
|
|
*/
|
|
export function Newsletter({
|
|
title = "Starte mit einer Woche voller Klarheit",
|
|
description = "Melde dich zum Newsletter an und erhalte die 7-Tage-Challenge, mit der du durch mehr Struktur weniger Stress spürst.",
|
|
}: NewsletterProps = {}) {
|
|
return (
|
|
<section className="py-16 w-full">
|
|
|
|
{/* Outer section padding — same fluid horizontal padding as all other sections */}
|
|
<div className="px-[var(--layout-padding-x)] w-full">
|
|
|
|
{/* Rounded card: cream bg, stacks below md */}
|
|
<Reveal className="bg-bg-muted flex flex-col md:flex-row gap-8 md:gap-12 items-center px-8 py-8 md:py-0 rounded-md w-full">
|
|
|
|
{/* Left: copy — fixed width from md+ so the form always gets the remaining space */}
|
|
<div className="flex gap-8 items-start w-full md:w-[var(--newsletter-copy-width)] md:py-4 md:shrink-0">
|
|
|
|
{/* Decorative envelope icon, tilted -4° as per design */}
|
|
<div className="flex items-center justify-center shrink-0 w-[4.23rem] h-[3.71rem]">
|
|
<div className="-rotate-4 -scale-y-100">
|
|
<img
|
|
alt=""
|
|
src="/newsletter-icon.svg"
|
|
className="w-16 h-[3.438rem] block"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Heading + body */}
|
|
<div className="flex flex-col gap-4 flex-1 min-w-0 text-text-primary">
|
|
<p
|
|
className="font-semibold text-h-section leading-normal"
|
|
style={{ fontFamily: "var(--font-lora)" }}
|
|
>
|
|
{title}
|
|
</p>
|
|
<p className="font-normal text-body leading-6">
|
|
{description}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Right: form — takes remaining space, centered vertically from md+ */}
|
|
<div className="flex w-full md:flex-1 items-center md:self-stretch min-w-0">
|
|
<div className="flex flex-1 flex-col gap-4 min-w-0 w-full">
|
|
|
|
{/* Input + submit button — stacked below md, side by side from md+ */}
|
|
<div className="flex flex-col md:flex-row gap-4 items-stretch w-full">
|
|
<input
|
|
type="email"
|
|
placeholder="Deine E-Mail-Adresse"
|
|
className="flex-1 min-w-0 bg-bg-white border border-border rounded-sm px-6 py-3 text-body text-text-muted font-normal outline-none focus:border-brand transition-colors"
|
|
/>
|
|
<button
|
|
type="submit"
|
|
className="shrink-0 bg-brand rounded-sm px-5 py-3 font-bold text-h4 text-text-primary tracking-[0.18px] whitespace-nowrap hover:brightness-95 active:scale-[0.97] transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 focus-visible:ring-offset-bg-muted"
|
|
>
|
|
Jetzt anmelden
|
|
</button>
|
|
</div>
|
|
|
|
{/* Privacy note */}
|
|
<p className="text-label text-text-primary font-normal leading-normal">
|
|
Ich achte auf deine Daten. Kein Spam, jederzeit abbestellbar.
|
|
</p>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</Reveal>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|