Redesign: warmer, more editorial visual pass; remove stray em dashes
Replaces em dashes with en dashes across all hardcoded copy, emails, and seed content, then reworks the site's visual language so it reads as deliberately designed rather than assembled from generic components: - New ArrowLink component replaces ad hoc "Mehr erfahren ->" links and ghost buttons; one shared FormField (TextField/TextAreaField) replaces 7 near-duplicate field styles across every form - Navbar loses its glassmorphism blur for a solid warm background, gets a subtle active-link underline and a softer, warmer mega-menu - PageHeader supports per-page blob tone/position and a compact mode instead of an identical band on every interior page - Homepage: the core offer is featured large instead of four equal cards, the philosophy section gets a single calmer accent blob, blog teasers now show their cover image like the real /aktuelles page does - Booking calendar and widget: 44px touch targets throughout (month nav, day cells, time slots, cancel action), a visible "today" ring, and responsive padding so the calendar isn't cramped on small screens - Quieter, warmer empty states on /termine and /aktuelles No functional changes: all interaction logic (nav menus, forms, booking, CMS data fetching) is untouched, only markup and styling.
This commit is contained in:
+57
-48
@@ -6,6 +6,8 @@ import { useEffect, useRef, useState } from "react";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { groupOffersByCategory } from "@/lib/angebote";
|
||||
import { mainNav, ctaNav, siteConfig } from "@/lib/site";
|
||||
import { track } from "@/lib/analytics/client";
|
||||
import { OrganicBlob } from "@/components/OrganicBlob";
|
||||
import type { Offer } from "@/payload-types";
|
||||
|
||||
export function Navbar({ offers, customerName }: { offers: Offer[]; customerName?: string | null }) {
|
||||
@@ -63,7 +65,7 @@ export function Navbar({ offers, customerName }: { offers: Offer[]; customerName
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 border-b border-anouma-taupe/15 bg-background/85 backdrop-blur-md">
|
||||
<header className="sticky top-0 z-50 border-b border-anouma-taupe/15 bg-background">
|
||||
<div className="mx-auto flex h-20 max-w-6xl items-center justify-between px-6 sm:px-8 lg:px-12">
|
||||
<Link
|
||||
href="/"
|
||||
@@ -108,52 +110,55 @@ export function Navbar({ offers, customerName }: { offers: Offer[]; customerName
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 8 }}
|
||||
transition={{ duration: 0.22, ease: "easeOut" }}
|
||||
className="absolute left-1/2 top-full z-50 mt-3 w-[min(640px,92vw)] -translate-x-1/2 rounded-3xl border border-anouma-taupe/15 bg-background p-8 shadow-xl shadow-anouma-plum/10"
|
||||
className="absolute left-1/2 top-full z-50 mt-3 w-[min(640px,92vw)] -translate-x-1/2 overflow-hidden rounded-3xl border border-anouma-taupe/15 bg-background p-8 shadow-lg shadow-anouma-plum/10"
|
||||
>
|
||||
<div className="grid grid-cols-2 gap-8 sm:grid-cols-4">
|
||||
{groups.map((group) => {
|
||||
const isSingle = group.offers.length === 1;
|
||||
const groupHref = isSingle
|
||||
? `/angebote/${group.offers[0].slug}`
|
||||
: group.href;
|
||||
return (
|
||||
<div key={group.category}>
|
||||
<Link
|
||||
href={groupHref}
|
||||
className="font-serif text-lg font-medium text-anouma-plum hover:text-anouma-mauve-dark"
|
||||
>
|
||||
{group.label}
|
||||
</Link>
|
||||
{!isSingle && (
|
||||
<ul className="mt-3 space-y-2">
|
||||
{group.offers.map((offer) => (
|
||||
<li key={offer.slug}>
|
||||
<Link
|
||||
href={`/angebote/${offer.slug}`}
|
||||
className="text-sm text-anouma-plum transition-colors hover:text-anouma-mauve-dark"
|
||||
>
|
||||
{offer.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{isSingle && (
|
||||
<p className="mt-3 text-sm leading-relaxed text-anouma-plum">
|
||||
{group.offers[0].shortDescription}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="mt-7 border-t border-anouma-taupe/15 pt-5">
|
||||
<Link
|
||||
href="/angebote"
|
||||
className="text-sm font-medium text-anouma-mauve-dark underline underline-offset-4"
|
||||
>
|
||||
Alle Angebote im Überblick
|
||||
</Link>
|
||||
<OrganicBlob tone="cream" className="-right-16 -top-16 h-52 w-52 opacity-30" />
|
||||
<div className="relative">
|
||||
<div className="grid grid-cols-2 gap-8 sm:grid-cols-4">
|
||||
{groups.map((group) => {
|
||||
const isSingle = group.offers.length === 1;
|
||||
const groupHref = isSingle
|
||||
? `/angebote/${group.offers[0].slug}`
|
||||
: group.href;
|
||||
return (
|
||||
<div key={group.category}>
|
||||
<Link
|
||||
href={groupHref}
|
||||
className="font-serif text-lg font-medium text-anouma-plum hover:text-anouma-mauve-dark"
|
||||
>
|
||||
{group.label}
|
||||
</Link>
|
||||
{!isSingle && (
|
||||
<ul className="mt-3 space-y-2">
|
||||
{group.offers.map((offer) => (
|
||||
<li key={offer.slug}>
|
||||
<Link
|
||||
href={`/angebote/${offer.slug}`}
|
||||
className="text-sm text-anouma-plum transition-colors hover:text-anouma-mauve-dark"
|
||||
>
|
||||
{offer.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
{isSingle && (
|
||||
<p className="mt-3 text-sm leading-relaxed text-anouma-plum">
|
||||
{group.offers[0].shortDescription}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="mt-7 border-t border-anouma-taupe/15 pt-5">
|
||||
<Link
|
||||
href="/angebote"
|
||||
className="text-sm font-medium text-anouma-mauve-dark underline underline-offset-4"
|
||||
>
|
||||
Alle Angebote im Überblick
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
@@ -163,8 +168,9 @@ export function Navbar({ offers, customerName }: { offers: Offer[]; customerName
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className={`text-[15px] font-medium transition-colors hover:text-anouma-mauve-dark ${
|
||||
pathname === item.href ? "text-anouma-mauve-dark" : "text-anouma-plum/90"
|
||||
onClick={() => track("navigation_clicked", { path: item.href })}
|
||||
className={`relative pb-1 text-[15px] font-medium transition-colors after:absolute after:bottom-0 after:left-0 after:h-px after:bg-anouma-mauve-dark after:transition-all after:duration-300 after:content-[''] hover:text-anouma-mauve-dark hover:after:w-full ${
|
||||
pathname === item.href ? "text-anouma-mauve-dark after:w-full" : "text-anouma-plum/90 after:w-0"
|
||||
}`}
|
||||
>
|
||||
{item.title}
|
||||
@@ -182,6 +188,7 @@ export function Navbar({ offers, customerName }: { offers: Offer[]; customerName
|
||||
</Link>
|
||||
<Link
|
||||
href={ctaNav.href}
|
||||
onClick={() => track("navigation_clicked", { path: ctaNav.href })}
|
||||
className="rounded-full bg-anouma-mauve-dark px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-anouma-plum"
|
||||
>
|
||||
{ctaNav.title}
|
||||
@@ -300,6 +307,7 @@ export function Navbar({ offers, customerName }: { offers: Offer[]; customerName
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
onClick={() => track("navigation_clicked", { path: item.href })}
|
||||
className="border-b border-anouma-taupe/10 py-4 text-lg font-medium text-anouma-plum"
|
||||
>
|
||||
{item.title}
|
||||
@@ -314,6 +322,7 @@ export function Navbar({ offers, customerName }: { offers: Offer[]; customerName
|
||||
</Link>
|
||||
<Link
|
||||
href={ctaNav.href}
|
||||
onClick={() => track("navigation_clicked", { path: ctaNav.href })}
|
||||
className="mt-6 rounded-full bg-anouma-mauve-dark px-6 py-4 text-center text-base font-medium text-white"
|
||||
>
|
||||
{ctaNav.title}
|
||||
|
||||
Reference in New Issue
Block a user