Image and text animation
diwali
This commit is contained in:
59
src/components/PillButton.module.css
Normal file
59
src/components/PillButton.module.css
Normal file
@ -0,0 +1,59 @@
|
||||
.pillButton {
|
||||
@apply relative bg-white text-black rounded-full px-6 py-2 text-lg font-sans flex items-center justify-center shadow-md transition duration-300 ease-in-out;
|
||||
}
|
||||
|
||||
.pillButton:not(:hover) .arrow {
|
||||
@apply hidden
|
||||
}
|
||||
|
||||
.arrow {
|
||||
@apply ml-2 transform -translate-x-5 opacity-0 transition-transform duration-300 ease-in-out;
|
||||
}
|
||||
|
||||
.pillButton:hover .arrow {
|
||||
@apply transform duration-300 translate-x-0 opacity-100 transition-transform ease-in-out;
|
||||
}
|
||||
|
||||
.pillButton:hover {
|
||||
@apply shadow-lg transform duration-300 translate-x-0 opacity-100 transition-transform ease-in-out;
|
||||
}
|
||||
|
||||
|
||||
/* Button style */
|
||||
/* .pillButton {
|
||||
background-color: white;
|
||||
border: none;
|
||||
border-radius: 30px;
|
||||
padding: 10px 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
|
||||
} */
|
||||
|
||||
/* Arrow style */
|
||||
/* .arrow {
|
||||
margin-left: 10px;
|
||||
transform: translateX(-20px);
|
||||
opacity: 0;
|
||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||
} */
|
||||
|
||||
/* Hover effect */
|
||||
/* .pillButton:hover {
|
||||
background-color: black;
|
||||
color: white;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.pillButton:hover .arrow {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
*/
|
||||
16
src/components/PillButton.tsx
Normal file
16
src/components/PillButton.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import styles from './PillButton.module.css';
|
||||
|
||||
type PillButtonProps = {
|
||||
text: string; // text prop is now required
|
||||
onClick?: () => void; // onClick is optional
|
||||
};
|
||||
|
||||
export function PillButton({ text, onClick }: PillButtonProps) {
|
||||
return (
|
||||
<button onClick={onClick} className={styles.pillButton}>
|
||||
{text}
|
||||
<span className={styles.arrow}>→</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
38
src/components/animated-image.tsx
Normal file
38
src/components/animated-image.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
// src/components/AnimatedImage.tsx
|
||||
import React, { ImgHTMLAttributes, useRef } from 'react';
|
||||
import useInView from '@/hooks/useInView';
|
||||
|
||||
interface AnimatedImageProps extends ImgHTMLAttributes<HTMLImageElement> {
|
||||
src: string;
|
||||
alt: string;
|
||||
className?: string;
|
||||
threshold?: number; // New prop
|
||||
}
|
||||
|
||||
const AnimatedImage: React.FC<AnimatedImageProps> = ({
|
||||
src,
|
||||
alt,
|
||||
className = '',
|
||||
threshold,
|
||||
...props
|
||||
}) => {
|
||||
const ref = useRef<HTMLImageElement>(null);
|
||||
const isVisible = useInView(ref, {
|
||||
threshold: threshold ?? 0.1,
|
||||
triggerOnce: true,
|
||||
});
|
||||
|
||||
return (
|
||||
<img
|
||||
ref={ref}
|
||||
src={src}
|
||||
alt={alt}
|
||||
className={`opacity-0 transform scale-95 transition-opacity transition-transform duration-700 ease-out ${
|
||||
isVisible ? 'opacity-100 scale-100' : ''
|
||||
} ${className}`}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnimatedImage;
|
||||
36
src/components/animated-text.tsx
Normal file
36
src/components/animated-text.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
// src/components/AnimatedText.tsx
|
||||
import { ReactNode, useRef } from 'react';
|
||||
import useInView from '@/hooks/useInView';
|
||||
|
||||
interface AnimatedTextProps {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
startClass?: string;
|
||||
finishClass?: string;
|
||||
threshold?: number; // New prop
|
||||
}
|
||||
|
||||
export function AnimatedText({
|
||||
children,
|
||||
className = '',
|
||||
startClass,
|
||||
finishClass,
|
||||
threshold,
|
||||
}: AnimatedTextProps) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const isVisible = useInView(ref, {
|
||||
threshold: threshold ?? 0.1,
|
||||
triggerOnce: true,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={`transition-[opacity, transform] ease-out duration-1000 ${
|
||||
isVisible ? 'opacity-100' : 'opacity-0'
|
||||
} ${isVisible ? finishClass : startClass} ${className}`}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user