This commit is contained in:
Your Name committed 2026-07-25 00:08:55 -04:00
1 parent 63bc3bfb1a
commit 497e3d4d5b
2 files changed
+205 -123

No files matched your search

+59
View File
@@ -209,6 +209,65 @@
@apply flex h-9 w-9 items-center justify-center rounded-full border border-line-primary/20 bg-surface-page text-[10px] font-bold text-text-main transition-all duration-300 hover:border-brand-primary hover:bg-brand-primary hover:text-surface-card; @apply flex h-9 w-9 items-center justify-center rounded-full border border-line-primary/20 bg-surface-page text-[10px] font-bold text-text-main transition-all duration-300 hover:border-brand-primary hover:bg-brand-primary hover:text-surface-card;
} }
.site-footer {
@apply relative bg-surface-page;
z-index: 1;
}
.site-footer-brand-finale {
@apply flex min-h-[55svh] items-center justify-center overflow-hidden border-t border-line-primary/20 bg-surface-page px-6 py-20 text-center;
}
.site-footer-finale-logo {
@apply h-auto max-h-32 w-auto max-w-[min(82vw,32rem)] object-contain;
}
.site-footer-finale-wordmark {
@apply max-w-full break-words text-5xl font-semibold uppercase text-text-main md:text-7xl;
letter-spacing: 0;
}
.site-footer-navigation {
@apply relative border-t border-line-primary/20 bg-surface-card px-6 py-20;
z-index: 3;
}
@media (min-width: 1024px) {
.global-main {
position: relative;
z-index: 2;
background: var(--color-surface-page);
}
.site-footer-with-finale {
padding-top: 100svh;
}
.site-footer-brand-finale {
@apply fixed inset-0 min-h-[100svh] py-24;
z-index: 0;
pointer-events: none;
}
.site-footer-finale-logo {
@apply max-h-48 max-w-[min(68vw,48rem)];
}
.site-footer-finale-wordmark {
@apply text-8xl;
}
}
@media (prefers-reduced-motion: reduce) {
.site-footer-brand-finale {
position: relative;
}
.site-footer-with-finale {
padding-top: 0;
}
}
.ui-section-band { .ui-section-band {
@apply px-6 py-20 md:py-24; @apply px-6 py-20 md:py-24;
} }
+146 -123
View File
@@ -54,138 +54,161 @@ export default function Footer({
// Social links — use settings if available, fallback to placeholder buttons // Social links — use settings if available, fallback to placeholder buttons
const hasSocialLinks = settings && (settings.facebookUrl || settings.instagramUrl || settings.tiktokUrl) const hasSocialLinks = settings && (settings.facebookUrl || settings.instagramUrl || settings.tiktokUrl)
const brandName = settings?.brandName || '' const brandName = settings?.brandName || ''
const hasBrandFinale = Boolean(settings?.logoUrl || brandName.trim())
return ( return (
<footer className="border-t border-line-primary/20 bg-surface-card px-6 py-20 text-text-main"> <footer className={`site-footer text-text-main${hasBrandFinale ? ' site-footer-with-finale' : ''}`}>
<div className="mx-auto grid max-w-7xl grid-cols-1 gap-12 md:grid-cols-4"> {hasBrandFinale && (
<section
className="site-footer-brand-finale"
aria-label={brandName || t('footer.brand', 'Brand')}
>
{settings?.logoUrl ? (
<Image
src={settings.logoUrl}
alt=""
width={640}
height={240}
unoptimized
className="site-footer-finale-logo"
/>
) : (
<p className="site-footer-finale-wordmark">{brandName}</p>
)}
</section>
)}
{/* Col 1 — Brand */} <div className="site-footer-navigation">
<div className="space-y-6"> <div className="mx-auto grid max-w-7xl grid-cols-1 gap-12 md:grid-cols-4">
<div className="text-2xl font-bold tracking-widest">
{settings?.logoUrl ? (
<Image src={settings.logoUrl} alt={brandName} width={160} height={40} unoptimized className="h-8 w-auto object-contain md:h-10" />
) : (
brandName
)}
</div>
<p className="text-sm leading-relaxed ui-muted-text">
{resolveLocalized(settings?.footerDescription, effectiveLang) || t('footer.catchphrase')}
</p>
<div className="flex gap-4">
{hasSocialLinks ? (
<>
{settings!.facebookUrl && (
<a
href={settings!.facebookUrl}
target="_blank"
rel="noreferrer"
className="ui-footer-social"
>
FB
</a>
)}
{settings!.instagramUrl && (
<a
href={settings!.instagramUrl}
target="_blank"
rel="noreferrer"
className="ui-footer-social"
>
IG
</a>
)}
{settings!.tiktokUrl && (
<a
href={settings!.tiktokUrl}
target="_blank"
rel="noreferrer"
className="ui-footer-social"
>
TT
</a>
)}
</>
) : (
['IG', 'FB', 'TW', 'YT'].map((s) => (
<a
key={s}
href="#"
className="ui-footer-social"
>
{s}
</a>
))
)}
</div>
</div>
{/* Col 2 — Explore */} {/* Col 1 — Brand */}
<div className="space-y-4"> <div className="space-y-6">
<h4 className="ui-menu-title">{t('footer.explore')}</h4> <div className="text-2xl font-bold tracking-widest">
<div className="flex flex-col space-y-2 text-sm text-muted-text"> {settings?.logoUrl ? (
{exploreMenu.length > 0 ? ( <Image src={settings.logoUrl} alt={brandName} width={160} height={40} unoptimized className="h-8 w-auto object-contain md:h-10" />
exploreMenu.map((item) => ( ) : (
brandName
)}
</div>
<p className="text-sm leading-relaxed ui-muted-text">
{resolveLocalized(settings?.footerDescription, effectiveLang) || t('footer.catchphrase')}
</p>
<div className="flex gap-4">
{hasSocialLinks ? (
<>
{settings!.facebookUrl && (
<a
href={settings!.facebookUrl}
target="_blank"
rel="noreferrer"
className="ui-footer-social"
>
FB
</a>
)}
{settings!.instagramUrl && (
<a
href={settings!.instagramUrl}
target="_blank"
rel="noreferrer"
className="ui-footer-social"
>
IG
</a>
)}
{settings!.tiktokUrl && (
<a
href={settings!.tiktokUrl}
target="_blank"
rel="noreferrer"
className="ui-footer-social"
>
TT
</a>
)}
</>
) : (
['IG', 'FB', 'TW', 'YT'].map((s) => (
<a
key={s}
href="#"
className="ui-footer-social"
>
{s}
</a>
))
)}
</div>
</div>
{/* Col 2 — Explore */}
<div className="space-y-4">
<h4 className="ui-menu-title">{t('footer.explore')}</h4>
<div className="flex flex-col space-y-2 text-sm text-muted-text">
{exploreMenu.length > 0 ? (
exploreMenu.map((item) => (
<Link key={item.id} href={item.url} className="ui-footer-link">
{translateMenuLabel(item)}
</Link>
))
) : (
<>
<Link href="/" className="ui-footer-link">{t('nav.home')}</Link>
<Link href="/shop" className="ui-footer-link">{t('nav.shop')}</Link>
<Link href="/scent-guide" className="ui-footer-link">{t('nav.scentGuide')}</Link>
<Link href="/about" className="ui-footer-link">{t('nav.about')}</Link>
<Link href="/contact" className="ui-footer-link">{t('nav.contact')}</Link>
<Link href="/faq" className="ui-footer-link">{t('nav.faq')}</Link>
</>
)}
</div>
</div>
{/* Col 3 — Collections */}
<div className="space-y-4">
<h4 className="ui-menu-title">{t('nav.collections')}</h4>
<div className="flex flex-col space-y-2 text-sm text-muted-text">
{categories.map((c) => (
<Link key={c.id} href={`/category/${c.id}`} className="ui-footer-link">
{resolveLocalized(c.name, effectiveLang)}
</Link>
))}
</div>
</div>
{/* Col 4 — Support & Legal */}
<div className="space-y-4">
<h4 className="ui-menu-title">
{settings?.footerSupportHeading
? (typeof settings.footerSupportHeading === 'string'
? settings.footerSupportHeading
: settings.footerSupportHeading[effectiveLang]
|| settings.footerSupportHeading.en
|| 'Support & Legal')
: t('footer.support', 'Support & Legal')}
</h4>
<div className="flex flex-col space-y-2 text-sm text-muted-text">
{supportMenu.map((item) => (
<Link key={item.id} href={item.url} className="ui-footer-link"> <Link key={item.id} href={item.url} className="ui-footer-link">
{translateMenuLabel(item)} {translateMenuLabel(item)}
</Link> </Link>
)) ))}
) : ( </div>
<>
<Link href="/" className="ui-footer-link">{t('nav.home')}</Link> <div className="pt-4">
<Link href="/shop" className="ui-footer-link">{t('nav.shop')}</Link> <p className="text-[10px] uppercase tracking-widest text-muted-text">
<Link href="/scent-guide" className="ui-footer-link">{t('nav.scentGuide')}</Link> {settings?.footerCopyrightText
<Link href="/about" className="ui-footer-link">{t('nav.about')}</Link> ? (typeof settings.footerCopyrightText === 'string'
<Link href="/contact" className="ui-footer-link">{t('nav.contact')}</Link> ? settings.footerCopyrightText
<Link href="/faq" className="ui-footer-link">{t('nav.faq')}</Link> : settings.footerCopyrightText[effectiveLang]
</> || settings.footerCopyrightText.en
)} || `© ${new Date().getFullYear()} ${brandName}. ${t('footer.rights')}`)
: `© ${new Date().getFullYear()} ${brandName}. ${t('footer.rights')}`}
</p>
</div>
</div> </div>
</div> </div>
{/* Col 3 — Collections */}
<div className="space-y-4">
<h4 className="ui-menu-title">{t('nav.collections')}</h4>
<div className="flex flex-col space-y-2 text-sm text-muted-text">
{categories.map((c) => (
<Link key={c.id} href={`/category/${c.id}`} className="ui-footer-link">
{resolveLocalized(c.name, effectiveLang)}
</Link>
))}
</div>
</div>
{/* Col 4 — Support & Legal */}
<div className="space-y-4">
<h4 className="ui-menu-title">
{settings?.footerSupportHeading
? (typeof settings.footerSupportHeading === 'string'
? settings.footerSupportHeading
: settings.footerSupportHeading[effectiveLang]
|| settings.footerSupportHeading.en
|| 'Support & Legal')
: t('footer.support', 'Support & Legal')}
</h4>
<div className="flex flex-col space-y-2 text-sm text-muted-text">
{supportMenu.map((item) => (
<Link key={item.id} href={item.url} className="ui-footer-link">
{translateMenuLabel(item)}
</Link>
))}
</div>
<div className="pt-4">
<p className="text-[10px] uppercase tracking-widest text-muted-text">
{settings?.footerCopyrightText
? (typeof settings.footerCopyrightText === 'string'
? settings.footerCopyrightText
: settings.footerCopyrightText[effectiveLang]
|| settings.footerCopyrightText.en
|| `© ${new Date().getFullYear()} ${brandName}. ${t('footer.rights')}`)
: `© ${new Date().getFullYear()} ${brandName}. ${t('footer.rights')}`}
</p>
</div>
</div>
</div> </div>
</footer> </footer>
) )