'use client' import { useState } from 'react' import { motion } from 'framer-motion' import { cn, formatNumber } from '@ciphera-net/ui' interface FunnelChartProps { steps: Array<{ name: string visitors: number dropoff: number conversion: number }> className?: string } export default function FunnelChart({ steps, className }: FunnelChartProps) { const [hoveredIndex, setHoveredIndex] = useState(null) if (!steps.length) return null const maxVisitors = steps[0].visitors const n = steps.length return (
{/* Left labels */}
{steps.map((step, i) => (
Step {i + 1}

{step.name}

))}
{/* Funnel segments */}
{steps.map((step, i) => { const topPct = maxVisitors > 0 ? Math.max(30, (step.visitors / maxVisitors) * 100) : 100 const bottomPct = steps[i + 1] ? Math.max(30, (steps[i + 1].visitors / maxVisitors) * 100) : topPct * 0.7 const topInset = (100 - topPct) / 2 const bottomInset = (100 - bottomPct) / 2 const opacity = Math.max(0.3, 1 - i * (0.55 / n)) const isHovered = hoveredIndex === i return ( setHoveredIndex(i)} onMouseLeave={() => setHoveredIndex(null)} /> ) })}
{/* Right stats */}
{steps.map((step, i) => (

{formatNumber(step.visitors)}

{i > 0 ? (
↓{Math.round(step.dropoff)}% {Math.round(step.conversion)}%
) : ( baseline )}
))}
) }