wwwfiberdirekt/src/blocks/FDCtaSideImageBlock/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

100 lines
3.7 KiB
TypeScript

import React from 'react'
import type { FDCtaSideImageBlock as FDCtaSideImageBlockProps } from '@/payload-types'
import type { Media } from '@/payload-types'
import { FDImage } from '@/components/FDImage'
import { FDButton } from '@/components/FDButton'
/* Priority #5: Responsive radius */
const imageRadius = 'rounded-[32px] md:rounded-[50px] lg:rounded-[70px]'
/* Color overlay — same map as FDHeaderTextImageBlock */
const overlayMap: Record<string, string> = {
none: '',
navyLight: 'bg-fd-navy/20',
navyMedium: 'bg-fd-navy/40',
yellowLight: 'bg-fd-yellow/20',
yellowMedium:'bg-fd-yellow/40',
sepia: 'bg-[#8B7D3C]/30',
blackLight: 'bg-black/20',
blackMedium: 'bg-black/40',
}
export const FDCtaSideImageBlockComponent: React.FC<FDCtaSideImageBlockProps> = ({
heading,
body,
ctaText,
ctaLink = '#',
image,
imageOverlay = 'none',
imagePosition = 'right',
theme = 'dark',
anchorId,
}) => {
const isDark = theme === 'dark'
const hasImage = !!image
const overlay = overlayMap[(imageOverlay as string) || 'none'] || ''
// 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'
// Mobile order is always: heading → image → body → button
// Desktop order respects imagePosition (left/right)
// We achieve this by splitting heading from body+button and using CSS order
const desktopTextOrder = imagePosition === 'left' ? 'min-[820px]:order-2' : 'min-[820px]:order-1'
const desktopImageOrder = imagePosition === 'left' ? 'min-[820px]:order-1' : 'min-[820px]:order-2'
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 flex flex-col min-[820px]:flex-row min-[820px]:items-center gap-6 min-[820px]:gap-16">
{/* Heading — always first on mobile */}
<h2 className={`w-full font-joey-heavy text-fd-h1 leading-tight order-1 min-[820px]:hidden ${headingClass}`}>
{heading}
</h2>
{/* Image — always second on mobile, position-aware on desktop */}
{hasImage && (
<div className={`relative w-full min-[820px]:w-[45%] lg:w-[575px] lg:h-[479px] flex-shrink-0 overflow-hidden order-2 ${desktopImageOrder} ${imageRadius}`}>
<FDImage
media={image as Media}
size="large"
fallbackAlt={heading}
className="w-full h-full object-cover"
sizes="(max-width: 1024px) 100vw, 575px"
/>
{overlay && <div className={`absolute inset-0 ${overlay}`} />}
</div>
)}
{/* Text block — heading hidden on mobile (shown above), body+button always third */}
<div className={`flex flex-col flex-1 items-start gap-4 min-[820px]:gap-[41px] order-3 ${desktopTextOrder} ${!hasImage ? 'max-w-2xl' : ''}`}>
{/* Heading shown only on desktop inside the text column */}
<h2 className={`hidden min-[820px]:block 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 ${bodyClass}`}>
{body}
</p>
{ctaText && (
<FDButton href={ctaLink || '#'} variant="primary" onDark={isDark} className="w-full sm:w-auto justify-center mt-4 min-[820px]:mt-0">
{ctaText}
</FDButton>
)}
</div>
</div>
</section>
)
}