FeatureGridSection.tsx57 lines · main
1import { cn } from 'ui'
2
3import type { GoFeatureGridSection } from '../schemas'
4
5export default function FeatureGridSection({ section }: { section: GoFeatureGridSection }) {
6 const { items, columns = 3 } = section
7 const hasSecondRow = items.length > columns
8
9 return (
10 <div className="max-w-7xl mx-auto px-8">
11 {(section.title || section.description) && (
12 <div className="mb-12">
13 {section.title && (
14 <h2 className="text-2xl sm:text-3xl font-medium text-foreground">{section.title}</h2>
15 )}
16 {section.description && (
17 <p className="text-foreground-lighter mt-3 text-lg">{section.description}</p>
18 )}
19 </div>
20 )}
21 <div className="border border-muted rounded-xl overflow-hidden">
22 <div
23 className={cn(
24 'grid grid-cols-1',
25 columns === 1 ? 'md:grid-cols-1' : columns === 2 ? 'md:grid-cols-2' : 'md:grid-cols-3'
26 )}
27 >
28 {items.map((item, i) => {
29 const col = i % columns
30 const row = Math.floor(i / columns)
31 const isLastCol = col === columns - 1 || i === items.length - 1
32 const isLastRow = !hasSecondRow || row === Math.floor((items.length - 1) / columns)
33
34 return (
35 <div
36 key={i}
37 className={cn(
38 'p-6 sm:p-8',
39 !isLastCol && 'md:border-r border-muted',
40 !isLastRow && 'border-b border-muted',
41 // On mobile, all items except the last get a bottom border
42 i < items.length - 1 && 'max-md:border-b max-md:border-muted'
43 )}
44 >
45 {item.icon && <span className="text-xl mb-3 block">{item.icon}</span>}
46 <h3 className="text-foreground font-medium text-base">{item.title}</h3>
47 <p className="text-foreground-lighter text-sm mt-2 leading-relaxed">
48 {item.description}
49 </p>
50 </div>
51 )
52 })}
53 </div>
54 </div>
55 </div>
56 )
57}