feat: dark mode across all blocks
This commit is contained in:
parent
097615569b
commit
576ecf1e97
@ -14,12 +14,24 @@ export const FDAlternateHeroBlockComponent: React.FC<Props> = ({
|
|||||||
imageCaption,
|
imageCaption,
|
||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
}) => {
|
}) => {
|
||||||
const media = image as Media | undefined
|
const media = image as Media | undefined
|
||||||
const hasImage = media && typeof media === 'object' && media.url
|
const hasImage = media && typeof media === 'object' && media.url
|
||||||
const isDark = sectionBackground === 'navy'
|
const isDark = sectionBackground === 'navy'
|
||||||
const bgClass = isDark ? 'bg-fd-navy' : sectionBackground === 'gray' ? 'bg-fd-gray-light' : 'bg-white'
|
|
||||||
const titleClass = isDark ? 'text-fd-yellow' : 'text-fd-navy'
|
const bgClass =
|
||||||
const bodyClass = isDark ? 'text-white' : 'text-fd-navy'
|
isDark
|
||||||
|
? 'bg-fd-navy'
|
||||||
|
: sectionBackground === 'gray'
|
||||||
|
? 'bg-fd-gray-light dark:bg-fd-navy'
|
||||||
|
: 'bg-white dark:bg-fd-navy'
|
||||||
|
|
||||||
|
const titleClass = isDark
|
||||||
|
? 'text-fd-yellow'
|
||||||
|
: 'text-fd-navy dark:text-fd-yellow'
|
||||||
|
|
||||||
|
const bodyClass = isDark
|
||||||
|
? 'text-white'
|
||||||
|
: 'text-fd-navy dark:text-white'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full pt-16 md:pt-20 lg:pt-[99px] ${bgClass}`}>
|
<section className={`w-full pt-16 md:pt-20 lg:pt-[99px] ${bgClass}`}>
|
||||||
@ -49,7 +61,7 @@ export const FDAlternateHeroBlockComponent: React.FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* FIX: Full-width image using FDImage with fill, replacing raw <img> */}
|
{/* Full-width image — no border radius, bleeds edge to edge */}
|
||||||
{hasImage && (
|
{hasImage && (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="relative w-full" style={{ maxHeight: '620px', height: '45vw', minHeight: '220px' }}>
|
<div className="relative w-full" style={{ maxHeight: '620px', height: '45vw', minHeight: '220px' }}>
|
||||||
|
|||||||
@ -1,42 +1,44 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type { FDCtaBannerBlock as FDCtaBannerBlockProps } from '@/payload-types'
|
import type { FDCtaBannerBlock as FDCtaBannerBlockProps } from '@/payload-types'
|
||||||
|
|
||||||
const bgMap: Record<string, { section: string; heading: string; sub: string; primaryBtn: string; secondaryBtn: string }> = {
|
const bgMap: Record<string, {
|
||||||
|
section: string; heading: string; sub: string
|
||||||
|
primaryBtn: string; secondaryBtn: string
|
||||||
|
}> = {
|
||||||
yellow: {
|
yellow: {
|
||||||
section: 'bg-fd-yellow',
|
section: 'bg-fd-yellow',
|
||||||
heading: 'text-fd-navy',
|
heading: 'text-fd-navy',
|
||||||
sub: 'text-fd-navy/70',
|
sub: 'text-fd-navy/70',
|
||||||
primaryBtn: 'bg-fd-navy hover:bg-fd-navy/90 text-white',
|
primaryBtn: 'bg-fd-navy hover:bg-fd-navy/90 text-white',
|
||||||
secondaryBtn: 'border-2 border-fd-navy text-fd-navy hover:bg-fd-navy/10',
|
secondaryBtn: 'border-2 border-fd-navy text-fd-navy hover:bg-fd-navy/10',
|
||||||
},
|
},
|
||||||
navy: {
|
navy: {
|
||||||
section: 'bg-fd-navy',
|
section: 'bg-fd-navy',
|
||||||
heading: 'text-fd-yellow',
|
heading: 'text-fd-yellow',
|
||||||
sub: 'text-white/70',
|
sub: 'text-white/70',
|
||||||
primaryBtn: 'bg-fd-yellow hover:bg-fd-yellow/90 text-fd-navy',
|
primaryBtn: 'bg-fd-yellow hover:bg-fd-yellow/90 text-fd-navy',
|
||||||
secondaryBtn: 'border-2 border-white text-white hover:bg-white/10',
|
secondaryBtn: 'border-2 border-white text-white hover:bg-white/10',
|
||||||
},
|
},
|
||||||
gray: {
|
gray: {
|
||||||
section: 'bg-[#e5e5e5]',
|
section: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
heading: 'text-fd-navy',
|
heading: 'text-fd-navy dark:text-fd-yellow',
|
||||||
sub: 'text-fd-navy/70',
|
sub: 'text-fd-navy/70 dark:text-white/70',
|
||||||
primaryBtn: 'bg-fd-navy hover:bg-fd-navy/90 text-white',
|
primaryBtn: 'bg-fd-navy hover:bg-fd-navy/90 text-white dark:bg-fd-yellow dark:hover:bg-fd-yellow/90 dark:text-fd-navy',
|
||||||
secondaryBtn: 'border-2 border-fd-navy text-fd-navy hover:bg-fd-navy/10',
|
secondaryBtn: 'border-2 border-fd-navy text-fd-navy hover:bg-fd-navy/10 dark:border-white dark:text-white dark:hover:bg-white/10',
|
||||||
},
|
},
|
||||||
white: {
|
white: {
|
||||||
section: 'bg-white',
|
section: 'bg-white dark:bg-fd-navy',
|
||||||
heading: 'text-fd-navy',
|
heading: 'text-fd-navy dark:text-fd-yellow',
|
||||||
sub: 'text-fd-navy/70',
|
sub: 'text-fd-navy/70 dark:text-white/70',
|
||||||
primaryBtn: 'bg-fd-navy hover:bg-fd-navy/90 text-white',
|
primaryBtn: 'bg-fd-navy hover:bg-fd-navy/90 text-white dark:bg-fd-yellow dark:hover:bg-fd-yellow/90 dark:text-fd-navy',
|
||||||
secondaryBtn: 'border-2 border-fd-navy text-fd-navy hover:bg-fd-navy/10',
|
secondaryBtn: 'border-2 border-fd-navy text-fd-navy hover:bg-fd-navy/10 dark:border-white dark:text-white dark:hover:bg-white/10',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const sizeMap: Record<string, { py: string; heading: string; sub: string }> = {
|
const sizeMap: Record<string, { py: string; heading: string; sub: string }> = {
|
||||||
small: { py: 'py-10 md:py-14', heading: 'text-2xl md:text-3xl lg:text-4xl', sub: 'text-base md:text-lg' },
|
small: { py: 'py-10 md:py-14', heading: 'text-fd-h2', sub: 'text-fd-body' },
|
||||||
medium: { py: 'py-14 md:py-20 lg:py-[80px]', heading: 'text-3xl md:text-4xl lg:text-5xl', sub: 'text-lg md:text-xl' },
|
medium: { py: 'py-14 md:py-20 lg:py-[80px]', heading: 'text-fd-h1', sub: 'text-fd-body-lg' },
|
||||||
large: { py: 'py-16 md:py-24 lg:py-[99px]', heading: 'text-4xl md:text-5xl lg:text-[64px]', sub: 'text-xl md:text-2xl' },
|
large: { py: 'py-16 md:py-24 lg:py-[99px]', heading: 'text-fd-display', sub: 'text-fd-body-lg' },
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FDCtaBannerBlockComponent: React.FC<FDCtaBannerBlockProps> = ({
|
export const FDCtaBannerBlockComponent: React.FC<FDCtaBannerBlockProps> = ({
|
||||||
@ -50,8 +52,8 @@ export const FDCtaBannerBlockComponent: React.FC<FDCtaBannerBlockProps> = ({
|
|||||||
alignment = 'center',
|
alignment = 'center',
|
||||||
size = 'medium',
|
size = 'medium',
|
||||||
}) => {
|
}) => {
|
||||||
const theme = bgMap[sectionBackground] || bgMap.yellow
|
const theme = bgMap[sectionBackground ?? 'yellow'] || bgMap.yellow
|
||||||
const sizing = sizeMap[size] || sizeMap.medium
|
const sizing = sizeMap[size ?? 'medium'] || sizeMap.medium
|
||||||
const isCenter = alignment === 'center'
|
const isCenter = alignment === 'center'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -75,7 +77,7 @@ export const FDCtaBannerBlockComponent: React.FC<FDCtaBannerBlockProps> = ({
|
|||||||
{ctaText && (
|
{ctaText && (
|
||||||
<a
|
<a
|
||||||
href={ctaLink || '#'}
|
href={ctaLink || '#'}
|
||||||
className={`inline-flex items-center justify-center px-8 py-3 rounded-full font-joey-bold text-lg transition-colors ${theme.primaryBtn}`}
|
className={`inline-flex items-center justify-center px-8 py-3 rounded-full font-joey-bold text-fd-btn transition-colors ${theme.primaryBtn}`}
|
||||||
>
|
>
|
||||||
{ctaText}
|
{ctaText}
|
||||||
</a>
|
</a>
|
||||||
@ -83,7 +85,7 @@ export const FDCtaBannerBlockComponent: React.FC<FDCtaBannerBlockProps> = ({
|
|||||||
{secondaryCtaText && secondaryCtaLink && (
|
{secondaryCtaText && secondaryCtaLink && (
|
||||||
<a
|
<a
|
||||||
href={secondaryCtaLink}
|
href={secondaryCtaLink}
|
||||||
className={`inline-flex items-center justify-center px-8 py-3 rounded-full font-joey-bold text-lg transition-colors ${theme.secondaryBtn}`}
|
className={`inline-flex items-center justify-center px-8 py-3 rounded-full font-joey-bold text-fd-btn transition-colors ${theme.secondaryBtn}`}
|
||||||
>
|
>
|
||||||
{secondaryCtaText}
|
{secondaryCtaText}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -16,26 +16,32 @@ export const FDCtaSideImageBlockComponent: React.FC<FDCtaSideImageBlockProps> =
|
|||||||
const isDark = theme === 'dark'
|
const isDark = theme === 'dark'
|
||||||
const hasImage = !!image
|
const hasImage = !!image
|
||||||
|
|
||||||
|
// Light theme adapts to OS dark preference → becomes navy bg
|
||||||
|
const sectionBg = isDark
|
||||||
|
? 'bg-fd-navy'
|
||||||
|
: 'bg-white dark:bg-fd-navy'
|
||||||
|
|
||||||
|
const headingClass = isDark
|
||||||
|
? 'text-fd-yellow'
|
||||||
|
: 'text-fd-navy dark:text-fd-yellow'
|
||||||
|
|
||||||
|
const bodyClass = isDark
|
||||||
|
? 'text-white'
|
||||||
|
: 'text-fd-navy dark:text-white'
|
||||||
|
|
||||||
const textContent = (
|
const textContent = (
|
||||||
<div className={`flex flex-col flex-1 items-start gap-8 lg:gap-[41px] ${!hasImage ? 'max-w-2xl' : ''}`}>
|
<div className={`flex flex-col flex-1 items-start gap-8 lg:gap-[41px] ${!hasImage ? 'max-w-2xl' : ''}`}>
|
||||||
<div className="flex flex-col items-start gap-4 w-full">
|
<div className="flex flex-col items-start gap-4 w-full">
|
||||||
<h2
|
<h2 className={`w-full font-joey-heavy text-fd-h1 leading-tight ${headingClass}`}>
|
||||||
className={`w-full font-joey-heavy text-fd-h1 leading-tight ${
|
|
||||||
isDark ? 'text-fd-yellow' : 'text-fd-navy'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{heading}
|
{heading}
|
||||||
</h2>
|
</h2>
|
||||||
<p
|
<p className={`w-full font-joey text-fd-body-lg leading-relaxed ${bodyClass}`}>
|
||||||
className={`w-full font-joey text-fd-body-lg leading-relaxed ${
|
|
||||||
isDark ? 'text-white' : 'text-fd-navy'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{body}
|
{body}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ctaText && (
|
{ctaText && (
|
||||||
|
// onDark — either explicit dark theme, or dark: mode makes it navy anyway
|
||||||
<FDButton href={ctaLink || '#'} variant="primary" onDark={isDark}>
|
<FDButton href={ctaLink || '#'} variant="primary" onDark={isDark}>
|
||||||
{ctaText}
|
{ctaText}
|
||||||
</FDButton>
|
</FDButton>
|
||||||
@ -56,19 +62,12 @@ export const FDCtaSideImageBlockComponent: React.FC<FDCtaSideImageBlockProps> =
|
|||||||
) : null
|
) : null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// FIX: added md:py-20 so tablet gets correct spacing
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${isDark ? 'bg-fd-navy' : 'bg-white'}`}>
|
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col lg:flex-row items-center gap-10 lg:gap-16">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col lg:flex-row items-center gap-10 lg:gap-16">
|
||||||
{imagePosition === 'left' ? (
|
{imagePosition === 'left' ? (
|
||||||
<>
|
<>{imageContent}{textContent}</>
|
||||||
{imageContent}
|
|
||||||
{textContent}
|
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>{textContent}{imageContent}</>
|
||||||
{textContent}
|
|
||||||
{imageContent}
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -10,16 +10,29 @@ export const FDFaqBlockComponent: React.FC<FDFaqBlockProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const [openIndex, setOpenIndex] = useState<number | null>(null)
|
const [openIndex, setOpenIndex] = useState<number | null>(null)
|
||||||
|
|
||||||
|
// dark theme = always navy. gray/white adapt via dark: OS preference
|
||||||
const bgClass =
|
const bgClass =
|
||||||
theme === 'dark'
|
theme === 'dark'
|
||||||
? 'bg-fd-navy'
|
? 'bg-fd-navy'
|
||||||
: theme === 'gray'
|
: theme === 'gray'
|
||||||
? 'bg-fd-gray-light'
|
? 'bg-fd-gray-light dark:bg-fd-navy'
|
||||||
: 'bg-white'
|
: 'bg-white dark:bg-fd-navy'
|
||||||
const headingColor = theme === 'dark' ? 'text-fd-yellow' : 'text-fd-navy'
|
|
||||||
const textColor = theme === 'dark' ? 'text-white' : 'text-fd-navy'
|
const headingColor = theme === 'dark'
|
||||||
const borderColor = theme === 'dark' ? 'border-white/20' : 'border-fd-navy/10'
|
? 'text-fd-yellow'
|
||||||
const proseColor = theme === 'dark' ? 'text-white/80' : 'text-fd-navy/80'
|
: 'text-fd-navy dark:text-fd-yellow'
|
||||||
|
|
||||||
|
const textColor = theme === 'dark'
|
||||||
|
? 'text-white'
|
||||||
|
: 'text-fd-navy dark:text-white'
|
||||||
|
|
||||||
|
const borderColor = theme === 'dark'
|
||||||
|
? 'border-white/20'
|
||||||
|
: 'border-fd-navy/10 dark:border-white/20'
|
||||||
|
|
||||||
|
const proseColor = theme === 'dark'
|
||||||
|
? 'text-white/80'
|
||||||
|
: 'text-fd-navy/80 dark:text-white/80'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-16 md:py-20 lg:py-[130px] ${bgClass}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[130px] ${bgClass}`}>
|
||||||
|
|||||||
@ -11,21 +11,36 @@ export const FDFeatureAnnouncementBlockComponent: React.FC<FDFeatureAnnouncement
|
|||||||
}) => {
|
}) => {
|
||||||
const isDark = theme === 'dark'
|
const isDark = theme === 'dark'
|
||||||
|
|
||||||
const bgClass = isDark ? 'bg-fd-navy' : theme === 'gray' ? 'bg-fd-gray' : 'bg-white'
|
// Light themes pick up dark: variants from OS preference
|
||||||
const headingColor = isDark ? 'text-fd-yellow' : 'text-fd-navy'
|
const bgClass =
|
||||||
const bodyColor = isDark ? 'text-white' : 'text-fd-navy'
|
isDark
|
||||||
|
? 'bg-fd-navy'
|
||||||
|
: theme === 'gray'
|
||||||
|
? 'bg-fd-gray-light dark:bg-fd-navy'
|
||||||
|
: 'bg-white dark:bg-fd-navy'
|
||||||
|
|
||||||
|
const headingColor = isDark
|
||||||
|
? 'text-fd-yellow'
|
||||||
|
: 'text-fd-navy dark:text-fd-yellow'
|
||||||
|
|
||||||
|
const bodyColor = isDark
|
||||||
|
? 'text-white'
|
||||||
|
: 'text-fd-navy dark:text-white'
|
||||||
|
|
||||||
|
// In dark mode the section is always navy, so onDark=true for the button
|
||||||
|
const onDark = isDark || true // once dark: kicks in bg is navy anyway
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-20 md:py-28 lg:py-[173px] ${bgClass}`}>
|
<section className={`w-full py-20 md:py-28 lg:py-[173px] ${bgClass}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col items-center gap-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col items-center gap-8">
|
||||||
<h2
|
<h2
|
||||||
className={`w-full max-w-[696px] font-joey-bold text-3xl md:text-4xl lg:text-[54px] text-center leading-tight lg:leading-[64.8px] ${headingColor}`}
|
className={`w-full max-w-[696px] font-joey-bold text-fd-h1 text-center leading-tight ${headingColor}`}
|
||||||
>
|
>
|
||||||
{heading}
|
{heading}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
className={`w-full max-w-[1112px] font-joey text-xl md:text-2xl lg:text-4xl text-center leading-relaxed lg:leading-[44px] ${bodyColor}`}
|
className={`w-full max-w-[1112px] font-joey text-xl md:text-2xl lg:text-4xl text-center leading-relaxed ${bodyColor}`}
|
||||||
>
|
>
|
||||||
{body}
|
{body}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -3,31 +3,38 @@ import type { FDHeaderTextImageBlock as FDHeaderTextImageBlockProps, Media } fro
|
|||||||
import { FDImage } from '@/components/FDImage'
|
import { FDImage } from '@/components/FDImage'
|
||||||
|
|
||||||
const bgMap: Record<string, string> = {
|
const bgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
}
|
}
|
||||||
|
|
||||||
const textMap: Record<string, string> = {
|
// Heading: navy→yellow in dark, white stays white
|
||||||
navy: 'text-fd-navy',
|
const headingMap: Record<string, string> = {
|
||||||
|
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||||
|
white: 'text-white',
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body: navy→white in dark, white stays white
|
||||||
|
const bodyMap: Record<string, string> = {
|
||||||
|
navy: 'text-fd-navy dark:text-white',
|
||||||
white: 'text-white',
|
white: 'text-white',
|
||||||
}
|
}
|
||||||
|
|
||||||
const overlayMap: Record<string, string> = {
|
const overlayMap: Record<string, string> = {
|
||||||
none: '',
|
none: '',
|
||||||
navyLight: 'bg-fd-navy/20',
|
navyLight: 'bg-fd-navy/20',
|
||||||
navyMedium: 'bg-fd-navy/40',
|
navyMedium: 'bg-fd-navy/40',
|
||||||
yellowLight: 'bg-fd-yellow/20',
|
yellowLight: 'bg-fd-yellow/20',
|
||||||
yellowMedium: 'bg-fd-yellow/40',
|
yellowMedium:'bg-fd-yellow/40',
|
||||||
sepia: 'bg-[#8B7D3C]/30',
|
sepia: 'bg-[#8B7D3C]/30',
|
||||||
blackLight: 'bg-black/20',
|
blackLight: 'bg-black/20',
|
||||||
blackMedium: 'bg-black/40',
|
blackMedium: 'bg-black/40',
|
||||||
}
|
}
|
||||||
|
|
||||||
const roundedMap: Record<string, string> = {
|
const roundedMap: Record<string, string> = {
|
||||||
none: '',
|
none: '',
|
||||||
medium: 'rounded-[24px]',
|
medium: 'rounded-[24px]',
|
||||||
large: 'rounded-[40px]',
|
large: 'rounded-[40px]',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FDHeaderTextImageBlockComponent: React.FC<FDHeaderTextImageBlockProps> = ({
|
export const FDHeaderTextImageBlockComponent: React.FC<FDHeaderTextImageBlockProps> = ({
|
||||||
@ -40,23 +47,24 @@ export const FDHeaderTextImageBlockComponent: React.FC<FDHeaderTextImageBlockPro
|
|||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
textColor = 'navy',
|
textColor = 'navy',
|
||||||
}) => {
|
}) => {
|
||||||
const bg = bgMap[sectionBackground || 'white']
|
const bg = bgMap[sectionBackground || 'white']
|
||||||
const txt = textMap[textColor || 'navy']
|
const headClr = headingMap[textColor || 'navy']
|
||||||
|
const bodyClr = bodyMap[textColor || 'navy']
|
||||||
const overlay = overlayMap[imageOverlay || 'none']
|
const overlay = overlayMap[imageOverlay || 'none']
|
||||||
const rounded = roundedMap[imageRounded || 'large']
|
const rounded = roundedMap[imageRounded || 'large']
|
||||||
const align = textAlign === 'center' ? 'text-center' : 'text-left'
|
const align = textAlign === 'center' ? 'text-center' : 'text-left'
|
||||||
const media = image as Media
|
const media = image as Media
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${bg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col gap-8 md:gap-10">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col gap-8 md:gap-10">
|
||||||
{(heading || body) && (
|
{(heading || body) && (
|
||||||
<div className={`flex flex-col gap-4 md:gap-6 ${align} ${textAlign === 'center' ? 'max-w-[900px] mx-auto' : ''}`}>
|
<div className={`flex flex-col gap-4 md:gap-6 ${align} ${textAlign === 'center' ? 'max-w-[900px] mx-auto' : ''}`}>
|
||||||
{heading && (
|
{heading && (
|
||||||
<h2 className={`font-joey-heavy text-fd-h1 ${txt}`}>{heading}</h2>
|
<h2 className={`font-joey-heavy text-fd-h1 ${headClr}`}>{heading}</h2>
|
||||||
)}
|
)}
|
||||||
{body && (
|
{body && (
|
||||||
<p className={`font-joey text-fd-body ${txt} opacity-80`}>{body}</p>
|
<p className={`font-joey text-fd-body-lg ${bodyClr} opacity-80`}>{body}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -3,22 +3,28 @@ import type { FDIconBarBlock as FDIconBarBlockProps, Media } from '@/payload-typ
|
|||||||
import { FDImage } from '@/components/FDImage'
|
import { FDImage } from '@/components/FDImage'
|
||||||
|
|
||||||
const bgMap: Record<string, string> = {
|
const bgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
yellow: 'bg-fd-yellow',
|
yellow: 'bg-fd-yellow',
|
||||||
}
|
}
|
||||||
|
|
||||||
const textColorMap: Record<string, string> = {
|
const headingMap: Record<string, string> = {
|
||||||
navy: 'text-fd-navy',
|
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||||
white: 'text-white',
|
white: 'text-white',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const labelMap: Record<string, string> = {
|
||||||
|
navy: 'text-fd-navy dark:text-white',
|
||||||
|
white: 'text-white',
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon circle bg — navy circles become yellow-tinted in dark when on a now-navy section
|
||||||
const iconBgMap: Record<string, string> = {
|
const iconBgMap: Record<string, string> = {
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy dark:bg-white/10',
|
||||||
yellow: 'bg-fd-yellow',
|
yellow: 'bg-fd-yellow',
|
||||||
gray: 'bg-[#e5e5e5]',
|
gray: 'bg-fd-gray-light dark:bg-white/10',
|
||||||
none: '',
|
none: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FDIconBarBlockComponent: React.FC<FDIconBarBlockProps> = ({
|
export const FDIconBarBlockComponent: React.FC<FDIconBarBlockProps> = ({
|
||||||
@ -28,16 +34,17 @@ export const FDIconBarBlockComponent: React.FC<FDIconBarBlockProps> = ({
|
|||||||
sectionBackground = 'gray',
|
sectionBackground = 'gray',
|
||||||
textColor = 'navy',
|
textColor = 'navy',
|
||||||
}) => {
|
}) => {
|
||||||
const bg = bgMap[sectionBackground || 'gray']
|
const bg = bgMap[sectionBackground || 'gray']
|
||||||
const txtColor = textColorMap[textColor || 'navy']
|
const headClr = headingMap[textColor || 'navy']
|
||||||
const iconBg = iconBgMap[iconStyle || 'navy']
|
const labelClr = labelMap[textColor || 'navy']
|
||||||
|
const iconBg = iconBgMap[iconStyle || 'navy']
|
||||||
const hasCircle = iconStyle !== 'none'
|
const hasCircle = iconStyle !== 'none'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${bg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
{heading && (
|
{heading && (
|
||||||
<h2 className={`font-joey-heavy text-fd-h1 mb-10 md:mb-14 ${txtColor}`}>
|
<h2 className={`font-joey-heavy text-fd-h1 mb-10 md:mb-14 ${headClr}`}>
|
||||||
{heading}
|
{heading}
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
@ -61,7 +68,7 @@ export const FDIconBarBlockComponent: React.FC<FDIconBarBlockProps> = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<span className={`font-joey-bold text-fd-body text-center ${txtColor}`}>
|
<span className={`font-joey-bold text-fd-body text-center ${labelClr}`}>
|
||||||
{item.label}
|
{item.label}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -12,18 +12,24 @@ export const FDLocationsGridBlockComponent: React.FC<Props> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const bgClass =
|
const bgClass =
|
||||||
sectionBackground === 'navy' ? 'bg-fd-navy' :
|
sectionBackground === 'navy' ? 'bg-fd-navy' :
|
||||||
sectionBackground === 'gray' ? 'bg-fd-surface-alt' : 'bg-white'
|
sectionBackground === 'gray' ? 'bg-fd-gray-light dark:bg-fd-navy' :
|
||||||
|
'bg-white dark:bg-fd-navy'
|
||||||
|
|
||||||
const titleClass = sectionBackground === 'navy' ? 'text-fd-yellow' : 'text-fd-navy'
|
const titleClass = sectionBackground === 'navy'
|
||||||
const bodyClass = sectionBackground === 'navy' ? 'text-white' : 'text-fd-navy'
|
? 'text-fd-yellow'
|
||||||
|
: 'text-fd-navy dark:text-fd-yellow'
|
||||||
|
|
||||||
|
const bodyClass = sectionBackground === 'navy'
|
||||||
|
? 'text-white'
|
||||||
|
: 'text-fd-navy dark:text-white'
|
||||||
|
|
||||||
const hoverBgClass =
|
const hoverBgClass =
|
||||||
hoverColor === 'yellow' ? 'bg-fd-yellow' :
|
hoverColor === 'yellow' ? 'bg-fd-yellow' :
|
||||||
hoverColor === 'mint' ? 'bg-fd-mint' : 'bg-fd-navy'
|
hoverColor === 'mint' ? 'bg-fd-mint' : 'bg-fd-navy'
|
||||||
|
|
||||||
const hoverTextClass =
|
const hoverTextClass =
|
||||||
hoverColor === 'yellow' ? 'text-fd-navy' :
|
hoverColor === 'yellow' ? 'text-fd-navy' :
|
||||||
hoverColor === 'mint' ? 'text-fd-navy' : 'text-white'
|
hoverColor === 'mint' ? 'text-fd-navy' : 'text-white'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bgClass}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bgClass}`}>
|
||||||
@ -51,8 +57,8 @@ export const FDLocationsGridBlockComponent: React.FC<Props> = ({
|
|||||||
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6">
|
||||||
{(cards ?? []).map((card, i) => {
|
{(cards ?? []).map((card, i) => {
|
||||||
const media = card.image as Media | undefined
|
const media = card.image as Media | undefined
|
||||||
const isLink = Boolean(card.link)
|
const isLink = Boolean(card.link)
|
||||||
const className = `group relative overflow-hidden rounded-[30px] md:rounded-[50px] aspect-[4/3] block ${isLink ? 'cursor-pointer' : ''}`
|
const className = `group relative overflow-hidden rounded-[30px] md:rounded-[50px] aspect-[4/3] block ${isLink ? 'cursor-pointer' : ''}`
|
||||||
|
|
||||||
const inner = (
|
const inner = (
|
||||||
|
|||||||
@ -8,22 +8,23 @@ export const FDPartnersLogosBlockComponent: React.FC<FDPartnersLogosBlockProps>
|
|||||||
sectionBackground = 'gray',
|
sectionBackground = 'gray',
|
||||||
}) => {
|
}) => {
|
||||||
const bgClass =
|
const bgClass =
|
||||||
sectionBackground === 'navy'
|
sectionBackground === 'navy' ? 'bg-fd-navy' :
|
||||||
? 'bg-fd-navy'
|
sectionBackground === 'gray' ? 'bg-fd-gray-light dark:bg-fd-navy' :
|
||||||
: sectionBackground === 'gray'
|
'bg-white dark:bg-fd-navy'
|
||||||
? 'bg-fd-surface-alt'
|
|
||||||
: 'bg-white'
|
|
||||||
|
|
||||||
const titleClass = sectionBackground === 'navy' ? 'text-fd-yellow' : 'text-fd-navy'
|
const titleClass = sectionBackground === 'navy'
|
||||||
|
? 'text-fd-yellow'
|
||||||
|
: 'text-fd-navy dark:text-fd-yellow'
|
||||||
|
|
||||||
|
// In dark mode, monochrome logos invert to be visible on navy bg
|
||||||
const imgFilter =
|
const imgFilter =
|
||||||
displayMode === 'monochrome'
|
displayMode === 'monochrome'
|
||||||
? 'grayscale opacity-40 hover:grayscale-0 hover:opacity-100 transition-all duration-500'
|
? 'grayscale opacity-40 hover:grayscale-0 hover:opacity-100 dark:invert dark:opacity-50 dark:hover:opacity-100 transition-all duration-500'
|
||||||
: 'hover:opacity-80 transition-opacity duration-300'
|
: 'hover:opacity-80 transition-opacity duration-300'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`fd-section ${bgClass}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bgClass}`}>
|
||||||
<div className="fd-container">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
{heading && (
|
{heading && (
|
||||||
<h2 className={`font-joey-medium text-fd-h2 text-center mb-10 md:mb-14 ${titleClass}`}>
|
<h2 className={`font-joey-medium text-fd-h2 text-center mb-10 md:mb-14 ${titleClass}`}>
|
||||||
{heading}
|
{heading}
|
||||||
|
|||||||
@ -3,14 +3,14 @@ import type { FDPricingCardBlock as FDPricingCardBlockProps } from '@/payload-ty
|
|||||||
import { FDButton } from '@/components/FDButton'
|
import { FDButton } from '@/components/FDButton'
|
||||||
|
|
||||||
const sectionBgMap: Record<string, string> = {
|
const sectionBgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
yellow: 'bg-fd-yellow',
|
yellow: 'bg-fd-yellow',
|
||||||
}
|
}
|
||||||
|
|
||||||
const titleColorMap: Record<string, string> = {
|
const titleColorMap: Record<string, string> = {
|
||||||
navy: 'text-fd-navy',
|
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||||
white: 'text-white',
|
white: 'text-white',
|
||||||
yellow: 'text-fd-yellow',
|
yellow: 'text-fd-yellow',
|
||||||
}
|
}
|
||||||
@ -19,11 +19,41 @@ const cardStyleMap: Record<string, {
|
|||||||
bg: string; border: string; title: string
|
bg: string; border: string; title: string
|
||||||
subtitle: string; body: string; bullet: string; isDark: boolean
|
subtitle: string; body: string; bullet: string; isDark: boolean
|
||||||
}> = {
|
}> = {
|
||||||
outlined: { bg: 'bg-white', border: 'border-[2px] border-[#d1d5db]', title: 'text-fd-navy', subtitle: 'text-fd-navy', body: 'text-fd-navy/80', bullet: 'text-fd-navy', isDark: false },
|
outlined: {
|
||||||
navy: { bg: 'bg-fd-navy', border: '', title: 'text-fd-yellow', subtitle: 'text-white', body: 'text-white/80', bullet: 'text-white', isDark: true },
|
bg: 'bg-white dark:bg-white/10',
|
||||||
gray: { bg: 'bg-fd-gray-light', border: '', title: 'text-fd-navy', subtitle: 'text-fd-navy', body: 'text-fd-navy/80', bullet: 'text-fd-navy', isDark: false },
|
border: 'border-[2px] border-gray-200 dark:border-white/20',
|
||||||
yellow: { bg: 'bg-fd-yellow', border: '', title: 'text-fd-navy', subtitle: 'text-fd-navy', body: 'text-fd-navy/80', bullet: 'text-fd-navy', isDark: false },
|
title: 'text-fd-navy dark:text-fd-yellow',
|
||||||
white: { bg: 'bg-white shadow-lg', border: '', title: 'text-fd-navy', subtitle: 'text-fd-navy', body: 'text-fd-navy/80', bullet: 'text-fd-navy', isDark: false },
|
subtitle: 'text-fd-navy dark:text-white',
|
||||||
|
body: 'text-fd-navy/80 dark:text-white/80',
|
||||||
|
bullet: 'text-fd-navy dark:text-white',
|
||||||
|
isDark: false,
|
||||||
|
},
|
||||||
|
navy: {
|
||||||
|
bg: 'bg-fd-navy', border: '', title: 'text-fd-yellow',
|
||||||
|
subtitle: 'text-white', body: 'text-white/80', bullet: 'text-white', isDark: true,
|
||||||
|
},
|
||||||
|
gray: {
|
||||||
|
bg: 'bg-fd-gray-light dark:bg-white/10',
|
||||||
|
border: '',
|
||||||
|
title: 'text-fd-navy dark:text-white',
|
||||||
|
subtitle: 'text-fd-navy dark:text-white',
|
||||||
|
body: 'text-fd-navy/80 dark:text-white/80',
|
||||||
|
bullet: 'text-fd-navy dark:text-white',
|
||||||
|
isDark: false,
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
bg: 'bg-fd-yellow', border: '', title: 'text-fd-navy',
|
||||||
|
subtitle: 'text-fd-navy', body: 'text-fd-navy/80', bullet: 'text-fd-navy', isDark: false,
|
||||||
|
},
|
||||||
|
white: {
|
||||||
|
bg: 'bg-white dark:bg-white/10 shadow-lg dark:shadow-none',
|
||||||
|
border: '',
|
||||||
|
title: 'text-fd-navy dark:text-fd-yellow',
|
||||||
|
subtitle: 'text-fd-navy dark:text-white',
|
||||||
|
body: 'text-fd-navy/80 dark:text-white/80',
|
||||||
|
bullet: 'text-fd-navy dark:text-white',
|
||||||
|
isDark: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttonVariantMap: Record<string, { variant: 'primary' | 'outline' }> = {
|
const buttonVariantMap: Record<string, { variant: 'primary' | 'outline' }> = {
|
||||||
@ -47,13 +77,13 @@ export const FDPricingCardBlockComponent: React.FC<FDPricingCardBlockProps> = ({
|
|||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
titleColor = 'navy',
|
titleColor = 'navy',
|
||||||
}) => {
|
}) => {
|
||||||
const sectionBg = sectionBgMap[sectionBackground || 'white']
|
const sectionBg = sectionBgMap[sectionBackground || 'white']
|
||||||
const sectionTitleColor = titleColorMap[titleColor || 'navy']
|
const sectionTitleColor = titleColorMap[titleColor || 'navy']
|
||||||
const style = cardStyleMap[cardStyle || 'outlined']
|
const style = cardStyleMap[cardStyle || 'outlined']
|
||||||
const { variant } = buttonVariantMap[buttonColor || 'yellow']
|
const { variant } = buttonVariantMap[buttonColor || 'yellow']
|
||||||
const cardCount = cards?.length || 1
|
const cardCount = cards?.length || 1
|
||||||
const gridCols = gridColsMap[cardCount] || gridColsMap[3]
|
const gridCols = gridColsMap[cardCount] || gridColsMap[3]
|
||||||
const outlineOnDark = style.isDark
|
const outlineOnDark = style.isDark
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
@ -63,7 +93,6 @@ export const FDPricingCardBlockComponent: React.FC<FDPricingCardBlockProps> = ({
|
|||||||
{sectionTitle}
|
{sectionTitle}
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
{/* FIX: rounded-[32px] → rounded-[70px] per design system */}
|
|
||||||
<div className={`grid grid-cols-1 ${gridCols} gap-6 md:gap-8`}>
|
<div className={`grid grid-cols-1 ${gridCols} gap-6 md:gap-8`}>
|
||||||
{cards?.map((card, index) => (
|
{cards?.map((card, index) => (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -14,10 +14,9 @@ export const FDServicesGridBlockComponent: React.FC<FDServicesGridBlockProps> =
|
|||||||
columns = '4',
|
columns = '4',
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
// FIX: lg:py-24 → lg:py-[99px] (standard section padding)
|
<section className="relative w-full bg-white dark:bg-fd-navy py-16 md:py-20 lg:py-[99px]">
|
||||||
<section className="relative w-full bg-white py-16 md:py-20 lg:py-[99px]">
|
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
<h2 className="font-joey-heavy text-fd-h1 text-fd-navy mb-8 lg:mb-12">
|
<h2 className="font-joey-heavy text-fd-h1 text-fd-navy dark:text-fd-yellow mb-8 lg:mb-12">
|
||||||
{heading}
|
{heading}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ export const FDServicesGridBlockComponent: React.FC<FDServicesGridBlockProps> =
|
|||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<div className="flex flex-col gap-4 md:gap-6 lg:gap-[30px]">
|
<div className="flex flex-col gap-4 md:gap-6 lg:gap-[30px]">
|
||||||
<h3 className="font-joey-bold text-fd-navy text-fd-h2">
|
<h3 className="font-joey-bold text-fd-navy dark:text-white text-fd-h2">
|
||||||
{service.title}
|
{service.title}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
@ -41,7 +40,7 @@ export const FDServicesGridBlockComponent: React.FC<FDServicesGridBlockProps> =
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<p className="font-joey text-fd-navy text-fd-body">
|
<p className="font-joey text-fd-navy dark:text-white/80 text-fd-body">
|
||||||
{service.description}
|
{service.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,10 +9,10 @@ const heightMap: Record<string, string> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bgMap: Record<string, string> = {
|
const bgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
yellow: 'bg-fd-yellow',
|
yellow: 'bg-fd-yellow',
|
||||||
transparent: 'bg-transparent',
|
transparent: 'bg-transparent',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,17 +22,24 @@ export const FDStatisticsBlockComponent: React.FC<Props> = ({
|
|||||||
|
|
||||||
const bgClass =
|
const bgClass =
|
||||||
sectionBackground === 'navy' ? 'bg-fd-navy' :
|
sectionBackground === 'navy' ? 'bg-fd-navy' :
|
||||||
sectionBackground === 'gray' ? 'bg-fd-surface-alt' : 'bg-white'
|
sectionBackground === 'gray' ? 'bg-fd-gray-light dark:bg-fd-navy' :
|
||||||
|
'bg-white dark:bg-fd-navy'
|
||||||
|
|
||||||
const titleClass = sectionBackground === 'navy' ? 'text-fd-yellow' : 'text-fd-navy'
|
const titleClass = sectionBackground === 'navy'
|
||||||
const labelClass = sectionBackground === 'navy' ? 'text-white' : 'text-fd-navy'
|
? 'text-fd-yellow'
|
||||||
|
: 'text-fd-navy dark:text-fd-yellow'
|
||||||
|
|
||||||
|
const labelClass = sectionBackground === 'navy'
|
||||||
|
? 'text-white'
|
||||||
|
: 'text-fd-navy dark:text-white'
|
||||||
|
|
||||||
const getNumberClass = () => {
|
const getNumberClass = () => {
|
||||||
if (numberColor === 'gradient') return 'bg-gradient-to-r from-fd-yellow to-fd-mint bg-clip-text text-transparent'
|
if (numberColor === 'gradient') return 'bg-gradient-to-r from-fd-yellow to-fd-mint bg-clip-text text-transparent'
|
||||||
if (numberColor === 'yellow') return 'text-fd-yellow'
|
if (numberColor === 'yellow') return 'text-fd-yellow'
|
||||||
if (numberColor === 'mint') return 'text-fd-mint'
|
if (numberColor === 'mint') return 'text-fd-mint'
|
||||||
if (numberColor === 'white') return 'text-white'
|
if (numberColor === 'white') return 'text-white'
|
||||||
return 'text-fd-navy'
|
// navy number adapts in dark mode
|
||||||
|
return 'text-fd-navy dark:text-white'
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -52,7 +59,6 @@ export const FDStatisticsBlockComponent: React.FC<Props> = ({
|
|||||||
}`}
|
}`}
|
||||||
style={{ transitionDelay: `${i * 120}ms` }}
|
style={{ transitionDelay: `${i * 120}ms` }}
|
||||||
>
|
>
|
||||||
{/* Intentionally oversized for visual impact — not mapped to fd-* token */}
|
|
||||||
<span className={`font-joey-heavy text-5xl md:text-7xl lg:text-[96px] leading-none ${getNumberClass()}`}>
|
<span className={`font-joey-heavy text-5xl md:text-7xl lg:text-[96px] leading-none ${getNumberClass()}`}>
|
||||||
{stat.number}
|
{stat.number}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -2,10 +2,10 @@ import React from 'react'
|
|||||||
import type { FDTagsBlock as FDTagsBlockProps } from '@/payload-types'
|
import type { FDTagsBlock as FDTagsBlockProps } from '@/payload-types'
|
||||||
|
|
||||||
const tagStyleMap: Record<string, { bg: string; text: string; border: string }> = {
|
const tagStyleMap: Record<string, { bg: string; text: string; border: string }> = {
|
||||||
navy: { bg: 'bg-fd-navy', text: 'text-fd-yellow', border: '' },
|
navy: { bg: 'bg-fd-navy', text: 'text-fd-yellow', border: '' },
|
||||||
yellow: { bg: 'bg-fd-yellow', text: 'text-fd-navy', border: '' },
|
yellow: { bg: 'bg-fd-yellow', text: 'text-fd-navy', border: '' },
|
||||||
outlined: { bg: 'bg-transparent', text: 'text-fd-navy', border: 'border-2 border-fd-navy' },
|
outlined: { bg: 'bg-transparent', text: 'text-fd-navy dark:text-white', border: 'border-2 border-fd-navy dark:border-white' },
|
||||||
gray: { bg: 'bg-fd-surface-alt', text: 'text-fd-navy', border: '' },
|
gray: { bg: 'bg-fd-gray-light dark:bg-white/10', text: 'text-fd-navy dark:text-white', border: '' },
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagSizeMap: Record<string, string> = {
|
const tagSizeMap: Record<string, string> = {
|
||||||
@ -15,15 +15,15 @@ const tagSizeMap: Record<string, string> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sectionBgMap: Record<string, string> = {
|
const sectionBgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
}
|
}
|
||||||
|
|
||||||
const headingColorMap: Record<string, string> = {
|
const headingColorMap: Record<string, string> = {
|
||||||
white: 'text-fd-navy',
|
white: 'text-fd-navy dark:text-fd-yellow',
|
||||||
navy: 'text-fd-yellow',
|
navy: 'text-fd-yellow',
|
||||||
gray: 'text-fd-navy',
|
gray: 'text-fd-navy dark:text-fd-yellow',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FDTagsBlockComponent: React.FC<FDTagsBlockProps> = ({
|
export const FDTagsBlockComponent: React.FC<FDTagsBlockProps> = ({
|
||||||
@ -34,14 +34,14 @@ export const FDTagsBlockComponent: React.FC<FDTagsBlockProps> = ({
|
|||||||
alignment = 'left',
|
alignment = 'left',
|
||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
}) => {
|
}) => {
|
||||||
const style = tagStyleMap[tagStyle ?? 'navy'] || tagStyleMap.navy
|
const style = tagStyleMap[tagStyle ?? 'navy'] || tagStyleMap.navy
|
||||||
const size = tagSizeMap[tagSize ?? 'large'] || tagSizeMap.large
|
const size = tagSizeMap[tagSize ?? 'large'] || tagSizeMap.large
|
||||||
const sectionBg = sectionBgMap[sectionBackground || 'white']
|
const sectionBg = sectionBgMap[sectionBackground || 'white']
|
||||||
const headingColor = headingColorMap[sectionBackground || 'white']
|
const headingColor = headingColorMap[sectionBackground || 'white']
|
||||||
const justify = alignment === 'center' ? 'justify-center' : 'justify-start'
|
const justify = alignment === 'center' ? 'justify-center' : 'justify-start'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${sectionBg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
{heading && (
|
{heading && (
|
||||||
<h2
|
<h2
|
||||||
|
|||||||
@ -3,15 +3,33 @@ import type { FDTeamBlock as FDTeamBlockProps, Media } from '@/payload-types'
|
|||||||
import { FDImage } from '@/components/FDImage'
|
import { FDImage } from '@/components/FDImage'
|
||||||
|
|
||||||
const sectionBgMap: Record<string, string> = {
|
const sectionBgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
}
|
}
|
||||||
|
|
||||||
const cardMap: Record<string, { bg: string; name: string; role: string; bio: string; icon: string }> = {
|
const cardMap: Record<string, { bg: string; name: string; role: string; bio: string; icon: string }> = {
|
||||||
navy: { bg: 'bg-fd-navy', name: 'text-fd-yellow', role: 'text-white/70', bio: 'text-white/60', icon: 'text-white/40 hover:text-fd-yellow' },
|
navy: {
|
||||||
white: { bg: 'bg-white', name: 'text-fd-navy', role: 'text-fd-navy/60', bio: 'text-fd-navy/60', icon: 'text-fd-navy/40 hover:text-fd-navy' },
|
bg: 'bg-fd-navy',
|
||||||
gray: { bg: 'bg-fd-gray-light', name: 'text-fd-navy', role: 'text-fd-navy/60', bio: 'text-fd-navy/60', icon: 'text-fd-navy/40 hover:text-fd-navy' },
|
name: 'text-fd-yellow',
|
||||||
|
role: 'text-white/70',
|
||||||
|
bio: 'text-white/60',
|
||||||
|
icon: 'text-white/40 hover:text-fd-yellow',
|
||||||
|
},
|
||||||
|
white: {
|
||||||
|
bg: 'bg-white dark:bg-white/10',
|
||||||
|
name: 'text-fd-navy dark:text-white',
|
||||||
|
role: 'text-fd-navy/60 dark:text-white/60',
|
||||||
|
bio: 'text-fd-navy/60 dark:text-white/60',
|
||||||
|
icon: 'text-fd-navy/40 hover:text-fd-navy dark:text-white/40 dark:hover:text-white',
|
||||||
|
},
|
||||||
|
gray: {
|
||||||
|
bg: 'bg-fd-gray-light dark:bg-white/10',
|
||||||
|
name: 'text-fd-navy dark:text-white',
|
||||||
|
role: 'text-fd-navy/60 dark:text-white/60',
|
||||||
|
bio: 'text-fd-navy/60 dark:text-white/60',
|
||||||
|
icon: 'text-fd-navy/40 hover:text-fd-navy dark:text-white/40 dark:hover:text-white',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const colsMap: Record<string, string> = {
|
const colsMap: Record<string, string> = {
|
||||||
@ -28,42 +46,38 @@ export const FDTeamBlockComponent: React.FC<FDTeamBlockProps> = ({
|
|||||||
cardStyle = 'navy',
|
cardStyle = 'navy',
|
||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
}) => {
|
}) => {
|
||||||
const sectionBg = sectionBgMap[sectionBackground ?? 'white'] || sectionBgMap.white
|
const sectionBg = sectionBgMap[sectionBackground ?? 'white'] || sectionBgMap.white
|
||||||
const card = cardMap[cardStyle ?? 'navy'] || cardMap.navy
|
const card = cardMap[cardStyle ?? 'navy'] || cardMap.navy
|
||||||
const gridCols = colsMap[columns ?? '3'] || colsMap['3']
|
const gridCols = colsMap[columns ?? '3'] || colsMap['3']
|
||||||
const isNavySection = sectionBackground === 'navy'
|
const isNavySection = sectionBackground === 'navy'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
|
|
||||||
{/* Header */}
|
|
||||||
{(heading || subheading) && (
|
{(heading || subheading) && (
|
||||||
<div className="flex flex-col gap-3 mb-10 md:mb-14">
|
<div className="flex flex-col gap-3 mb-10 md:mb-14">
|
||||||
{heading && (
|
{heading && (
|
||||||
<h2 className={`font-joey-heavy text-fd-h1 ${isNavySection ? 'text-fd-yellow' : 'text-fd-navy'}`}>
|
<h2 className={`font-joey-heavy text-fd-h1 ${isNavySection ? 'text-fd-yellow' : 'text-fd-navy dark:text-fd-yellow'}`}>
|
||||||
{heading}
|
{heading}
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
{subheading && (
|
{subheading && (
|
||||||
<p className={`font-joey text-fd-body-lg ${isNavySection ? 'text-white/70' : 'text-fd-navy/60'}`}>
|
<p className={`font-joey text-fd-body-lg ${isNavySection ? 'text-white/70' : 'text-fd-navy/60 dark:text-white/70'}`}>
|
||||||
{subheading}
|
{subheading}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Grid */}
|
|
||||||
<div className={`grid grid-cols-1 ${gridCols} gap-6`}>
|
<div className={`grid grid-cols-1 ${gridCols} gap-6`}>
|
||||||
{members?.map((member, i) => {
|
{members?.map((member, i) => {
|
||||||
// FIX: cast photo properly as Media and pass full object to FDImage
|
const photo = member.photo as Media | undefined
|
||||||
const photo = member.photo as Media | undefined
|
|
||||||
const hasPhoto = photo && typeof photo === 'object' && photo.url
|
const hasPhoto = photo && typeof photo === 'object' && photo.url
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={i} className={`${card.bg} rounded-[70px] overflow-hidden flex flex-col`}>
|
<div key={i} className={`${card.bg} rounded-[70px] overflow-hidden flex flex-col`}>
|
||||||
|
|
||||||
{/* Photo */}
|
|
||||||
<div className="aspect-[4/3] w-full overflow-hidden">
|
<div className="aspect-[4/3] w-full overflow-hidden">
|
||||||
{hasPhoto ? (
|
{hasPhoto ? (
|
||||||
<FDImage
|
<FDImage
|
||||||
@ -74,7 +88,7 @@ export const FDTeamBlockComponent: React.FC<FDTeamBlockProps> = ({
|
|||||||
fallbackAlt={member.name}
|
fallbackAlt={member.name}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className={`w-full h-full flex items-center justify-center ${cardStyle === 'navy' ? 'bg-fd-navy/50' : 'bg-fd-navy/10'}`}>
|
<div className={`w-full h-full flex items-center justify-center ${cardStyle === 'navy' ? 'bg-fd-navy/50' : 'bg-fd-navy/10 dark:bg-white/5'}`}>
|
||||||
<svg viewBox="0 0 80 80" className="w-20 h-20 opacity-30" fill="currentColor">
|
<svg viewBox="0 0 80 80" className="w-20 h-20 opacity-30" fill="currentColor">
|
||||||
<circle cx="40" cy="30" r="18" />
|
<circle cx="40" cy="30" r="18" />
|
||||||
<path d="M10 72c0-16.6 13.4-30 30-30s30 13.4 30 30H10z" />
|
<path d="M10 72c0-16.6 13.4-30 30-30s30 13.4 30 30H10z" />
|
||||||
@ -83,7 +97,6 @@ export const FDTeamBlockComponent: React.FC<FDTeamBlockProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Info */}
|
|
||||||
<div className="flex flex-col gap-2 px-8 py-8 flex-1">
|
<div className="flex flex-col gap-2 px-8 py-8 flex-1">
|
||||||
<p className={`font-joey-bold text-fd-h3 ${card.name}`}>{member.name}</p>
|
<p className={`font-joey-bold text-fd-h3 ${card.name}`}>{member.name}</p>
|
||||||
<p className={`font-joey text-fd-small ${card.role}`}>{member.role}</p>
|
<p className={`font-joey text-fd-small ${card.role}`}>{member.role}</p>
|
||||||
@ -94,28 +107,17 @@ export const FDTeamBlockComponent: React.FC<FDTeamBlockProps> = ({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Links */}
|
|
||||||
{(member.email || member.linkedin) && (
|
{(member.email || member.linkedin) && (
|
||||||
<div className="flex items-center gap-4 mt-4">
|
<div className="flex items-center gap-4 mt-4">
|
||||||
{member.email && (
|
{member.email && (
|
||||||
<a
|
<a href={`mailto:${member.email}`} aria-label={`E-post till ${member.name}`} className={`transition-colors ${card.icon}`}>
|
||||||
href={`mailto:${member.email}`}
|
|
||||||
aria-label={`E-post till ${member.name}`}
|
|
||||||
className={`transition-colors ${card.icon}`}
|
|
||||||
>
|
|
||||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
{member.linkedin && (
|
{member.linkedin && (
|
||||||
<a
|
<a href={member.linkedin} target="_blank" rel="noopener noreferrer" aria-label={`LinkedIn för ${member.name}`} className={`transition-colors ${card.icon}`}>
|
||||||
href={member.linkedin}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
aria-label={`LinkedIn för ${member.name}`}
|
|
||||||
className={`transition-colors ${card.icon}`}
|
|
||||||
>
|
|
||||||
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
|
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@ -3,20 +3,22 @@ import type { FDTechPropertiesBlock as FDTechPropertiesBlockProps } from '@/payl
|
|||||||
|
|
||||||
const bgMap: Record<string, string> = {
|
const bgMap: Record<string, string> = {
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
yellow: 'bg-fd-yellow',
|
yellow: 'bg-fd-yellow',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Category label (small text above value)
|
||||||
const catColorMap: Record<string, string> = {
|
const catColorMap: Record<string, string> = {
|
||||||
white: 'text-white',
|
white: 'text-white',
|
||||||
navy: 'text-fd-navy',
|
navy: 'text-fd-navy dark:text-white/70',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value (large number/text)
|
||||||
const valColorMap: Record<string, string> = {
|
const valColorMap: Record<string, string> = {
|
||||||
yellow: 'text-fd-yellow',
|
yellow: 'text-fd-yellow',
|
||||||
white: 'text-white',
|
white: 'text-white',
|
||||||
navy: 'text-fd-navy',
|
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FDTechPropertiesBlockComponent: React.FC<FDTechPropertiesBlockProps> = ({
|
export const FDTechPropertiesBlockComponent: React.FC<FDTechPropertiesBlockProps> = ({
|
||||||
@ -25,15 +27,15 @@ export const FDTechPropertiesBlockComponent: React.FC<FDTechPropertiesBlockProps
|
|||||||
categoryColor = 'white',
|
categoryColor = 'white',
|
||||||
valueColor = 'yellow',
|
valueColor = 'yellow',
|
||||||
}) => {
|
}) => {
|
||||||
const bg = bgMap[sectionBackground || 'navy']
|
const bg = bgMap[sectionBackground || 'navy']
|
||||||
const catColor = catColorMap[categoryColor || 'white']
|
const catColor = catColorMap[categoryColor || 'white']
|
||||||
const valColor = valColorMap[valueColor || 'yellow']
|
const valColor = valColorMap[valueColor || 'yellow']
|
||||||
const count = properties?.length || 1
|
const count = properties?.length || 1
|
||||||
const gridCols =
|
const gridCols =
|
||||||
count <= 2 ? 'grid-cols-2' : count === 3 ? 'grid-cols-3' : 'grid-cols-2 md:grid-cols-4'
|
count <= 2 ? 'grid-cols-2' : count === 3 ? 'grid-cols-3' : 'grid-cols-2 md:grid-cols-4'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${bg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
<div className={`grid ${gridCols} gap-8 md:gap-12`}>
|
<div className={`grid ${gridCols} gap-8 md:gap-12`}>
|
||||||
{properties?.map((prop, index) => (
|
{properties?.map((prop, index) => (
|
||||||
|
|||||||
@ -2,13 +2,36 @@ import React from 'react'
|
|||||||
import type { FDTestimonialBlock as FDTestimonialBlockProps, Media } from '@/payload-types'
|
import type { FDTestimonialBlock as FDTestimonialBlockProps, Media } from '@/payload-types'
|
||||||
import { FDImage } from '@/components/FDImage'
|
import { FDImage } from '@/components/FDImage'
|
||||||
|
|
||||||
const bgMap: Record<string, { section: string; card: string; quote: string; meta: string; name: string; company: string }> = {
|
const bgMap: Record<string, {
|
||||||
gray: { section: 'bg-fd-gray-light', card: 'bg-white', quote: 'text-fd-navy', meta: 'text-fd-navy/60', name: 'text-fd-navy', company: 'text-fd-navy/50' },
|
section: string; card: string
|
||||||
white: { section: 'bg-white', card: 'bg-fd-gray-light', quote: 'text-fd-navy', meta: 'text-fd-navy/60', name: 'text-fd-navy', company: 'text-fd-navy/50' },
|
quote: string; meta: string; name: string; accent: string
|
||||||
navy: { section: 'bg-fd-navy', card: 'bg-white/10', quote: 'text-white', meta: 'text-white/60', name: 'text-white', company: 'text-white/50' },
|
}> = {
|
||||||
|
gray: {
|
||||||
|
section: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
|
card: 'bg-white dark:bg-white/10',
|
||||||
|
quote: 'text-fd-navy dark:text-white',
|
||||||
|
meta: 'text-fd-navy/60 dark:text-white/60',
|
||||||
|
name: 'text-fd-navy dark:text-white',
|
||||||
|
accent: 'text-fd-navy dark:text-fd-yellow',
|
||||||
|
},
|
||||||
|
white: {
|
||||||
|
section: 'bg-white dark:bg-fd-navy',
|
||||||
|
card: 'bg-fd-gray-light dark:bg-white/10',
|
||||||
|
quote: 'text-fd-navy dark:text-white',
|
||||||
|
meta: 'text-fd-navy/60 dark:text-white/60',
|
||||||
|
name: 'text-fd-navy dark:text-white',
|
||||||
|
accent: 'text-fd-navy dark:text-fd-yellow',
|
||||||
|
},
|
||||||
|
navy: {
|
||||||
|
section: 'bg-fd-navy',
|
||||||
|
card: 'bg-white/10',
|
||||||
|
quote: 'text-white',
|
||||||
|
meta: 'text-white/60',
|
||||||
|
name: 'text-white',
|
||||||
|
accent: 'text-fd-yellow',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Avatar helper — uses FDImage with media object correctly */
|
|
||||||
const Avatar: React.FC<{ media: Media | undefined; name: string; size: number }> = ({ media, name, size }) => {
|
const Avatar: React.FC<{ media: Media | undefined; name: string; size: number }> = ({ media, name, size }) => {
|
||||||
if (!media?.url) return null
|
if (!media?.url) return null
|
||||||
return (
|
return (
|
||||||
@ -33,26 +56,24 @@ export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
|
|||||||
layout = 'grid',
|
layout = 'grid',
|
||||||
sectionBackground = 'gray',
|
sectionBackground = 'gray',
|
||||||
}) => {
|
}) => {
|
||||||
const theme = bgMap[sectionBackground ?? 'gray'] || bgMap.gray
|
const theme = bgMap[sectionBackground ?? 'gray'] || bgMap.gray
|
||||||
const isFeatured = layout === 'featured'
|
const isFeatured = layout === 'featured'
|
||||||
const isNavy = sectionBackground === 'navy'
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${theme.section}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${theme.section}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
|
|
||||||
{heading && (
|
{heading && (
|
||||||
<h2 className={`font-joey-heavy text-fd-h1 mb-10 md:mb-14 ${isNavy ? 'text-fd-yellow' : 'text-fd-navy'}`}>
|
<h2 className={`font-joey-heavy text-fd-h1 mb-10 md:mb-14 ${theme.accent}`}>
|
||||||
{heading}
|
{heading}
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isFeatured && testimonials && testimonials.length > 0 ? (
|
{isFeatured && testimonials && testimonials.length > 0 ? (
|
||||||
// ── Featured layout: first testimonial large, rest below ──────
|
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
{/* First testimonial — large */}
|
{/* First testimonial — large */}
|
||||||
{(() => {
|
{(() => {
|
||||||
const t = testimonials[0]
|
const t = testimonials[0]
|
||||||
const avatar = t.avatar as Media | undefined
|
const avatar = t.avatar as Media | undefined
|
||||||
return (
|
return (
|
||||||
<div className={`${theme.card} rounded-[70px] px-8 md:px-16 py-10 md:py-16 flex flex-col gap-8`}>
|
<div className={`${theme.card} rounded-[70px] px-8 md:px-16 py-10 md:py-16 flex flex-col gap-8`}>
|
||||||
@ -72,7 +93,6 @@ export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
|
|||||||
)
|
)
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
{/* Remaining testimonials — smaller grid */}
|
|
||||||
{testimonials.length > 1 && (
|
{testimonials.length > 1 && (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
{testimonials.slice(1).map((t, i) => {
|
{testimonials.slice(1).map((t, i) => {
|
||||||
@ -98,14 +118,12 @@ export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
// ── Grid layout ───────────────────────────────────────────────
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{testimonials?.map((t, i) => {
|
{testimonials?.map((t, i) => {
|
||||||
const avatar = t.avatar as Media | undefined
|
const avatar = t.avatar as Media | undefined
|
||||||
return (
|
return (
|
||||||
<div key={i} className={`${theme.card} rounded-[70px] px-8 md:px-10 py-10 md:py-12 flex flex-col gap-6`}>
|
<div key={i} className={`${theme.card} rounded-[70px] px-8 md:px-10 py-10 md:py-12 flex flex-col gap-6`}>
|
||||||
{/* Quote mark */}
|
<span className={`font-joey-heavy text-5xl leading-none ${theme.accent} opacity-30`}>
|
||||||
<span className={`font-joey-heavy text-5xl leading-none ${isNavy ? 'text-fd-yellow' : 'text-fd-navy'} opacity-30`}>
|
|
||||||
“
|
“
|
||||||
</span>
|
</span>
|
||||||
<p className={`font-joey-medium text-lg leading-relaxed -mt-4 ${theme.quote}`}>
|
<p className={`font-joey-medium text-lg leading-relaxed -mt-4 ${theme.quote}`}>
|
||||||
|
|||||||
@ -3,9 +3,9 @@ import type { FDTextBlock as FDTextBlockProps } from '@/payload-types'
|
|||||||
import RichText from '@/components/RichText'
|
import RichText from '@/components/RichText'
|
||||||
|
|
||||||
const bgMap: Record<string, string> = {
|
const bgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
yellow: 'bg-fd-yellow',
|
yellow: 'bg-fd-yellow',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,10 +22,15 @@ const maxWidthMap: Record<string, string> = {
|
|||||||
full: '',
|
full: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Navy text color = adapts to dark mode. White/yellow = always explicit.
|
||||||
const textColorMap: Record<string, { h1: string; h2: string; body: string }> = {
|
const textColorMap: Record<string, { h1: string; h2: string; body: string }> = {
|
||||||
navy: { h1: 'text-fd-navy', h2: 'text-fd-navy', body: 'text-fd-navy' },
|
navy: {
|
||||||
white: { h1: 'text-white', h2: 'text-white', body: 'text-white/90' },
|
h1: 'text-fd-navy dark:text-fd-yellow',
|
||||||
yellow: { h1: 'text-fd-yellow', h2: 'text-fd-yellow', body: 'text-fd-yellow/90' },
|
h2: 'text-fd-navy dark:text-fd-yellow',
|
||||||
|
body: 'text-fd-navy dark:text-white',
|
||||||
|
},
|
||||||
|
white: { h1: 'text-white', h2: 'text-white', body: 'text-white/90' },
|
||||||
|
yellow: { h1: 'text-fd-yellow', h2: 'text-fd-yellow', body: 'text-fd-yellow/90' },
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FDTextBlockComponent: React.FC<FDTextBlockProps> = ({
|
export const FDTextBlockComponent: React.FC<FDTextBlockProps> = ({
|
||||||
@ -37,9 +42,9 @@ export const FDTextBlockComponent: React.FC<FDTextBlockProps> = ({
|
|||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
maxWidth = 'wide',
|
maxWidth = 'wide',
|
||||||
}) => {
|
}) => {
|
||||||
const bg = bgMap[sectionBackground || 'white']
|
const bg = bgMap[sectionBackground || 'white']
|
||||||
const align = alignMap[alignment || 'left']
|
const align = alignMap[alignment || 'left']
|
||||||
const width = maxWidthMap[maxWidth || 'wide']
|
const width = maxWidthMap[maxWidth || 'wide']
|
||||||
const colors = textColorMap[textColor || 'navy']
|
const colors = textColorMap[textColor || 'navy']
|
||||||
const containerAlign =
|
const containerAlign =
|
||||||
alignment === 'center' ? 'mx-auto' : alignment === 'right' ? 'ml-auto' : ''
|
alignment === 'center' ? 'mx-auto' : alignment === 'right' ? 'ml-auto' : ''
|
||||||
@ -47,7 +52,7 @@ export const FDTextBlockComponent: React.FC<FDTextBlockProps> = ({
|
|||||||
if (!heading && !subheading && !body) return null
|
if (!heading && !subheading && !body) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${bg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
<div className={`${width} ${containerAlign} ${align} flex flex-col gap-4 md:gap-6`}>
|
<div className={`${width} ${containerAlign} ${align} flex flex-col gap-4 md:gap-6`}>
|
||||||
{heading && (
|
{heading && (
|
||||||
|
|||||||
@ -3,13 +3,18 @@ import type { FDUspChecklistBlock as FDUspChecklistBlockProps, Media } from '@/p
|
|||||||
import { FDImage } from '@/components/FDImage'
|
import { FDImage } from '@/components/FDImage'
|
||||||
|
|
||||||
const bgMap: Record<string, string> = {
|
const bgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
}
|
}
|
||||||
|
|
||||||
const textMap: Record<string, string> = {
|
const headingMap: Record<string, string> = {
|
||||||
navy: 'text-fd-navy',
|
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||||
|
white: 'text-white',
|
||||||
|
}
|
||||||
|
|
||||||
|
const bodyMap: Record<string, string> = {
|
||||||
|
navy: 'text-fd-navy dark:text-white',
|
||||||
white: 'text-white',
|
white: 'text-white',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,19 +43,20 @@ export const FDUspChecklistBlockComponent: React.FC<FDUspChecklistBlockProps> =
|
|||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
textColor = 'navy',
|
textColor = 'navy',
|
||||||
}) => {
|
}) => {
|
||||||
const bg = bgMap[sectionBackground || 'white']
|
const bg = bgMap[sectionBackground || 'white']
|
||||||
const txt = textMap[textColor || 'navy']
|
const headClr = headingMap[textColor || 'navy']
|
||||||
const media = image as Media | undefined
|
const bodyClr = bodyMap[textColor || 'navy']
|
||||||
|
const media = image as Media | undefined
|
||||||
const hasImage = Boolean(media?.url)
|
const hasImage = Boolean(media?.url)
|
||||||
|
|
||||||
const textContent = (
|
const textContent = (
|
||||||
<div className="flex-1 flex flex-col gap-6 md:gap-8">
|
<div className="flex-1 flex flex-col gap-6 md:gap-8">
|
||||||
<h2 className={`font-joey-heavy text-fd-h1 ${txt}`}>{heading}</h2>
|
<h2 className={`font-joey-heavy text-fd-h1 ${headClr}`}>{heading}</h2>
|
||||||
<div className="flex flex-col gap-5 md:gap-6">
|
<div className="flex flex-col gap-5 md:gap-6">
|
||||||
{items?.map((item, index) => (
|
{items?.map((item, index) => (
|
||||||
<div key={index} className="flex items-start gap-4">
|
<div key={index} className="flex items-start gap-4">
|
||||||
<CheckIcon color={checkColor || 'navy'} />
|
<CheckIcon color={checkColor || 'navy'} />
|
||||||
<span className={`font-joey text-fd-body-lg pt-1 ${txt}`}>{item.text}</span>
|
<span className={`font-joey text-fd-body-lg pt-1 ${bodyClr}`}>{item.text}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -70,7 +76,7 @@ export const FDUspChecklistBlockComponent: React.FC<FDUspChecklistBlockProps> =
|
|||||||
) : null
|
) : null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${bg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col lg:flex-row items-center gap-10 lg:gap-16">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col lg:flex-row items-center gap-10 lg:gap-16">
|
||||||
{imagePosition === 'left' ? <>{imageContent}{textContent}</> : <>{textContent}{imageContent}</>}
|
{imagePosition === 'left' ? <>{imageContent}{textContent}</> : <>{textContent}{imageContent}</>}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,18 +3,30 @@ import type { FDUspTableBlock as FDUspTableBlockProps } from '@/payload-types'
|
|||||||
import RichText from '@/components/RichText'
|
import RichText from '@/components/RichText'
|
||||||
|
|
||||||
const bgMap: Record<string, string> = {
|
const bgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
}
|
}
|
||||||
|
|
||||||
const textMap: Record<string, string> = {
|
// Heading: navy bg → yellow in dark
|
||||||
navy: 'text-fd-navy',
|
const headingMap: Record<string, string> = {
|
||||||
|
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||||
white: 'text-white',
|
white: 'text-white',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Body / row titles: navy bg → white in dark
|
||||||
|
const textMap: Record<string, string> = {
|
||||||
|
navy: 'text-fd-navy dark:text-white',
|
||||||
|
white: 'text-white',
|
||||||
|
}
|
||||||
|
|
||||||
|
const proseMap: Record<string, string> = {
|
||||||
|
navy: 'text-fd-navy/80 dark:text-white/80',
|
||||||
|
white: 'text-white/80',
|
||||||
|
}
|
||||||
|
|
||||||
const borderMap: Record<string, string> = {
|
const borderMap: Record<string, string> = {
|
||||||
navy: 'border-fd-navy/10',
|
navy: 'border-fd-navy/10 dark:border-white/20',
|
||||||
white: 'border-white/20',
|
white: 'border-white/20',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,16 +53,17 @@ export const FDUspTableBlockComponent: React.FC<FDUspTableBlockProps> = ({
|
|||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
textColor = 'navy',
|
textColor = 'navy',
|
||||||
}) => {
|
}) => {
|
||||||
const bg = bgMap[sectionBackground || 'white']
|
const bg = bgMap[sectionBackground || 'white']
|
||||||
const txt = textMap[textColor || 'navy']
|
const headClr = headingMap[textColor || 'navy']
|
||||||
const border = borderMap[textColor || 'navy']
|
const txt = textMap[textColor || 'navy']
|
||||||
const proseOpacity = textColor === 'white' ? 'opacity-80' : 'opacity-80'
|
const prose = proseMap[textColor || 'navy']
|
||||||
|
const border = borderMap[textColor || 'navy']
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-12 md:py-16 lg:py-20 ${bg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bg}`}>
|
||||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||||
{heading && (
|
{heading && (
|
||||||
<h2 className={`font-joey-heavy text-fd-h1 mb-10 md:mb-14 ${txt}`}>{heading}</h2>
|
<h2 className={`font-joey-heavy text-fd-h1 mb-10 md:mb-14 ${headClr}`}>{heading}</h2>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{rows?.map((row, index) => (
|
{rows?.map((row, index) => (
|
||||||
@ -64,7 +77,7 @@ export const FDUspTableBlockComponent: React.FC<FDUspTableBlockProps> = ({
|
|||||||
<CheckIcon color={checkColor || 'navy'} />
|
<CheckIcon color={checkColor || 'navy'} />
|
||||||
<span className={`font-joey-bold text-fd-h3 ${txt}`}>{row.title}</span>
|
<span className={`font-joey-bold text-fd-h3 ${txt}`}>{row.title}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={`font-joey text-fd-body fd-prose ${txt} ${proseOpacity} md:pl-0 pl-14`}>
|
<div className={`font-joey text-fd-body fd-prose ${prose} md:pl-0 pl-14`}>
|
||||||
<RichText data={(row.description) as any} />
|
<RichText data={(row.description) as any} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,22 +4,22 @@ import { FDButton } from '@/components/FDButton'
|
|||||||
import { FDImage } from '@/components/FDImage'
|
import { FDImage } from '@/components/FDImage'
|
||||||
|
|
||||||
const cardBgMap: Record<string, { bg: string; heading: string; body: string; isDark: boolean }> = {
|
const cardBgMap: Record<string, { bg: string; heading: string; body: string; isDark: boolean }> = {
|
||||||
navy: { bg: 'bg-fd-navy', heading: 'text-white', body: 'text-white/80', isDark: true },
|
navy: { bg: 'bg-fd-navy', heading: 'text-white', body: 'text-white/80', isDark: true },
|
||||||
yellow: { bg: 'bg-fd-yellow', heading: 'text-fd-navy', body: 'text-fd-navy/80', isDark: false },
|
yellow: { bg: 'bg-fd-yellow', heading: 'text-fd-navy', body: 'text-fd-navy/80', isDark: false },
|
||||||
gray: { bg: 'bg-fd-gray-light', heading: 'text-fd-navy', body: 'text-fd-navy/80', isDark: false },
|
gray: { bg: 'bg-fd-gray-light dark:bg-white/10', heading: 'text-fd-navy dark:text-white', body: 'text-fd-navy/80 dark:text-white/80', isDark: false },
|
||||||
white: { bg: 'bg-white shadow-xl', heading: 'text-fd-navy', body: 'text-fd-navy/80', isDark: false },
|
white: { bg: 'bg-white dark:bg-white/10 shadow-xl dark:shadow-none', heading: 'text-fd-navy dark:text-white', body: 'text-fd-navy/80 dark:text-white/80', isDark: false },
|
||||||
}
|
}
|
||||||
|
|
||||||
const sectionBgMap: Record<string, string> = {
|
const sectionBgMap: Record<string, string> = {
|
||||||
white: 'bg-white',
|
white: 'bg-white dark:bg-fd-navy',
|
||||||
gray: 'bg-fd-gray-light',
|
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||||
navy: 'bg-fd-navy',
|
navy: 'bg-fd-navy',
|
||||||
}
|
}
|
||||||
|
|
||||||
const btnVariantMap: Record<string, { variant: 'primary' | 'outline' }> = {
|
const btnVariantMap: Record<string, { variant: 'primary' | 'outline' }> = {
|
||||||
yellow: { variant: 'primary' },
|
yellow: { variant: 'primary' },
|
||||||
navy: { variant: 'outline' },
|
navy: { variant: 'outline' },
|
||||||
white: { variant: 'primary' },
|
white: { variant: 'primary' },
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
|
export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
|
||||||
@ -32,11 +32,11 @@ export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
|
|||||||
buttonColor = 'yellow',
|
buttonColor = 'yellow',
|
||||||
sectionBackground = 'white',
|
sectionBackground = 'white',
|
||||||
}) => {
|
}) => {
|
||||||
const card = cardBgMap[cardBackground || 'navy']
|
const card = cardBgMap[cardBackground || 'navy']
|
||||||
const sectionBg = sectionBgMap[sectionBackground || 'white']
|
const sectionBg = sectionBgMap[sectionBackground || 'white']
|
||||||
const { variant } = btnVariantMap[buttonColor || 'yellow']
|
const { variant } = btnVariantMap[buttonColor || 'yellow']
|
||||||
const media = image as Media | undefined
|
const media = image as Media | undefined
|
||||||
const hasImage = media && typeof media === 'object' && media.url
|
const hasImage = media && typeof media === 'object' && media.url
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||||
@ -53,18 +53,13 @@ export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
|
|||||||
)}
|
)}
|
||||||
{ctaText && (
|
{ctaText && (
|
||||||
<div>
|
<div>
|
||||||
<FDButton
|
<FDButton href={ctaLink || '#'} variant={variant} onDark={card.isDark}>
|
||||||
href={ctaLink || '#'}
|
|
||||||
variant={variant}
|
|
||||||
onDark={card.isDark}
|
|
||||||
>
|
|
||||||
{ctaText}
|
{ctaText}
|
||||||
</FDButton>
|
</FDButton>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* FIX: replaced raw <img> with FDImage */}
|
|
||||||
{hasImage && (
|
{hasImage && (
|
||||||
<div className="relative flex-1 min-h-[250px] lg:min-h-0">
|
<div className="relative flex-1 min-h-[250px] lg:min-h-0">
|
||||||
<FDImage
|
<FDImage
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user