gitea
This commit is contained in:
148
frontend/components/landing/PolicyDemoVisual.tsx
Normal file
148
frontend/components/landing/PolicyDemoVisual.tsx
Normal file
@@ -0,0 +1,148 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'framer-motion'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { FileCheck, Check } from 'lucide-react'
|
||||
|
||||
export function PolicyDemoVisual() {
|
||||
const [phase, setPhase] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setPhase(p => (p + 1) % 2)
|
||||
}, 3000)
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="relative h-full min-h-[200px] bg-gradient-to-br from-background via-background to-[hsl(var(--burgundy))]/5 rounded-xl p-4 overflow-hidden">
|
||||
{/* Document Header */}
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<FileCheck className="h-4 w-4 text-[hsl(var(--burgundy))]" />
|
||||
<span className="text-xs font-bold text-foreground">Terms of Service</span>
|
||||
</div>
|
||||
<motion.div
|
||||
className="px-2 py-0.5 rounded-full border text-[9px] font-bold"
|
||||
animate={{
|
||||
borderColor: phase === 1 ? 'hsl(var(--teal))' : 'hsl(var(--border))',
|
||||
backgroundColor: phase === 1 ? 'hsl(var(--teal) / 0.1)' : 'transparent',
|
||||
color: phase === 1 ? 'hsl(var(--teal))' : 'hsl(var(--muted-foreground))'
|
||||
}}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
{phase === 0 ? 'v2.1' : 'v2.2'}
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* Document Content */}
|
||||
<motion.div
|
||||
className="space-y-2 p-3 rounded-lg border-2 bg-white overflow-hidden"
|
||||
animate={{
|
||||
borderColor: phase === 1 ? 'hsl(var(--teal))' : 'hsl(var(--border))',
|
||||
boxShadow: phase === 1
|
||||
? '0 0 20px hsl(var(--teal) / 0.3)'
|
||||
: '0 1px 3px rgba(0,0,0,0.1)'
|
||||
}}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
{/* Section 4.2 */}
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-[10px] font-bold text-[hsl(var(--primary))]">
|
||||
Section 4.2 - Data Retention
|
||||
</div>
|
||||
|
||||
{/* Text Lines */}
|
||||
<div className="space-y-1 text-[9px] text-muted-foreground leading-relaxed">
|
||||
<p>We will retain your personal data for</p>
|
||||
|
||||
{/* Changing text */}
|
||||
<motion.div
|
||||
className="relative rounded"
|
||||
layout
|
||||
>
|
||||
<motion.p
|
||||
animate={{
|
||||
backgroundColor: phase === 1 ? 'hsl(var(--burgundy) / 0.15)' : 'transparent',
|
||||
paddingLeft: phase === 1 ? '4px' : '0px',
|
||||
paddingRight: phase === 1 ? '4px' : '0px',
|
||||
color: phase === 1 ? 'hsl(var(--burgundy))' : 'hsl(var(--muted-foreground))',
|
||||
fontWeight: phase === 1 ? 600 : 400
|
||||
}}
|
||||
transition={{ duration: 0.4 }}
|
||||
className="relative inline-block rounded"
|
||||
>
|
||||
{phase === 0 ? (
|
||||
'as long as necessary to fulfill purposes'
|
||||
) : (
|
||||
<motion.span
|
||||
initial={{ opacity: 0, y: -5 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
a minimum of 90 days after account deletion
|
||||
</motion.span>
|
||||
)}
|
||||
</motion.p>
|
||||
|
||||
{/* Change highlight indicator */}
|
||||
{phase === 1 && (
|
||||
<motion.div
|
||||
initial={{ scaleX: 0 }}
|
||||
animate={{ scaleX: 1 }}
|
||||
transition={{ duration: 0.4 }}
|
||||
className="absolute -left-1 top-0 bottom-0 w-0.5 bg-[hsl(var(--burgundy))] rounded-full origin-left"
|
||||
/>
|
||||
)}
|
||||
</motion.div>
|
||||
|
||||
<p>outlined in our Privacy Policy.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Diff Stats */}
|
||||
{phase === 1 && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
transition={{ delay: 0.3 }}
|
||||
className="pt-2 border-t border-border flex items-center justify-between"
|
||||
>
|
||||
<div className="flex items-center gap-3 text-[8px] text-muted-foreground">
|
||||
<span className="flex items-center gap-1">
|
||||
<span className="w-2 h-2 rounded bg-green-500/20 border border-green-500" />
|
||||
+18 words
|
||||
</span>
|
||||
<span className="flex items-center gap-1">
|
||||
<span className="w-2 h-2 rounded bg-red-500/20 border border-red-500" />
|
||||
-7 words
|
||||
</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</motion.div>
|
||||
|
||||
{/* Audit Trail Badge */}
|
||||
{phase === 1 && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 5, scale: 0.9 }}
|
||||
animate={{ opacity: 1, y: 0, scale: 1 }}
|
||||
transition={{ delay: 0.5 }}
|
||||
className="mt-3 flex items-center gap-2 p-2 rounded-lg bg-[hsl(var(--teal))]/10 border border-[hsl(var(--teal))]/30"
|
||||
>
|
||||
<div className="flex-shrink-0 flex items-center justify-center w-5 h-5 rounded-full bg-[hsl(var(--teal))] text-white">
|
||||
<Check className="h-3 w-3" strokeWidth={3} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="text-[9px] font-bold text-[hsl(var(--teal))]">
|
||||
Audit trail saved
|
||||
</div>
|
||||
<div className="text-[8px] text-muted-foreground">
|
||||
Snapshot archived for compliance
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user