This commit is contained in:
Your Name committed 2026-06-27 23:19:51 -04:00
1 parent 1a13b3624a
commit 4454b860c1
9 files changed
+381 -105

No files matched your search

@@ -290,9 +290,9 @@ function BannerSection({ payload, lang }: { payload: Record<string, unknown>, la
<Image src={imageUrl} alt={title || 'Banner'} fill unoptimized className="absolute inset-0 h-full w-full object-cover" />
<div className="ui-banner-overlay" />
<div className="ui-banner-content">
{title && <h2 className="text-3xl font-semibold md:text-5xl">{title}</h2>}
{description && <p className="text-surface-card">{description}</p>}
{buttonText && <span className="inline-flex rounded-full bg-surface-card px-6 py-3 font-semibold text-text-main">{buttonText}</span>}
{title && <h2 className="text-3xl font-semibold text-brand-primary drop-shadow-md md:text-5xl">{title}</h2>}
{description && <p className="text-surface-page/90 drop-shadow-sm">{description}</p>}
{buttonText && <span className="inline-flex cursor-pointer rounded-full bg-surface-card px-6 py-3 font-semibold text-text-main transition-colors hover:bg-brand-primary hover:text-surface-card">{buttonText}</span>}
</div>
</div>
)
@@ -399,56 +399,82 @@ function EditorialCarouselSection({ payload, lang }: { payload: Record<string, u
const slides = Array.isArray(payload.slides) ? payload.slides.map(toRecord) : []
const backgroundColor = typeof payload.backgroundColor === 'string' ? payload.backgroundColor : undefined
const textColor = typeof payload.textColor === 'string' ? payload.textColor : undefined
const bgClass = backgroundColor ? `bg-pop-${backgroundColor}` : 'bg-surface-page'
const textClass = textColor ? `text-pop-${textColor}` : 'text-text-main'
const scrollContainerRef = useRef<HTMLDivElement>(null)
const scrollBy = (offset: number) => {
if (scrollContainerRef.current) {
scrollContainerRef.current.scrollBy({ left: offset, behavior: 'smooth' })
}
}
if (!slides.length) return null
return (
<section className="ui-section-dark py-16 md:py-24" style={{ backgroundColor, color: textColor }}>
<section className={`px-6 py-16 md:py-24 ${bgClass} ${textClass}`}>
<div className="mx-auto max-w-7xl space-y-12">
{title && (
<div className="mx-auto max-w-3xl space-y-4 text-center">
<h2 className="text-4xl font-semibold text-surface-card md:text-5xl" style={{ color: textColor }}>{renderAccentTitle(title)}</h2>
<h2 className={`text-4xl font-semibold md:text-5xl ${textClass}`}>{renderAccentTitle(title)}</h2>
<div className="mx-auto h-px w-16 bg-brand-accent" />
</div>
)}
<div className="flex overflow-x-auto snap-x snap-mandatory hide-scrollbar gap-6 pb-8">
{slides.map((slide, index) => {
const slideTitle = localizedFromRecord(slide, 'title', resolvedLang)
const description = localizedFromRecord(slide, 'description', resolvedLang)
const category = localizedFromRecord(slide, 'category', resolvedLang)
const buttonText = localizedFromRecord(slide, 'buttonText', resolvedLang)
const buttonLink = typeof slide.buttonLink === 'string' ? slide.buttonLink : ''
const imageUrl = typeof slide.imageUrl === 'string' ? slide.imageUrl : ''
<div className="relative">
<button
onClick={() => scrollBy(-400)}
className="hidden md:flex bg-surface-card rounded-full shadow-card hover:text-brand-primary h-10 w-10 items-center justify-center absolute z-10 top-1/2 -translate-y-1/2 -left-5"
aria-label="Scroll left"
>
<ChevronLeft className="h-6 w-6 text-brand-primary" />
</button>
<div ref={scrollContainerRef} className="flex overflow-x-auto snap-x snap-mandatory hide-scrollbar gap-6 pb-8">
{slides.map((slide, index) => {
const slideTitle = localizedFromRecord(slide, 'title', resolvedLang)
const description = localizedFromRecord(slide, 'description', resolvedLang)
const category = localizedFromRecord(slide, 'category', resolvedLang)
const buttonText = localizedFromRecord(slide, 'buttonText', resolvedLang)
const buttonLink = typeof slide.buttonLink === 'string' ? slide.buttonLink : ''
const imageUrl = typeof slide.imageUrl === 'string' ? slide.imageUrl : ''
return (
<article key={index} className="ui-section-dark-card group w-[85vw] md:w-[350px] flex-none snap-start">
{imageUrl ? (
<div className="relative aspect-[4/3] overflow-hidden">
<Image
src={imageUrl}
alt={slideTitle || 'Editorial slide'}
fill
unoptimized
className="h-full w-full object-cover transition duration-700 group-hover:scale-105"
/>
</div>
) : null}
<div className="space-y-4 p-6 flex flex-col flex-1 justify-between">
<div>
{category && <p className="text-[10px] font-bold uppercase tracking-[0.24em] text-brand-accent mb-2">{category}</p>}
{slideTitle && <h3 className="ui-section-dark-card-title text-xl mb-3">{renderAccentTitle(slideTitle)}</h3>}
{description && <p className="ui-section-dark-card-copy text-sm line-clamp-3">{description}</p>}
</div>
{buttonText && buttonLink && (
<div className="pt-2">
<Link href={buttonLink} className="ui-section-dark-link inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest transition-colors group/link">
{buttonText} <span className="group-hover/link:translate-x-1 transition-transform">&rarr;</span>
</Link>
return (
<article key={index} className="ui-card overflow-hidden group w-[85vw] md:w-[350px] flex-none snap-start">
{imageUrl ? (
<div className="relative aspect-[4/3] overflow-hidden">
<Image
src={imageUrl}
alt={slideTitle || 'Editorial slide'}
fill
unoptimized
className="h-full w-full object-cover transition duration-700 group-hover:scale-105"
/>
</div>
)}
</div>
</article>
)
})}
) : null}
<div className="space-y-4 p-6 flex flex-col flex-1 justify-between">
<div>
{category && <span className="text-[10px] font-bold uppercase tracking-[0.24em] text-brand-primary block">{category}</span>}
{slideTitle && <h3 className="text-xl font-bold text-text-main mt-6 group-hover:text-brand-primary transition-colors">{renderAccentTitle(slideTitle)}</h3>}
{description && <p className="text-base text-muted-text mt-3 whitespace-pre-wrap">{description}</p>}
</div>
{buttonText && buttonLink && (
<div className="pt-2">
<Link href={buttonLink} className="ui-section-dark-link inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest transition-colors group/link">
{buttonText} <span className="group-hover/link:translate-x-1 transition-transform">&rarr;</span>
</Link>
</div>
)}
</div>
</article>
)
})}
</div>
<button
onClick={() => scrollBy(400)}
className="hidden md:flex bg-surface-card rounded-full shadow-card hover:text-brand-primary h-10 w-10 items-center justify-center absolute z-10 top-1/2 -translate-y-1/2 -right-5"
aria-label="Scroll right"
>
<ChevronRight className="h-6 w-6 text-brand-primary" />
</button>
</div>
</div>
</section>
@@ -560,9 +586,12 @@ function AccordionSection({ payload, lang }: { payload: Record<string, unknown>,
const categories = Array.isArray(payload.categories) ? payload.categories.map(toRecord) : []
if (!categories.length) return null
const sectionTitle = localizedFromRecord(payload, 'title', resolvedLang)
const backgroundColor = typeof payload.backgroundColor === 'string' ? payload.backgroundColor : undefined
const textColor = typeof payload.textColor === 'string' ? payload.textColor : undefined
const iconColor = typeof payload.iconColor === 'string' ? payload.iconColor : undefined
return (
<section className="bg-surface-page ui-section-band">
<section className="ui-section-band" style={{ backgroundColor, color: textColor }}>
<div className="mx-auto max-w-4xl space-y-10">
{sectionTitle && <h2 className="ui-section-title">{sectionTitle}</h2>}
{categories.map((category, categoryIndex) => {
@@ -573,8 +602,8 @@ function AccordionSection({ payload, lang }: { payload: Record<string, unknown>,
return (
<div key={categoryIndex} className="space-y-5">
{name && (
<h2 className="flex items-center gap-3 text-2xl font-semibold text-text-main">
{icon && <span className="text-brand-primary">{icon}</span>}
<h2 className="flex items-center gap-3 text-2xl font-semibold">
{icon && <span style={{ color: iconColor }}>{icon}</span>}
{name}
</h2>
)}
@@ -586,7 +615,7 @@ function AccordionSection({ payload, lang }: { payload: Record<string, unknown>,
return (
<details key={itemIndex} className="group rounded-2xl bg-surface-card p-5 shadow-card">
<summary className="cursor-pointer list-none text-lg font-semibold text-text-main marker:hidden">
<summary className="cursor-pointer list-none text-lg font-semibold marker:hidden">
{question}
</summary>
<p className="mt-4 whitespace-pre-wrap leading-relaxed text-muted-text">{answer}</p>