website-monitor/frontend/components/landing/SEODemoVisual.tsx

126 lines
4.7 KiB
TypeScript

'use client'
import { motion } from 'framer-motion'
import { useState, useEffect } from 'react'
import { TrendingDown, TrendingUp } from 'lucide-react'
export function SEODemoVisual() {
const [phase, setPhase] = useState(0)
useEffect(() => {
const interval = setInterval(() => {
setPhase(p => (p + 1) % 2)
}, 3000)
return () => clearInterval(interval)
}, [])
const oldMeta = "Best enterprise software for teams of all sizes. Try free for 30 days."
const newMeta = "Best enterprise software for teams of all sizes. Try free for 30 days. Now with AI-powered analytics and real-time collaboration."
return (
<div className="relative h-full min-h-[200px] bg-gradient-to-br from-background via-background to-[hsl(var(--teal))]/5 rounded-xl p-4 overflow-hidden">
{/* SERP Result */}
<div className="space-y-4">
{/* Ranking Indicator */}
<div className="flex items-center justify-between">
<div className="text-xs font-mono text-muted-foreground">
google.com/search
</div>
<motion.div
className="flex items-center gap-1 px-2 py-1 rounded-full bg-background border border-border"
animate={{
borderColor: phase === 0 ? 'hsl(var(--border))' : 'hsl(var(--burgundy))',
backgroundColor: phase === 0 ? 'hsl(var(--background))' : 'hsl(var(--burgundy) / 0.1)'
}}
transition={{ duration: 0.5 }}
>
<span className="text-xs font-bold">Ranking:</span>
<motion.span
key={phase}
initial={{ y: -10, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 10, opacity: 0 }}
className="text-xs font-bold"
>
#{phase === 0 ? '3' : '5'}
</motion.span>
{phase === 1 && (
<motion.div
initial={{ scale: 0, rotate: -180 }}
animate={{ scale: 1, rotate: 0 }}
>
<TrendingDown className="h-3 w-3 text-[hsl(var(--burgundy))]" />
</motion.div>
)}
</motion.div>
</div>
{/* SERP Snippet */}
<motion.div
className="space-y-2 p-3 rounded-lg border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950"
animate={{
borderColor: phase === 0 ? '#27272a' : 'hsl(var(--burgundy))',
boxShadow: phase === 0
? '0 1px 3px rgba(0,0,0,0.2)'
: '0 0 20px hsl(var(--burgundy) / 0.2)'
}}
transition={{ duration: 0.5 }}
>
{/* URL */}
<div className="flex items-center gap-2">
<div className="w-4 h-4 rounded-full bg-zinc-800" />
<span className="text-[10px] text-zinc-500 font-mono">
competitor.com/product
</span>
</div>
{/* Title */}
<h4 className="text-sm font-bold text-zinc-300 line-clamp-1">
Best Enterprise Software Solution 2026
</h4>
{/* Meta Description with change highlighting */}
<motion.p
className="text-[11px] text-zinc-500 leading-relaxed relative"
layout
>
<motion.span
animate={{
backgroundColor: phase === 1 ? 'hsl(var(--burgundy) / 0.1)' : 'transparent',
color: phase === 1 ? 'hsl(var(--burgundy))' : 'inherit'
}}
transition={{ duration: 0.5 }}
className="inline-block rounded px-0.5"
>
{phase === 0 ? oldMeta : newMeta}
</motion.span>
{/* Change indicator */}
{phase === 1 && (
<motion.span
initial={{ opacity: 0, x: -5 }}
animate={{ opacity: 1, x: 0 }}
className="absolute -right-2 top-0 px-1.5 py-0.5 rounded bg-[hsl(var(--burgundy))] text-[8px] font-bold text-white"
>
Changed
</motion.span>
)}
</motion.p>
</motion.div>
{/* Alert Badge */}
{phase === 1 && (
<motion.div
initial={{ opacity: 0, y: 5, scale: 0.9 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
className="flex items-center justify-center gap-2 text-[10px] font-bold text-[hsl(var(--teal))] uppercase tracking-wider"
>
<span className="w-1.5 h-1.5 rounded-full bg-[hsl(var(--teal))] animate-pulse" />
Meta Description Changed
</motion.div>
)}
</div>
</div>
)
}