wwwlayermeshusa/src/blocks/FDPricingCardBlock/Component.tsx
Jeffrey 89f6ab505d feat: mobile typography overhaul + layout fixes
Typography:
- Raise all fd-* token minimums in globals.css for larger mobile text
  (fd-h1: 28→40px, fd-h2: 22→32px, fd-h3: 18→22px, body-lg: 15→18px, body: 14→16px)
- Strip all text-[x] sm:text-fd-* overrides from 25 block components
  — tokens now handle full range, no block-level hacks
- Change RichText enableGutter default to false — fixes rich text
  indenting in FAQ, TextBlock, posts, and form confirmations

Layout fixes (mobile):
- FDContactBlock: 3-column grid on all screen sizes
- FDHeroBlock: full-width buttons on mobile
- FDServicesGridBlock: px-3 padding on description text under images
- FDWideCardBlock: image now padded inside card, object-contain,
  no longer bleeds edge-to-edge
- FDCtaSideImageBlock: consistent mobile order (heading → image →
  body → button) regardless of imagePosition setting; extra mt-4
  between body and button on mobile
- FDTestimonialBlock: quote text sizes migrated to fd-h3/fd-body-lg tokens
2026-02-26 10:32:23 +01:00

147 lines
5.3 KiB
TypeScript

import React from 'react'
import type { FDPricingCardBlock as FDPricingCardBlockProps } from '@/payload-types'
import { FDButton } from '@/components/FDButton'
const sectionBgMap: Record<string, string> = {
white: 'bg-white dark:bg-fd-navy',
navy: 'bg-fd-navy',
gray: 'bg-fd-gray-light dark:bg-fd-navy',
yellow: 'bg-fd-yellow',
}
const titleColorMap: Record<string, string> = {
navy: 'text-fd-navy dark:text-fd-yellow',
white: 'text-white',
yellow: 'text-fd-yellow',
}
const cardStyleMap: Record<string, {
bg: string; border: string; title: string
subtitle: string; body: string; bullet: string; isDark: boolean
}> = {
outlined: {
bg: 'bg-white dark:bg-white/10',
border: 'border-[5px] 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' }> = {
yellow: { variant: 'primary' },
navy: { variant: 'primary' },
outlinedNavy: { variant: 'outline' },
outlinedWhite: { variant: 'outline' },
}
const gridColsMap: Record<number, string> = {
1: 'min-[820px]:grid-cols-1 max-w-[500px] mx-auto',
2: 'min-[820px]:grid-cols-2',
3: 'min-[820px]:grid-cols-3',
}
const cardRadius = 'rounded-[32px] md:rounded-[50px] lg:rounded-[70px]'
export const FDPricingCardBlockComponent: React.FC<FDPricingCardBlockProps> = ({
sectionTitle,
cards,
cardStyle = 'outlined',
buttonColor = 'yellow',
sectionBackground = 'white',
titleColor = 'navy',
anchorId,
}) => {
const sectionBg = sectionBgMap[sectionBackground || 'white']
const sectionTitleColor = titleColorMap[titleColor || 'navy']
const style = cardStyleMap[cardStyle || 'outlined']
const { variant } = buttonVariantMap[buttonColor || 'yellow']
const cardCount = cards?.length || 1
const gridCols = gridColsMap[cardCount] || gridColsMap[3]
const outlineOnDark = style.isDark
return (
<section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
<div className="max-w-[1200px] mx-auto px-6 md:px-8">
{sectionTitle && (
<h2 className={`font-joey-heavy text-fd-h1 text-center mb-10 md:mb-14 ${sectionTitleColor}`}>
{sectionTitle}
</h2>
)}
<div className={`grid grid-cols-1 ${gridCols} gap-4 min-[820px]:gap-5 lg:gap-8`}>
{cards?.map((card, index) => (
<div
key={index}
className={`${style.bg} ${style.border} ${cardRadius} px-6 min-[820px]:px-8 lg:px-12 py-8 min-[820px]:py-10 lg:py-14 flex flex-col gap-5`}
>
<h3 className={`font-joey-heavy text-fd-h2 leading-tight ${style.title}`}>
{card.title}
</h3>
{card.subtitle && (
<p className={`font-joey-bold text-fd-h3 leading-tight ${style.subtitle}`}>
{card.subtitle}
</p>
)}
{card.description && (
<p className={`font-joey text-fd-body-lg leading-relaxed ${style.body}`}>
{card.description}
</p>
)}
{card.bulletPoints && card.bulletPoints.length > 0 && (
<ul className={`flex flex-col gap-2 ${style.bullet}`}>
{card.bulletPoints.map((point, i) => (
<li key={i} className="flex items-start gap-3">
<span className="mt-2 w-2 h-2 rounded-full bg-current flex-shrink-0" />
<span className="font-joey text-fd-body-lg">{point.text}</span>
</li>
))}
</ul>
)}
{card.ctaText && (
<div className="mt-auto pt-4">
<FDButton
href={card.ctaLink || '#'}
variant={variant}
onDark={variant === 'outline' ? outlineOnDark : style.isDark}
className="w-full sm:w-auto justify-center"
>
{card.ctaText}
</FDButton>
</div>
)}
</div>
))}
</div>
</div>
</section>
)
}