feat: dark mode across all blocks
This commit is contained in:
parent
097615569b
commit
576ecf1e97
@ -17,9 +17,21 @@ export const FDAlternateHeroBlockComponent: React.FC<Props> = ({
|
||||
const media = image as Media | undefined
|
||||
const hasImage = media && typeof media === 'object' && media.url
|
||||
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 bodyClass = isDark ? 'text-white' : 'text-fd-navy'
|
||||
|
||||
const bgClass =
|
||||
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 (
|
||||
<section className={`w-full pt-16 md:pt-20 lg:pt-[99px] ${bgClass}`}>
|
||||
@ -49,7 +61,7 @@ export const FDAlternateHeroBlockComponent: React.FC<Props> = ({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* FIX: Full-width image using FDImage with fill, replacing raw <img> */}
|
||||
{/* Full-width image — no border radius, bleeds edge to edge */}
|
||||
{hasImage && (
|
||||
<div className="w-full">
|
||||
<div className="relative w-full" style={{ maxHeight: '620px', height: '45vw', minHeight: '220px' }}>
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react'
|
||||
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: {
|
||||
section: 'bg-fd-yellow',
|
||||
heading: 'text-fd-navy',
|
||||
@ -18,25 +20,25 @@ const bgMap: Record<string, { section: string; heading: string; sub: string; pri
|
||||
secondaryBtn: 'border-2 border-white text-white hover:bg-white/10',
|
||||
},
|
||||
gray: {
|
||||
section: 'bg-[#e5e5e5]',
|
||||
heading: 'text-fd-navy',
|
||||
sub: 'text-fd-navy/70',
|
||||
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',
|
||||
section: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||
heading: 'text-fd-navy dark:text-fd-yellow',
|
||||
sub: 'text-fd-navy/70 dark:text-white/70',
|
||||
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 dark:border-white dark:text-white dark:hover:bg-white/10',
|
||||
},
|
||||
white: {
|
||||
section: 'bg-white',
|
||||
heading: 'text-fd-navy',
|
||||
sub: 'text-fd-navy/70',
|
||||
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',
|
||||
section: 'bg-white dark:bg-fd-navy',
|
||||
heading: 'text-fd-navy dark:text-fd-yellow',
|
||||
sub: 'text-fd-navy/70 dark:text-white/70',
|
||||
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 dark:border-white dark:text-white dark:hover:bg-white/10',
|
||||
},
|
||||
}
|
||||
|
||||
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' },
|
||||
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' },
|
||||
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' },
|
||||
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-fd-h1', sub: 'text-fd-body-lg' },
|
||||
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> = ({
|
||||
@ -50,8 +52,8 @@ export const FDCtaBannerBlockComponent: React.FC<FDCtaBannerBlockProps> = ({
|
||||
alignment = 'center',
|
||||
size = 'medium',
|
||||
}) => {
|
||||
const theme = bgMap[sectionBackground] || bgMap.yellow
|
||||
const sizing = sizeMap[size] || sizeMap.medium
|
||||
const theme = bgMap[sectionBackground ?? 'yellow'] || bgMap.yellow
|
||||
const sizing = sizeMap[size ?? 'medium'] || sizeMap.medium
|
||||
const isCenter = alignment === 'center'
|
||||
|
||||
return (
|
||||
@ -75,7 +77,7 @@ export const FDCtaBannerBlockComponent: React.FC<FDCtaBannerBlockProps> = ({
|
||||
{ctaText && (
|
||||
<a
|
||||
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}
|
||||
</a>
|
||||
@ -83,7 +85,7 @@ export const FDCtaBannerBlockComponent: React.FC<FDCtaBannerBlockProps> = ({
|
||||
{secondaryCtaText && secondaryCtaLink && (
|
||||
<a
|
||||
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}
|
||||
</a>
|
||||
|
||||
@ -16,26 +16,32 @@ export const FDCtaSideImageBlockComponent: React.FC<FDCtaSideImageBlockProps> =
|
||||
const isDark = theme === 'dark'
|
||||
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 = (
|
||||
<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">
|
||||
<h2
|
||||
className={`w-full font-joey-heavy text-fd-h1 leading-tight ${
|
||||
isDark ? 'text-fd-yellow' : 'text-fd-navy'
|
||||
}`}
|
||||
>
|
||||
<h2 className={`w-full font-joey-heavy text-fd-h1 leading-tight ${headingClass}`}>
|
||||
{heading}
|
||||
</h2>
|
||||
<p
|
||||
className={`w-full font-joey text-fd-body-lg leading-relaxed ${
|
||||
isDark ? 'text-white' : 'text-fd-navy'
|
||||
}`}
|
||||
>
|
||||
<p className={`w-full font-joey text-fd-body-lg leading-relaxed ${bodyClass}`}>
|
||||
{body}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{ctaText && (
|
||||
// onDark — either explicit dark theme, or dark: mode makes it navy anyway
|
||||
<FDButton href={ctaLink || '#'} variant="primary" onDark={isDark}>
|
||||
{ctaText}
|
||||
</FDButton>
|
||||
@ -56,19 +62,12 @@ export const FDCtaSideImageBlockComponent: React.FC<FDCtaSideImageBlockProps> =
|
||||
) : null
|
||||
|
||||
return (
|
||||
// FIX: added md:py-20 so tablet gets correct spacing
|
||||
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${isDark ? 'bg-fd-navy' : 'bg-white'}`}>
|
||||
<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 flex flex-col lg:flex-row items-center gap-10 lg:gap-16">
|
||||
{imagePosition === 'left' ? (
|
||||
<>
|
||||
{imageContent}
|
||||
{textContent}
|
||||
</>
|
||||
<>{imageContent}{textContent}</>
|
||||
) : (
|
||||
<>
|
||||
{textContent}
|
||||
{imageContent}
|
||||
</>
|
||||
<>{textContent}{imageContent}</>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -10,16 +10,29 @@ export const FDFaqBlockComponent: React.FC<FDFaqBlockProps> = ({
|
||||
}) => {
|
||||
const [openIndex, setOpenIndex] = useState<number | null>(null)
|
||||
|
||||
// dark theme = always navy. gray/white adapt via dark: OS preference
|
||||
const bgClass =
|
||||
theme === 'dark'
|
||||
? 'bg-fd-navy'
|
||||
: theme === 'gray'
|
||||
? 'bg-fd-gray-light'
|
||||
: 'bg-white'
|
||||
const headingColor = theme === 'dark' ? 'text-fd-yellow' : 'text-fd-navy'
|
||||
const textColor = theme === 'dark' ? 'text-white' : 'text-fd-navy'
|
||||
const borderColor = theme === 'dark' ? 'border-white/20' : 'border-fd-navy/10'
|
||||
const proseColor = theme === 'dark' ? 'text-white/80' : 'text-fd-navy/80'
|
||||
? 'bg-fd-gray-light dark:bg-fd-navy'
|
||||
: 'bg-white dark:bg-fd-navy'
|
||||
|
||||
const headingColor = theme === 'dark'
|
||||
? 'text-fd-yellow'
|
||||
: '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 (
|
||||
<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 bgClass = isDark ? 'bg-fd-navy' : theme === 'gray' ? 'bg-fd-gray' : 'bg-white'
|
||||
const headingColor = isDark ? 'text-fd-yellow' : 'text-fd-navy'
|
||||
const bodyColor = isDark ? 'text-white' : 'text-fd-navy'
|
||||
// Light themes pick up dark: variants from OS preference
|
||||
const bgClass =
|
||||
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 (
|
||||
<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">
|
||||
<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}
|
||||
</h2>
|
||||
|
||||
<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}
|
||||
</p>
|
||||
|
||||
@ -3,13 +3,20 @@ import type { FDHeaderTextImageBlock as FDHeaderTextImageBlockProps, Media } fro
|
||||
import { FDImage } from '@/components/FDImage'
|
||||
|
||||
const bgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
gray: 'bg-fd-gray-light',
|
||||
white: 'bg-white dark:bg-fd-navy',
|
||||
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||
navy: 'bg-fd-navy',
|
||||
}
|
||||
|
||||
const textMap: Record<string, string> = {
|
||||
navy: 'text-fd-navy',
|
||||
// Heading: navy→yellow in dark, white stays white
|
||||
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',
|
||||
}
|
||||
|
||||
@ -41,22 +48,23 @@ export const FDHeaderTextImageBlockComponent: React.FC<FDHeaderTextImageBlockPro
|
||||
textColor = 'navy',
|
||||
}) => {
|
||||
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 rounded = roundedMap[imageRounded || 'large']
|
||||
const align = textAlign === 'center' ? 'text-center' : 'text-left'
|
||||
const media = image as Media
|
||||
|
||||
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">
|
||||
{(heading || body) && (
|
||||
<div className={`flex flex-col gap-4 md:gap-6 ${align} ${textAlign === 'center' ? 'max-w-[900px] mx-auto' : ''}`}>
|
||||
{heading && (
|
||||
<h2 className={`font-joey-heavy text-fd-h1 ${txt}`}>{heading}</h2>
|
||||
<h2 className={`font-joey-heavy text-fd-h1 ${headClr}`}>{heading}</h2>
|
||||
)}
|
||||
{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>
|
||||
)}
|
||||
|
||||
@ -3,21 +3,27 @@ import type { FDIconBarBlock as FDIconBarBlockProps, Media } from '@/payload-typ
|
||||
import { FDImage } from '@/components/FDImage'
|
||||
|
||||
const bgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
gray: 'bg-fd-gray-light',
|
||||
white: 'bg-white dark:bg-fd-navy',
|
||||
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||
navy: 'bg-fd-navy',
|
||||
yellow: 'bg-fd-yellow',
|
||||
}
|
||||
|
||||
const textColorMap: Record<string, string> = {
|
||||
navy: 'text-fd-navy',
|
||||
const headingMap: Record<string, string> = {
|
||||
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||
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> = {
|
||||
navy: 'bg-fd-navy',
|
||||
navy: 'bg-fd-navy dark:bg-white/10',
|
||||
yellow: 'bg-fd-yellow',
|
||||
gray: 'bg-[#e5e5e5]',
|
||||
gray: 'bg-fd-gray-light dark:bg-white/10',
|
||||
none: '',
|
||||
}
|
||||
|
||||
@ -29,15 +35,16 @@ export const FDIconBarBlockComponent: React.FC<FDIconBarBlockProps> = ({
|
||||
textColor = 'navy',
|
||||
}) => {
|
||||
const bg = bgMap[sectionBackground || 'gray']
|
||||
const txtColor = textColorMap[textColor || 'navy']
|
||||
const headClr = headingMap[textColor || 'navy']
|
||||
const labelClr = labelMap[textColor || 'navy']
|
||||
const iconBg = iconBgMap[iconStyle || 'navy']
|
||||
const hasCircle = iconStyle !== 'none'
|
||||
|
||||
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">
|
||||
{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}
|
||||
</h2>
|
||||
)}
|
||||
@ -61,7 +68,7 @@ export const FDIconBarBlockComponent: React.FC<FDIconBarBlockProps> = ({
|
||||
/>
|
||||
)}
|
||||
</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}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -12,10 +12,16 @@ export const FDLocationsGridBlockComponent: React.FC<Props> = ({
|
||||
}) => {
|
||||
const bgClass =
|
||||
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 bodyClass = sectionBackground === 'navy' ? 'text-white' : 'text-fd-navy'
|
||||
const titleClass = sectionBackground === '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 =
|
||||
hoverColor === 'yellow' ? 'bg-fd-yellow' :
|
||||
|
||||
@ -8,22 +8,23 @@ export const FDPartnersLogosBlockComponent: React.FC<FDPartnersLogosBlockProps>
|
||||
sectionBackground = 'gray',
|
||||
}) => {
|
||||
const bgClass =
|
||||
sectionBackground === 'navy'
|
||||
? 'bg-fd-navy'
|
||||
: sectionBackground === 'gray'
|
||||
? 'bg-fd-surface-alt'
|
||||
: 'bg-white'
|
||||
sectionBackground === 'navy' ? 'bg-fd-navy' :
|
||||
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'
|
||||
? 'text-fd-yellow'
|
||||
: 'text-fd-navy dark:text-fd-yellow'
|
||||
|
||||
// In dark mode, monochrome logos invert to be visible on navy bg
|
||||
const imgFilter =
|
||||
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'
|
||||
|
||||
return (
|
||||
<section className={`fd-section ${bgClass}`}>
|
||||
<div className="fd-container">
|
||||
<section className={`w-full py-16 md:py-20 lg:py-[99px] ${bgClass}`}>
|
||||
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
|
||||
{heading && (
|
||||
<h2 className={`font-joey-medium text-fd-h2 text-center mb-10 md:mb-14 ${titleClass}`}>
|
||||
{heading}
|
||||
|
||||
@ -3,14 +3,14 @@ import type { FDPricingCardBlock as FDPricingCardBlockProps } from '@/payload-ty
|
||||
import { FDButton } from '@/components/FDButton'
|
||||
|
||||
const sectionBgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
white: 'bg-white dark: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',
|
||||
}
|
||||
|
||||
const titleColorMap: Record<string, string> = {
|
||||
navy: 'text-fd-navy',
|
||||
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||
white: 'text-white',
|
||||
yellow: 'text-fd-yellow',
|
||||
}
|
||||
@ -19,11 +19,41 @@ const cardStyleMap: Record<string, {
|
||||
bg: string; border: string; title: string
|
||||
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 },
|
||||
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', border: '', title: 'text-fd-navy', subtitle: 'text-fd-navy', body: 'text-fd-navy/80', bullet: 'text-fd-navy', 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 shadow-lg', border: '', title: 'text-fd-navy', subtitle: 'text-fd-navy', body: 'text-fd-navy/80', bullet: 'text-fd-navy', isDark: false },
|
||||
outlined: {
|
||||
bg: 'bg-white dark:bg-white/10',
|
||||
border: 'border-[2px] border-gray-200 dark:border-white/20',
|
||||
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,
|
||||
},
|
||||
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' }> = {
|
||||
@ -63,7 +93,6 @@ export const FDPricingCardBlockComponent: React.FC<FDPricingCardBlockProps> = ({
|
||||
{sectionTitle}
|
||||
</h2>
|
||||
)}
|
||||
{/* FIX: rounded-[32px] → rounded-[70px] per design system */}
|
||||
<div className={`grid grid-cols-1 ${gridCols} gap-6 md:gap-8`}>
|
||||
{cards?.map((card, index) => (
|
||||
<div
|
||||
|
||||
@ -14,10 +14,9 @@ export const FDServicesGridBlockComponent: React.FC<FDServicesGridBlockProps> =
|
||||
columns = '4',
|
||||
}) => {
|
||||
return (
|
||||
// FIX: lg:py-24 → lg:py-[99px] (standard section padding)
|
||||
<section className="relative w-full bg-white py-16 md:py-20 lg:py-[99px]">
|
||||
<section className="relative w-full bg-white dark:bg-fd-navy py-16 md:py-20 lg:py-[99px]">
|
||||
<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}
|
||||
</h2>
|
||||
|
||||
@ -27,7 +26,7 @@ export const FDServicesGridBlockComponent: React.FC<FDServicesGridBlockProps> =
|
||||
|
||||
const content = (
|
||||
<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}
|
||||
</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}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -9,9 +9,9 @@ const heightMap: Record<string, string> = {
|
||||
}
|
||||
|
||||
const bgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
white: 'bg-white dark: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',
|
||||
transparent: 'bg-transparent',
|
||||
}
|
||||
|
||||
@ -22,17 +22,24 @@ export const FDStatisticsBlockComponent: React.FC<Props> = ({
|
||||
|
||||
const bgClass =
|
||||
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 labelClass = sectionBackground === 'navy' ? 'text-white' : 'text-fd-navy'
|
||||
const titleClass = sectionBackground === '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 = () => {
|
||||
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 === 'mint') return 'text-fd-mint'
|
||||
if (numberColor === 'white') return 'text-white'
|
||||
return 'text-fd-navy'
|
||||
// navy number adapts in dark mode
|
||||
return 'text-fd-navy dark:text-white'
|
||||
}
|
||||
|
||||
return (
|
||||
@ -52,7 +59,6 @@ export const FDStatisticsBlockComponent: React.FC<Props> = ({
|
||||
}`}
|
||||
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()}`}>
|
||||
{stat.number}
|
||||
</span>
|
||||
|
||||
@ -4,8 +4,8 @@ import type { FDTagsBlock as FDTagsBlockProps } from '@/payload-types'
|
||||
const tagStyleMap: Record<string, { bg: string; text: string; border: string }> = {
|
||||
navy: { bg: 'bg-fd-navy', text: 'text-fd-yellow', 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' },
|
||||
gray: { bg: 'bg-fd-surface-alt', text: 'text-fd-navy', border: '' },
|
||||
outlined: { bg: 'bg-transparent', text: 'text-fd-navy dark:text-white', border: 'border-2 border-fd-navy dark:border-white' },
|
||||
gray: { bg: 'bg-fd-gray-light dark:bg-white/10', text: 'text-fd-navy dark:text-white', border: '' },
|
||||
}
|
||||
|
||||
const tagSizeMap: Record<string, string> = {
|
||||
@ -15,15 +15,15 @@ const tagSizeMap: Record<string, string> = {
|
||||
}
|
||||
|
||||
const sectionBgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
white: 'bg-white dark: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> = {
|
||||
white: 'text-fd-navy',
|
||||
white: 'text-fd-navy dark: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> = ({
|
||||
@ -41,7 +41,7 @@ export const FDTagsBlockComponent: React.FC<FDTagsBlockProps> = ({
|
||||
const justify = alignment === 'center' ? 'justify-center' : 'justify-start'
|
||||
|
||||
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">
|
||||
{heading && (
|
||||
<h2
|
||||
|
||||
@ -3,15 +3,33 @@ import type { FDTeamBlock as FDTeamBlockProps, Media } from '@/payload-types'
|
||||
import { FDImage } from '@/components/FDImage'
|
||||
|
||||
const sectionBgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
gray: 'bg-fd-gray-light',
|
||||
white: 'bg-white dark:bg-fd-navy',
|
||||
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||
navy: 'bg-fd-navy',
|
||||
}
|
||||
|
||||
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' },
|
||||
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' },
|
||||
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' },
|
||||
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',
|
||||
},
|
||||
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> = {
|
||||
@ -37,33 +55,29 @@ export const FDTeamBlockComponent: React.FC<FDTeamBlockProps> = ({
|
||||
<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">
|
||||
|
||||
{/* Header */}
|
||||
{(heading || subheading) && (
|
||||
<div className="flex flex-col gap-3 mb-10 md:mb-14">
|
||||
{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}
|
||||
</h2>
|
||||
)}
|
||||
{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}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Grid */}
|
||||
<div className={`grid grid-cols-1 ${gridCols} gap-6`}>
|
||||
{members?.map((member, i) => {
|
||||
// FIX: cast photo properly as Media and pass full object to FDImage
|
||||
const photo = member.photo as Media | undefined
|
||||
const hasPhoto = photo && typeof photo === 'object' && photo.url
|
||||
|
||||
return (
|
||||
<div key={i} className={`${card.bg} rounded-[70px] overflow-hidden flex flex-col`}>
|
||||
|
||||
{/* Photo */}
|
||||
<div className="aspect-[4/3] w-full overflow-hidden">
|
||||
{hasPhoto ? (
|
||||
<FDImage
|
||||
@ -74,7 +88,7 @@ export const FDTeamBlockComponent: React.FC<FDTeamBlockProps> = ({
|
||||
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">
|
||||
<circle cx="40" cy="30" r="18" />
|
||||
<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>
|
||||
|
||||
{/* Info */}
|
||||
<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 text-fd-small ${card.role}`}>{member.role}</p>
|
||||
@ -94,28 +107,17 @@ export const FDTeamBlockComponent: React.FC<FDTeamBlockProps> = ({
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Links */}
|
||||
{(member.email || member.linkedin) && (
|
||||
<div className="flex items-center gap-4 mt-4">
|
||||
{member.email && (
|
||||
<a
|
||||
href={`mailto:${member.email}`}
|
||||
aria-label={`E-post till ${member.name}`}
|
||||
className={`transition-colors ${card.icon}`}
|
||||
>
|
||||
<a 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">
|
||||
<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>
|
||||
</a>
|
||||
)}
|
||||
{member.linkedin && (
|
||||
<a
|
||||
href={member.linkedin}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={`LinkedIn för ${member.name}`}
|
||||
className={`transition-colors ${card.icon}`}
|
||||
>
|
||||
<a 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">
|
||||
<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>
|
||||
|
||||
@ -3,20 +3,22 @@ import type { FDTechPropertiesBlock as FDTechPropertiesBlockProps } from '@/payl
|
||||
|
||||
const bgMap: Record<string, string> = {
|
||||
navy: 'bg-fd-navy',
|
||||
white: 'bg-white',
|
||||
gray: 'bg-fd-gray-light',
|
||||
white: 'bg-white dark:bg-fd-navy',
|
||||
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||
yellow: 'bg-fd-yellow',
|
||||
}
|
||||
|
||||
// Category label (small text above value)
|
||||
const catColorMap: Record<string, string> = {
|
||||
white: 'text-white',
|
||||
navy: 'text-fd-navy',
|
||||
navy: 'text-fd-navy dark:text-white/70',
|
||||
}
|
||||
|
||||
// Value (large number/text)
|
||||
const valColorMap: Record<string, string> = {
|
||||
yellow: 'text-fd-yellow',
|
||||
white: 'text-white',
|
||||
navy: 'text-fd-navy',
|
||||
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||
}
|
||||
|
||||
export const FDTechPropertiesBlockComponent: React.FC<FDTechPropertiesBlockProps> = ({
|
||||
@ -33,7 +35,7 @@ export const FDTechPropertiesBlockComponent: React.FC<FDTechPropertiesBlockProps
|
||||
count <= 2 ? 'grid-cols-2' : count === 3 ? 'grid-cols-3' : 'grid-cols-2 md:grid-cols-4'
|
||||
|
||||
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={`grid ${gridCols} gap-8 md:gap-12`}>
|
||||
{properties?.map((prop, index) => (
|
||||
|
||||
@ -2,13 +2,36 @@ import React from 'react'
|
||||
import type { FDTestimonialBlock as FDTestimonialBlockProps, Media } from '@/payload-types'
|
||||
import { FDImage } from '@/components/FDImage'
|
||||
|
||||
const bgMap: Record<string, { section: string; card: string; quote: string; meta: string; name: string; company: 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' },
|
||||
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' },
|
||||
navy: { section: 'bg-fd-navy', card: 'bg-white/10', quote: 'text-white', meta: 'text-white/60', name: 'text-white', company: 'text-white/50' },
|
||||
const bgMap: Record<string, {
|
||||
section: string; card: string
|
||||
quote: string; meta: string; name: string; accent: string
|
||||
}> = {
|
||||
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 }) => {
|
||||
if (!media?.url) return null
|
||||
return (
|
||||
@ -35,20 +58,18 @@ export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
|
||||
}) => {
|
||||
const theme = bgMap[sectionBackground ?? 'gray'] || bgMap.gray
|
||||
const isFeatured = layout === 'featured'
|
||||
const isNavy = sectionBackground === 'navy'
|
||||
|
||||
return (
|
||||
<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">
|
||||
|
||||
{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}
|
||||
</h2>
|
||||
)}
|
||||
|
||||
{isFeatured && testimonials && testimonials.length > 0 ? (
|
||||
// ── Featured layout: first testimonial large, rest below ──────
|
||||
<div className="flex flex-col gap-6">
|
||||
{/* First testimonial — large */}
|
||||
{(() => {
|
||||
@ -72,7 +93,6 @@ export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
|
||||
)
|
||||
})()}
|
||||
|
||||
{/* Remaining testimonials — smaller grid */}
|
||||
{testimonials.length > 1 && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{testimonials.slice(1).map((t, i) => {
|
||||
@ -98,14 +118,12 @@ export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
// ── Grid layout ───────────────────────────────────────────────
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{testimonials?.map((t, i) => {
|
||||
const avatar = t.avatar as Media | undefined
|
||||
return (
|
||||
<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 ${isNavy ? 'text-fd-yellow' : 'text-fd-navy'} opacity-30`}>
|
||||
<span className={`font-joey-heavy text-5xl leading-none ${theme.accent} opacity-30`}>
|
||||
“
|
||||
</span>
|
||||
<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'
|
||||
|
||||
const bgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
white: 'bg-white dark: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',
|
||||
}
|
||||
|
||||
@ -22,8 +22,13 @@ const maxWidthMap: Record<string, string> = {
|
||||
full: '',
|
||||
}
|
||||
|
||||
// Navy text color = adapts to dark mode. White/yellow = always explicit.
|
||||
const textColorMap: Record<string, { h1: string; h2: string; body: string }> = {
|
||||
navy: { h1: 'text-fd-navy', h2: 'text-fd-navy', body: 'text-fd-navy' },
|
||||
navy: {
|
||||
h1: 'text-fd-navy dark:text-fd-yellow',
|
||||
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' },
|
||||
}
|
||||
@ -47,7 +52,7 @@ export const FDTextBlockComponent: React.FC<FDTextBlockProps> = ({
|
||||
if (!heading && !subheading && !body) return null
|
||||
|
||||
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={`${width} ${containerAlign} ${align} flex flex-col gap-4 md:gap-6`}>
|
||||
{heading && (
|
||||
|
||||
@ -3,13 +3,18 @@ import type { FDUspChecklistBlock as FDUspChecklistBlockProps, Media } from '@/p
|
||||
import { FDImage } from '@/components/FDImage'
|
||||
|
||||
const bgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
gray: 'bg-fd-gray-light',
|
||||
white: 'bg-white dark:bg-fd-navy',
|
||||
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||
navy: 'bg-fd-navy',
|
||||
}
|
||||
|
||||
const textMap: Record<string, string> = {
|
||||
navy: 'text-fd-navy',
|
||||
const headingMap: Record<string, string> = {
|
||||
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',
|
||||
}
|
||||
|
||||
@ -39,18 +44,19 @@ export const FDUspChecklistBlockComponent: React.FC<FDUspChecklistBlockProps> =
|
||||
textColor = 'navy',
|
||||
}) => {
|
||||
const bg = bgMap[sectionBackground || 'white']
|
||||
const txt = textMap[textColor || 'navy']
|
||||
const headClr = headingMap[textColor || 'navy']
|
||||
const bodyClr = bodyMap[textColor || 'navy']
|
||||
const media = image as Media | undefined
|
||||
const hasImage = Boolean(media?.url)
|
||||
|
||||
const textContent = (
|
||||
<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">
|
||||
{items?.map((item, index) => (
|
||||
<div key={index} className="flex items-start gap-4">
|
||||
<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>
|
||||
@ -70,7 +76,7 @@ export const FDUspChecklistBlockComponent: React.FC<FDUspChecklistBlockProps> =
|
||||
) : null
|
||||
|
||||
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">
|
||||
{imagePosition === 'left' ? <>{imageContent}{textContent}</> : <>{textContent}{imageContent}</>}
|
||||
</div>
|
||||
|
||||
@ -3,18 +3,30 @@ import type { FDUspTableBlock as FDUspTableBlockProps } from '@/payload-types'
|
||||
import RichText from '@/components/RichText'
|
||||
|
||||
const bgMap: Record<string, string> = {
|
||||
white: 'bg-white',
|
||||
gray: 'bg-fd-gray-light',
|
||||
white: 'bg-white dark:bg-fd-navy',
|
||||
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||
navy: 'bg-fd-navy',
|
||||
}
|
||||
|
||||
const textMap: Record<string, string> = {
|
||||
navy: 'text-fd-navy',
|
||||
// Heading: navy bg → yellow in dark
|
||||
const headingMap: Record<string, string> = {
|
||||
navy: 'text-fd-navy dark:text-fd-yellow',
|
||||
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> = {
|
||||
navy: 'border-fd-navy/10',
|
||||
navy: 'border-fd-navy/10 dark:border-white/20',
|
||||
white: 'border-white/20',
|
||||
}
|
||||
|
||||
@ -42,15 +54,16 @@ export const FDUspTableBlockComponent: React.FC<FDUspTableBlockProps> = ({
|
||||
textColor = 'navy',
|
||||
}) => {
|
||||
const bg = bgMap[sectionBackground || 'white']
|
||||
const headClr = headingMap[textColor || 'navy']
|
||||
const txt = textMap[textColor || 'navy']
|
||||
const prose = proseMap[textColor || 'navy']
|
||||
const border = borderMap[textColor || 'navy']
|
||||
const proseOpacity = textColor === 'white' ? 'opacity-80' : 'opacity-80'
|
||||
|
||||
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">
|
||||
{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">
|
||||
{rows?.map((row, index) => (
|
||||
@ -64,7 +77,7 @@ export const FDUspTableBlockComponent: React.FC<FDUspTableBlockProps> = ({
|
||||
<CheckIcon color={checkColor || 'navy'} />
|
||||
<span className={`font-joey-bold text-fd-h3 ${txt}`}>{row.title}</span>
|
||||
</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} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -6,13 +6,13 @@ import { FDImage } from '@/components/FDImage'
|
||||
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 },
|
||||
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 },
|
||||
white: { bg: 'bg-white shadow-xl', 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 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> = {
|
||||
white: 'bg-white',
|
||||
gray: 'bg-fd-gray-light',
|
||||
white: 'bg-white dark:bg-fd-navy',
|
||||
gray: 'bg-fd-gray-light dark:bg-fd-navy',
|
||||
navy: 'bg-fd-navy',
|
||||
}
|
||||
|
||||
@ -53,18 +53,13 @@ export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
|
||||
)}
|
||||
{ctaText && (
|
||||
<div>
|
||||
<FDButton
|
||||
href={ctaLink || '#'}
|
||||
variant={variant}
|
||||
onDark={card.isDark}
|
||||
>
|
||||
<FDButton href={ctaLink || '#'} variant={variant} onDark={card.isDark}>
|
||||
{ctaText}
|
||||
</FDButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* FIX: replaced raw <img> with FDImage */}
|
||||
{hasImage && (
|
||||
<div className="relative flex-1 min-h-[250px] lg:min-h-0">
|
||||
<FDImage
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user