555 lines
24 KiB
TypeScript
555 lines
24 KiB
TypeScript
"use client"
|
||
|
||
import { useState } from 'react'
|
||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||
import { Badge } from '@/components/ui/badge'
|
||
import { Button } from '@/components/ui/button'
|
||
import { Avatar, AvatarFallback } from '@/components/ui/avatar'
|
||
import { Progress } from '@/components/ui/progress'
|
||
import {
|
||
Play,
|
||
Pause,
|
||
RotateCcw,
|
||
Zap,
|
||
Sparkles,
|
||
Loader,
|
||
RefreshCw,
|
||
Heart,
|
||
Star,
|
||
ArrowRight,
|
||
ChevronDown,
|
||
Bell,
|
||
Settings,
|
||
CheckCircle,
|
||
AlertTriangle,
|
||
Package,
|
||
Truck,
|
||
ShoppingCart
|
||
} from 'lucide-react'
|
||
|
||
export function AnimationsDemo() {
|
||
const [isAnimating, setIsAnimating] = useState(false)
|
||
const [hoveredCard, setHoveredCard] = useState<number | null>(null)
|
||
const [progress, setProgress] = useState(0)
|
||
const [isLoading, setIsLoading] = useState(false)
|
||
const [showNotification, setShowNotification] = useState(false)
|
||
|
||
const startProgress = () => {
|
||
setProgress(0)
|
||
const interval = setInterval(() => {
|
||
setProgress((prev) => {
|
||
if (prev >= 100) {
|
||
clearInterval(interval)
|
||
return 100
|
||
}
|
||
return prev + 10
|
||
})
|
||
}, 200)
|
||
}
|
||
|
||
const showLoadingDemo = () => {
|
||
setIsLoading(true)
|
||
setTimeout(() => setIsLoading(false), 3000)
|
||
}
|
||
|
||
const triggerNotification = () => {
|
||
setShowNotification(true)
|
||
setTimeout(() => setShowNotification(false), 3000)
|
||
}
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* CSS Анимации */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">CSS Анимации</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
{/* Spin Animations */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Вращение и загрузка</h4>
|
||
<div className="grid grid-cols-4 gap-4">
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<div className="w-8 h-8 border-2 border-white/20 border-t-white rounded-full animate-spin mx-auto mb-2"></div>
|
||
<p className="text-white/70 text-xs">animate-spin</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<RefreshCw className="w-8 h-8 text-white/70 animate-spin mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">icon spin</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<Loader className="w-8 h-8 text-blue-400 animate-spin mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">loader</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<div className="flex space-x-1 mx-auto w-fit mb-2">
|
||
<div className="w-2 h-2 bg-white rounded-full animate-bounce"></div>
|
||
<div className="w-2 h-2 bg-white rounded-full animate-bounce" style={{ animationDelay: '0.1s' }}></div>
|
||
<div className="w-2 h-2 bg-white rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
|
||
</div>
|
||
<p className="text-white/70 text-xs">dots bounce</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Pulse Animations */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Пульсация</h4>
|
||
<div className="grid grid-cols-4 gap-4">
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<div className="w-8 h-8 bg-green-400 rounded-full animate-pulse mx-auto mb-2"></div>
|
||
<p className="text-white/70 text-xs">pulse circle</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<Bell className="w-8 h-8 text-yellow-400 animate-pulse mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">notification</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<Heart className="w-8 h-8 text-red-400 animate-pulse mx-auto mb-2 fill-current" />
|
||
<p className="text-white/70 text-xs">heartbeat</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<div className="relative mx-auto w-8 h-8 mb-2">
|
||
<div className="absolute inset-0 bg-blue-400 rounded-full animate-ping"></div>
|
||
<div className="relative w-8 h-8 bg-blue-400 rounded-full"></div>
|
||
</div>
|
||
<p className="text-white/70 text-xs">ping</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Bounce Animations */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Подпрыгивание</h4>
|
||
<div className="grid grid-cols-3 gap-4">
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<ArrowRight className="w-8 h-8 text-white/70 animate-bounce mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">bounce arrow</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<ChevronDown className="w-8 h-8 text-white/70 animate-bounce mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">bounce down</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center">
|
||
<Button
|
||
variant="glass"
|
||
size="sm"
|
||
className="animate-bounce"
|
||
>
|
||
Кнопка
|
||
</Button>
|
||
<p className="text-white/70 text-xs mt-2">bounce button</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Hover эффекты */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">Hover эффекты</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
{/* Scale Hover */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Масштабирование при наведении</h4>
|
||
<div className="grid grid-cols-4 gap-4">
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center hover:scale-105 transition-transform cursor-pointer">
|
||
<Package className="w-8 h-8 text-blue-400 mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">scale-105</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center hover:scale-110 transition-transform cursor-pointer">
|
||
<Truck className="w-8 h-8 text-green-400 mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">scale-110</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center hover:scale-95 transition-transform cursor-pointer">
|
||
<ShoppingCart className="w-8 h-8 text-purple-400 mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">scale-95</p>
|
||
</div>
|
||
|
||
<div className="glass-card p-4 rounded-lg border border-white/10 text-center hover:-translate-y-1 transition-transform cursor-pointer">
|
||
<Star className="w-8 h-8 text-yellow-400 mx-auto mb-2" />
|
||
<p className="text-white/70 text-xs">translate-y</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Color Hover */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Изменение цвета</h4>
|
||
<div className="grid grid-cols-3 gap-4">
|
||
<Button
|
||
variant="outline"
|
||
className="hover:bg-blue-500 hover:border-blue-500 transition-colors"
|
||
>
|
||
Hover Blue
|
||
</Button>
|
||
|
||
<Button
|
||
variant="outline"
|
||
className="hover:bg-green-500 hover:border-green-500 transition-colors"
|
||
>
|
||
Hover Green
|
||
</Button>
|
||
|
||
<Button
|
||
variant="outline"
|
||
className="hover:bg-purple-500 hover:border-purple-500 transition-colors"
|
||
>
|
||
Hover Purple
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Shadow Hover */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Тени при наведении</h4>
|
||
<div className="grid grid-cols-3 gap-4">
|
||
{[1, 2, 3].map((card) => (
|
||
<div
|
||
key={card}
|
||
className="glass-card p-4 rounded-lg border border-white/10 cursor-pointer transition-all duration-300 hover:shadow-xl hover:shadow-purple-500/20"
|
||
onMouseEnter={() => setHoveredCard(card)}
|
||
onMouseLeave={() => setHoveredCard(null)}
|
||
>
|
||
<div className="text-center">
|
||
<div className={`w-12 h-12 rounded-full mx-auto mb-3 flex items-center justify-center transition-all ${
|
||
hoveredCard === card ? 'bg-purple-500/30 scale-110' : 'bg-white/10'
|
||
}`}>
|
||
<Sparkles className={`w-6 h-6 transition-colors ${
|
||
hoveredCard === card ? 'text-purple-300' : 'text-white/60'
|
||
}`} />
|
||
</div>
|
||
<p className="text-white font-medium">Карточка {card}</p>
|
||
<p className="text-white/60 text-xs">Наведите для эффекта</p>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Transition эффекты */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">Переходы (Transitions)</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
{/* Duration Examples */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Продолжительность переходов</h4>
|
||
<div className="grid grid-cols-4 gap-4">
|
||
<Button
|
||
variant="outline"
|
||
className="hover:bg-white/20 transition-all duration-75"
|
||
>
|
||
75ms
|
||
</Button>
|
||
|
||
<Button
|
||
variant="outline"
|
||
className="hover:bg-white/20 transition-all duration-150"
|
||
>
|
||
150ms
|
||
</Button>
|
||
|
||
<Button
|
||
variant="outline"
|
||
className="hover:bg-white/20 transition-all duration-300"
|
||
>
|
||
300ms
|
||
</Button>
|
||
|
||
<Button
|
||
variant="outline"
|
||
className="hover:bg-white/20 transition-all duration-500"
|
||
>
|
||
500ms
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Easing Examples */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Типы анимации</h4>
|
||
<div className="grid grid-cols-3 gap-4">
|
||
<Button
|
||
variant="outline"
|
||
className="hover:scale-110 transition-transform duration-300 ease-linear"
|
||
>
|
||
Linear
|
||
</Button>
|
||
|
||
<Button
|
||
variant="outline"
|
||
className="hover:scale-110 transition-transform duration-300 ease-in-out"
|
||
>
|
||
Ease In Out
|
||
</Button>
|
||
|
||
<Button
|
||
variant="outline"
|
||
className="hover:scale-110 transition-transform duration-300 ease-out"
|
||
>
|
||
Ease Out
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Интерактивные анимации */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">Интерактивные анимации</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
{/* Loading Progress */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Прогресс загрузки</h4>
|
||
<div className="glass-card p-4 rounded-lg border border-white/10">
|
||
<div className="flex items-center justify-between mb-4">
|
||
<span className="text-white text-sm">Прогресс: {progress}%</span>
|
||
<Button
|
||
variant="glass"
|
||
size="sm"
|
||
onClick={startProgress}
|
||
disabled={progress > 0 && progress < 100}
|
||
>
|
||
<Play className="h-4 w-4 mr-2" />
|
||
Запустить
|
||
</Button>
|
||
</div>
|
||
<Progress value={progress} className="mb-2" />
|
||
<div className="text-xs text-white/60">
|
||
{progress === 0 && "Нажмите 'Запустить' для начала"}
|
||
{progress > 0 && progress < 100 && "Загрузка..."}
|
||
{progress === 100 && "Загрузка завершена!"}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Loading States */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Состояния загрузки</h4>
|
||
<div className="glass-card p-4 rounded-lg border border-white/10">
|
||
<div className="flex items-center justify-between mb-4">
|
||
<span className="text-white text-sm">Демо загрузки (3 сек)</span>
|
||
<Button
|
||
variant="glass"
|
||
size="sm"
|
||
onClick={showLoadingDemo}
|
||
disabled={isLoading}
|
||
>
|
||
{isLoading ? (
|
||
<>
|
||
<Loader className="h-4 w-4 mr-2 animate-spin" />
|
||
Загрузка...
|
||
</>
|
||
) : (
|
||
<>
|
||
<Zap className="h-4 w-4 mr-2" />
|
||
Загрузить
|
||
</>
|
||
)}
|
||
</Button>
|
||
</div>
|
||
|
||
{isLoading && (
|
||
<div className="space-y-3">
|
||
<div className="flex items-center space-x-3">
|
||
<div className="w-4 h-4 border-2 border-white/20 border-t-white rounded-full animate-spin"></div>
|
||
<span className="text-white/70 text-sm">Подключение к серверу...</span>
|
||
</div>
|
||
<div className="flex items-center space-x-3">
|
||
<div className="w-4 h-4 border-2 border-white/20 border-t-blue-400 rounded-full animate-spin"></div>
|
||
<span className="text-white/70 text-sm">Загрузка данных...</span>
|
||
</div>
|
||
<div className="flex items-center space-x-3">
|
||
<div className="w-4 h-4 border-2 border-white/20 border-t-green-400 rounded-full animate-spin"></div>
|
||
<span className="text-white/70 text-sm">Обработка результата...</span>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
{/* Notification Animation */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Анимация уведомлений</h4>
|
||
<div className="glass-card p-4 rounded-lg border border-white/10">
|
||
<div className="flex items-center justify-between mb-4">
|
||
<span className="text-white text-sm">Всплывающее уведомление</span>
|
||
<Button
|
||
variant="glass"
|
||
size="sm"
|
||
onClick={triggerNotification}
|
||
>
|
||
<Bell className="h-4 w-4 mr-2" />
|
||
Показать
|
||
</Button>
|
||
</div>
|
||
|
||
{showNotification && (
|
||
<div className="animate-in slide-in-from-right-5 duration-300">
|
||
<div className="glass-card p-3 rounded-lg border border-green-500/30 bg-green-500/10">
|
||
<div className="flex items-center space-x-3">
|
||
<CheckCircle className="h-5 w-5 text-green-400" />
|
||
<div>
|
||
<div className="text-white font-medium text-sm">Успешно!</div>
|
||
<div className="text-green-300/70 text-xs">Операция выполнена успешно</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
{/* Animation Toggle */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Переключение анимации</h4>
|
||
<div className="glass-card p-4 rounded-lg border border-white/10">
|
||
<div className="flex items-center justify-between mb-4">
|
||
<span className="text-white text-sm">Управление анимацией</span>
|
||
<Button
|
||
variant="glass"
|
||
size="sm"
|
||
onClick={() => setIsAnimating(!isAnimating)}
|
||
>
|
||
{isAnimating ? (
|
||
<>
|
||
<Pause className="h-4 w-4 mr-2" />
|
||
Остановить
|
||
</>
|
||
) : (
|
||
<>
|
||
<Play className="h-4 w-4 mr-2" />
|
||
Запустить
|
||
</>
|
||
)}
|
||
</Button>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-4 gap-4">
|
||
<div className={`glass-card p-3 rounded-lg border border-white/10 text-center ${isAnimating ? 'animate-pulse' : ''}`}>
|
||
<div className="w-8 h-8 bg-blue-400 rounded-full mx-auto mb-2"></div>
|
||
<p className="text-white/70 text-xs">Pulse</p>
|
||
</div>
|
||
|
||
<div className={`glass-card p-3 rounded-lg border border-white/10 text-center ${isAnimating ? 'animate-bounce' : ''}`}>
|
||
<div className="w-8 h-8 bg-green-400 rounded-full mx-auto mb-2"></div>
|
||
<p className="text-white/70 text-xs">Bounce</p>
|
||
</div>
|
||
|
||
<div className={`glass-card p-3 rounded-lg border border-white/10 text-center ${isAnimating ? 'animate-spin' : ''}`}>
|
||
<div className="w-8 h-8 bg-purple-400 rounded-full mx-auto mb-2"></div>
|
||
<p className="text-white/70 text-xs">Spin</p>
|
||
</div>
|
||
|
||
<div className={`glass-card p-3 rounded-lg border border-white/10 text-center transition-all duration-1000 ${isAnimating ? 'scale-110 rotate-12' : 'scale-100 rotate-0'}`}>
|
||
<div className="w-8 h-8 bg-yellow-400 rounded-full mx-auto mb-2"></div>
|
||
<p className="text-white/70 text-xs">Transform</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Сложные анимации */}
|
||
<Card className="glass-card border-white/10">
|
||
<CardHeader>
|
||
<CardTitle className="text-white">Сложные анимации</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-6">
|
||
{/* Staggered Animation */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Поэтапная анимация</h4>
|
||
<div className="glass-card p-4 rounded-lg border border-white/10">
|
||
<div className="grid grid-cols-5 gap-2">
|
||
{[1, 2, 3, 4, 5].map((item) => (
|
||
<div
|
||
key={item}
|
||
className="h-16 bg-gradient-to-r from-purple-500/20 to-pink-500/20 rounded animate-pulse border border-white/10"
|
||
style={{
|
||
animationDelay: `${item * 0.2}s`,
|
||
animationDuration: '2s'
|
||
}}
|
||
>
|
||
<div className="h-full flex items-center justify-center text-white/70 text-sm">
|
||
{item}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Chain Animation */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Цепочка анимаций</h4>
|
||
<div className="glass-card p-4 rounded-lg border border-white/10">
|
||
<div className="relative h-20">
|
||
<div className="absolute inset-0 flex items-center">
|
||
<div className="w-4 h-4 bg-blue-400 rounded-full animate-bounce"></div>
|
||
<div className="flex-1 h-0.5 bg-white/20 mx-2"></div>
|
||
<div className="w-4 h-4 bg-green-400 rounded-full animate-pulse"></div>
|
||
<div className="flex-1 h-0.5 bg-white/20 mx-2"></div>
|
||
<div className="w-4 h-4 bg-purple-400 rounded-full animate-spin"></div>
|
||
<div className="flex-1 h-0.5 bg-white/20 mx-2"></div>
|
||
<div className="w-4 h-4 bg-yellow-400 rounded-full animate-ping"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Card Flip Animation */}
|
||
<div>
|
||
<h4 className="text-white/90 text-sm font-medium mb-3">Переворот карточки</h4>
|
||
<div className="glass-card p-4 rounded-lg border border-white/10">
|
||
<div className="grid grid-cols-3 gap-4">
|
||
{[1, 2, 3].map((card) => (
|
||
<div
|
||
key={card}
|
||
className="relative h-32 [perspective:1000px] cursor-pointer group"
|
||
>
|
||
<div className="relative w-full h-full transition-transform duration-700 [transform-style:preserve-3d] group-hover:[transform:rotateY(180deg)]">
|
||
{/* Front */}
|
||
<div className="absolute inset-0 glass-card rounded-lg border border-white/10 [backface-visibility:hidden] flex items-center justify-center">
|
||
<div className="text-center">
|
||
<div className="w-8 h-8 bg-blue-400 rounded-full mx-auto mb-2"></div>
|
||
<p className="text-white text-sm">Карточка {card}</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Back */}
|
||
<div className="absolute inset-0 glass-card rounded-lg border border-white/10 [backface-visibility:hidden] [transform:rotateY(180deg)] flex items-center justify-center">
|
||
<div className="text-center">
|
||
<Settings className="w-8 h-8 text-purple-400 mx-auto mb-2" />
|
||
<p className="text-white text-sm">Настройки</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
)
|
||
}
|