feat: implement UX patterns inspired by Greenback (Hero slider, Stats block, numbered Process cards)

This commit is contained in:
MichalC
2026-09-01 23:21:36 +02:00
parent 66c62f8a31
commit 441ae8f272
8 changed files with 259 additions and 61 deletions
+47 -48
View File
@@ -1,61 +1,60 @@
'use client'
import React from 'react'
import { motion } from 'framer-motion'
import Link from 'next/link'
import type { Page } from '../../payload-types'
import { ArrowRight } from 'lucide-react'
type Props = Extract<NonNullable<Page['layout']>[0], { blockType: 'process' }>
export const ProcessBlock: React.FC<Props> = ({ title, steps, ctaText }) => {
return (
<section className="py-24 bg-background text-foreground">
<div className="container mx-auto px-4">
<motion.h2
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
className="text-3xl md:text-5xl font-bold mb-16 text-center"
>
{title}
</motion.h2>
<div className="max-w-4xl mx-auto">
<div className="flex flex-col md:flex-row gap-8 relative">
{/* Linia łącząca na desktopie */}
<div className="hidden md:block absolute top-6 left-[10%] right-[10%] h-0.5 bg-border z-0" />
{steps?.map((step: NonNullable<Props['steps']>[0], index: number) => (
<motion.div
key={step.id || index}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: index * 0.15 }}
className="flex-1 relative z-10 text-center md:text-left flex flex-col items-center md:items-start"
>
<div className="w-12 h-12 rounded-full bg-accent text-white border-4 border-background flex items-center justify-center text-xl font-bold mb-6">
{index + 1}
</div>
<h3 className="text-xl font-bold mb-3">{step.title}</h3>
<p className="text-foreground/80 text-center md:text-left">{step.description}</p>
</motion.div>
))}
</div>
{ctaText && (
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.6 }}
className="mt-16 text-center"
>
<Link href="/jak-to-dziala" className="inline-block px-8 py-4 border-2 border-border hover:border-foreground rounded-lg text-foreground font-semibold transition-colors">
{ctaText}
</Link>
</motion.div>
)}
<section className="py-20 md:py-28 bg-background text-foreground border-t border-border">
<div className="container-premium">
<div className="max-w-2xl mx-auto text-center mb-16">
<h2 className="font-heading text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground mb-4">
{title}
</h2>
<p className="text-foreground/70 text-base sm:text-lg">
Prosty i przejrzysty proces rozliczenia w 3 krokach — bez zbędnych formalności.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 md:gap-8 mb-12">
{steps?.map((step: NonNullable<Props['steps']>[0], index: number) => {
const stepNumber = String(index + 1).padStart(2, '0')
return (
<div
key={step.id || index}
className="bg-card border border-border rounded-2xl p-6 sm:p-8 shadow-xs flex flex-col justify-between hover:border-accent/40 transition-colors"
>
<div>
<div className="font-heading text-3xl font-extrabold text-accent/80 mb-4">
{stepNumber}
</div>
<h3 className="font-heading text-xl font-bold text-foreground mb-3 leading-snug">
{step.title}
</h3>
<p className="text-foreground/75 text-sm sm:text-base leading-relaxed">
{step.description}
</p>
</div>
</div>
)
})}
</div>
{ctaText && (
<div className="text-center">
<Link
href="/jak-sie-umowic"
className="inline-flex items-center gap-2 px-8 py-4 bg-card hover:bg-accent/5 border border-border hover:border-foreground/40 rounded-xl text-foreground font-semibold text-base transition-colors"
>
<span>{ctaText}</span>
<ArrowRight size={18} />
</Link>
</div>
)}
</div>
</section>
)