fix: product texts, mobile nav background, mobile product page layout
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Successful in 2m20s
Build & Deploy / 🏗️ Build (push) Successful in 4m22s
Build & Deploy / 🚀 Deploy (push) Successful in 23s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 5m16s
Build & Deploy / 🔔 Notify (push) Successful in 1s
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Successful in 2m20s
Build & Deploy / 🏗️ Build (push) Successful in 4m22s
Build & Deploy / 🚀 Deploy (push) Successful in 23s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 5m16s
Build & Deploy / 🔔 Notify (push) Successful in 1s
- Fix PayloadRichText: migrate custom JSX converters to Lexical v3 nodesToJSX API - paragraph, heading, list, listitem, quote, link converters now use nodesToJSX - Resolves missing product texts since PayloadCMS migration - Fix mobile navigation: move overlay outside <header> to prevent fixed-position clipping - Header transform/backdrop-filter was containing the fixed overlay - Use bg-primary/95 backdrop-blur-3xl for premium blue background - Fix product image mobile layout: use md:-mt-32 responsive prefix - Negative margin only applies on md+ to avoid overlap on mobile - Improve mobile product page UX: - Breadcrumbs: flex-wrap, truncate, reduced separator spacing - Hero: reduced top padding pt-28 on mobile - Product image card: 4/3 aspect ratio and smaller padding on mobile - Section spacing: use responsive md: prefixes throughout - Data tables: 2-col grid on mobile, smaller card padding/radius - Tables: add right-edge scroll hint gradient on mobile
This commit is contained in:
@@ -141,7 +141,8 @@ export default function Header() {
|
||||
{
|
||||
'bg-primary/95 backdrop-blur-md md:bg-transparent py-3 md:py-8 shadow-2xl md:shadow-none':
|
||||
isHomePage && !isScrolled && !isMobileMenuOpen,
|
||||
'bg-primary py-3 md:py-4 shadow-2xl': !isHomePage || isScrolled || isMobileMenuOpen,
|
||||
'bg-primary/90 backdrop-blur-md py-3 md:py-4 shadow-2xl':
|
||||
!isHomePage || isScrolled || isMobileMenuOpen,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -152,9 +153,7 @@ export default function Header() {
|
||||
<>
|
||||
<header className={headerClass} style={{ animationDuration: '800ms' }}>
|
||||
<div className="container mx-auto px-4 md:px-12 lg:px-16 max-w-7xl flex items-center justify-between">
|
||||
<div
|
||||
className="flex-shrink-0 group touch-target fill-mode-both"
|
||||
>
|
||||
<div className="flex-shrink-0 group touch-target fill-mode-both">
|
||||
<Link
|
||||
href={`/${currentLocale}`}
|
||||
onClick={() =>
|
||||
@@ -336,115 +335,115 @@ export default function Header() {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Mobile Menu Overlay */}
|
||||
<div
|
||||
className={cn(
|
||||
'fixed inset-0 bg-primary z-[60] lg:hidden transition-all duration-500 ease-in-out flex flex-col',
|
||||
isMobileMenuOpen
|
||||
? 'opacity-100 translate-y-0'
|
||||
: 'opacity-0 -translate-y-full pointer-events-none',
|
||||
)}
|
||||
id="mobile-menu"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label={t('menu')}
|
||||
ref={mobileMenuRef}
|
||||
inert={isMobileMenuOpen ? undefined : true}
|
||||
>
|
||||
<nav className="flex-grow flex flex-col justify-center items-center p-8 space-y-8">
|
||||
{menuItems.map((item, idx) => (
|
||||
<div
|
||||
key={item.href}
|
||||
className={cn(
|
||||
'transition-all duration-500 transform',
|
||||
isMobileMenuOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8',
|
||||
)}
|
||||
style={{ transitionDelay: `${isMobileMenuOpen ? 200 + idx * 80 : 0}ms` }}
|
||||
>
|
||||
<Link
|
||||
href={`/${currentLocale}${item.href === '/' ? '' : item.href}`}
|
||||
aria-current={
|
||||
(
|
||||
item.href === '/'
|
||||
? pathname === `/${currentLocale}` || pathname === '/'
|
||||
: pathname.startsWith(`/${currentLocale}${item.href}`)
|
||||
)
|
||||
? 'page'
|
||||
: undefined
|
||||
}
|
||||
onClick={() => {
|
||||
setIsMobileMenuOpen(false);
|
||||
trackEvent(AnalyticsEvents.LINK_CLICK, {
|
||||
label: item.label,
|
||||
href: item.href,
|
||||
location: 'mobile_menu',
|
||||
});
|
||||
}}
|
||||
className={cn(
|
||||
'text-2xl md:text-3xl font-extrabold text-white hover:text-accent transition-all transform block py-4',
|
||||
(item.href === '/'
|
||||
? pathname === `/${currentLocale}` || pathname === '/'
|
||||
: pathname.startsWith(`/${currentLocale}${item.href}`)) && 'text-accent',
|
||||
)}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Mobile Menu Overlay */}
|
||||
<div
|
||||
className={cn(
|
||||
'fixed inset-0 bg-primary/95 backdrop-blur-3xl z-[60] lg:hidden transition-all duration-500 ease-in-out flex flex-col',
|
||||
isMobileMenuOpen
|
||||
? 'opacity-100 translate-y-0'
|
||||
: 'opacity-0 -translate-y-full pointer-events-none',
|
||||
)}
|
||||
id="mobile-menu"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label={t('menu')}
|
||||
ref={mobileMenuRef}
|
||||
inert={isMobileMenuOpen ? undefined : true}
|
||||
>
|
||||
<nav className="flex-grow flex flex-col justify-center items-center p-8 space-y-8">
|
||||
{menuItems.map((item, idx) => (
|
||||
<div
|
||||
key={item.href}
|
||||
className={cn(
|
||||
'pt-8 border-t border-white/10 w-full flex flex-col items-center space-y-8 transition-all duration-500',
|
||||
'transition-all duration-500 transform',
|
||||
isMobileMenuOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8',
|
||||
)}
|
||||
style={{ transitionDelay: isMobileMenuOpen ? '600ms' : '0ms' }}
|
||||
style={{ transitionDelay: `${isMobileMenuOpen ? 200 + idx * 80 : 0}ms` }}
|
||||
>
|
||||
<div className="flex items-center space-x-8 text-lg md:text-xl font-extrabold tracking-widest uppercase text-white">
|
||||
<div>
|
||||
<Link
|
||||
href={getPathForLocale('en')}
|
||||
className={`hover:text-accent transition-colors ${currentLocale === 'en' ? 'text-accent' : 'opacity-80'}`}
|
||||
>
|
||||
EN
|
||||
</Link>
|
||||
</div>
|
||||
<div className="w-px h-6 bg-white/30" />
|
||||
<div>
|
||||
<Link
|
||||
href={getPathForLocale('de')}
|
||||
className={`hover:text-accent transition-colors ${currentLocale === 'de' ? 'text-accent' : 'opacity-80'}`}
|
||||
>
|
||||
DE
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href={`/${currentLocale}${item.href === '/' ? '' : item.href}`}
|
||||
aria-current={
|
||||
(
|
||||
item.href === '/'
|
||||
? pathname === `/${currentLocale}` || pathname === '/'
|
||||
: pathname.startsWith(`/${currentLocale}${item.href}`)
|
||||
)
|
||||
? 'page'
|
||||
: undefined
|
||||
}
|
||||
onClick={() => {
|
||||
setIsMobileMenuOpen(false);
|
||||
trackEvent(AnalyticsEvents.LINK_CLICK, {
|
||||
label: item.label,
|
||||
href: item.href,
|
||||
location: 'mobile_menu',
|
||||
});
|
||||
}}
|
||||
className={cn(
|
||||
'text-2xl md:text-3xl font-extrabold text-white hover:text-accent transition-all transform block py-4',
|
||||
(item.href === '/'
|
||||
? pathname === `/${currentLocale}` || pathname === '/'
|
||||
: pathname.startsWith(`/${currentLocale}${item.href}`)) && 'text-accent',
|
||||
)}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="w-full max-w-xs">
|
||||
<Button
|
||||
href={`/${currentLocale}/${currentLocale === 'de' ? 'kontakt' : 'contact'}`}
|
||||
variant="accent"
|
||||
size="lg"
|
||||
className="w-full py-6 text-lg md:text-xl shadow-2xl hover:scale-105 transition-transform"
|
||||
<div
|
||||
className={cn(
|
||||
'pt-8 border-t border-white/10 w-full flex flex-col items-center space-y-8 transition-all duration-500',
|
||||
isMobileMenuOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8',
|
||||
)}
|
||||
style={{ transitionDelay: isMobileMenuOpen ? '600ms' : '0ms' }}
|
||||
>
|
||||
<div className="flex items-center space-x-8 text-lg md:text-xl font-extrabold tracking-widest uppercase text-white">
|
||||
<div>
|
||||
<Link
|
||||
href={getPathForLocale('en')}
|
||||
className={`hover:text-accent transition-colors ${currentLocale === 'en' ? 'text-accent' : 'opacity-80'}`}
|
||||
>
|
||||
{t('contact')}
|
||||
</Button>
|
||||
EN
|
||||
</Link>
|
||||
</div>
|
||||
<div className="w-px h-6 bg-white/30" />
|
||||
<div>
|
||||
<Link
|
||||
href={getPathForLocale('de')}
|
||||
className={`hover:text-accent transition-colors ${currentLocale === 'de' ? 'text-accent' : 'opacity-80'}`}
|
||||
>
|
||||
DE
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Branding */}
|
||||
<div
|
||||
className={cn(
|
||||
'p-12 flex justify-center transition-all duration-700',
|
||||
isMobileMenuOpen ? 'opacity-20 scale-100' : 'opacity-0 scale-75',
|
||||
)}
|
||||
style={{ transitionDelay: isMobileMenuOpen ? '800ms' : '0ms' }}
|
||||
>
|
||||
<Image src="/logo-white.svg" alt={t('home')} width={80} height={80} unoptimized />
|
||||
<div className="w-full max-w-xs">
|
||||
<Button
|
||||
href={`/${currentLocale}/${currentLocale === 'de' ? 'kontakt' : 'contact'}`}
|
||||
variant="accent"
|
||||
size="lg"
|
||||
className="w-full py-6 text-lg md:text-xl shadow-2xl hover:scale-105 transition-transform"
|
||||
>
|
||||
{t('contact')}
|
||||
</Button>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
{/* Bottom Branding */}
|
||||
<div
|
||||
className={cn(
|
||||
'p-12 flex justify-center transition-all duration-700',
|
||||
isMobileMenuOpen ? 'opacity-20 scale-100' : 'opacity-0 scale-75',
|
||||
)}
|
||||
style={{ transitionDelay: isMobileMenuOpen ? '800ms' : '0ms' }}
|
||||
>
|
||||
<Image src="/logo-white.svg" alt={t('home')} width={80} height={80} unoptimized />
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user