117 lines
3.0 KiB
Plaintext
117 lines
3.0 KiB
Plaintext
---
|
|
interface Props {
|
|
animation: 'fade' | 'scale' | 'slide-up' | 'slide-down' | 'slide-left' | 'slide-right' | 'pulse';
|
|
duration?: number; // in milliseconds
|
|
delay?: number; // in milliseconds
|
|
easing?: string; // CSS easing function
|
|
class?: string;
|
|
tag?: string; // HTML tag to use
|
|
}
|
|
|
|
const {
|
|
animation,
|
|
duration = 300,
|
|
delay = 0,
|
|
easing = 'ease',
|
|
class: className = '',
|
|
tag: Tag = 'div'
|
|
} = Astro.props;
|
|
|
|
const animationClasses = {
|
|
'fade': 'animate-fade',
|
|
'scale': 'animate-scale',
|
|
'slide-up': 'animate-slide-up',
|
|
'slide-down': 'animate-slide-down',
|
|
'slide-left': 'animate-slide-left',
|
|
'slide-right': 'animate-slide-right',
|
|
'pulse': 'animate-pulse'
|
|
};
|
|
|
|
const animationClass = animationClasses[animation] || '';
|
|
---
|
|
|
|
<Tag class:list={[animationClass, className]}>
|
|
<style define:vars={{
|
|
animationDuration: `${duration}ms`,
|
|
animationDelay: `${delay}ms`,
|
|
animationEasing: easing
|
|
}}>
|
|
.animate-fade {
|
|
animation: fade var(--animationDuration) var(--animationEasing) var(--animationDelay) both;
|
|
}
|
|
|
|
.animate-scale {
|
|
animation: scale var(--animationDuration) var(--animationEasing) var(--animationDelay) both;
|
|
}
|
|
|
|
.animate-slide-up {
|
|
animation: slideUp var(--animationDuration) var(--animationEasing) var(--animationDelay) both;
|
|
}
|
|
|
|
.animate-slide-down {
|
|
animation: slideDown var(--animationDuration) var(--animationEasing) var(--animationDelay) both;
|
|
}
|
|
|
|
.animate-slide-left {
|
|
animation: slideLeft var(--animationDuration) var(--animationEasing) var(--animationDelay) both;
|
|
}
|
|
|
|
.animate-slide-right {
|
|
animation: slideRight var(--animationDuration) var(--animationEasing) var(--animationDelay) both;
|
|
}
|
|
|
|
.animate-pulse {
|
|
animation: pulse var(--animationDuration) var(--animationEasing) var(--animationDelay) infinite;
|
|
}
|
|
</style>
|
|
<slot />
|
|
</Tag>
|
|
|
|
<style>
|
|
|
|
@keyframes fade {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
@keyframes scale {
|
|
from { transform: scale(0.95); opacity: 0; }
|
|
to { transform: scale(1); opacity: 1; }
|
|
}
|
|
|
|
@keyframes slideUp {
|
|
from { transform: translateY(20px); opacity: 0; }
|
|
to { transform: translateY(0); opacity: 1; }
|
|
}
|
|
|
|
@keyframes slideDown {
|
|
from { transform: translateY(-20px); opacity: 0; }
|
|
to { transform: translateY(0); opacity: 1; }
|
|
}
|
|
|
|
@keyframes slideLeft {
|
|
from { transform: translateX(20px); opacity: 0; }
|
|
to { transform: translateX(0); opacity: 1; }
|
|
}
|
|
|
|
@keyframes slideRight {
|
|
from { transform: translateX(-20px); opacity: 0; }
|
|
to { transform: translateX(0); opacity: 1; }
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0% { transform: scale(1); }
|
|
50% { transform: scale(1.05); }
|
|
100% { transform: scale(1); }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.animate-fade, .animate-scale, .animate-slide-up,
|
|
.animate-slide-down, .animate-slide-left,
|
|
.animate-slide-right, .animate-pulse {
|
|
animation: none !important;
|
|
transition: none !important;
|
|
}
|
|
}
|
|
</style>
|