Components
3DCard Component
Components
- 3DCard Component
- AirpodsProLeft Component
- AirpodsProRight Component
- Alert Component
- Audio Component
- Button Component
- Card Component
- ChargingIconRight Component
- ChargingTextLeft Component
- Checkbox Component
- Collapse Component
- EmptyState Component
- ErrorMessage Component
- Form Component
- GridLayout Component
- HelpTooltip Component
- Image Component
- Input Component
- Lamp Component
- LightBox Component
- Modal Component
- MovingBorder Component
- PageLoading Component
- Popover Component
- PropertyDefault Component
- Radio Component
- RangeSlider Component
- Select
- SilentIconLeft Component
- SongThumbnail Component
- SilentTextRight Component
- Spinner Component
- TabButton Component
- TextArea Component
- Toggle Component
- Toggle2 Component
- Tooltip Component
- WarningMessage Component
Components
3DCard Component
3DCard
This component provides 3DCard functionality.
Props
prop1
: Description of prop1.prop2
: Description of prop2.
Usage
import { 3DCard } from './3DCard';
const props = {};
<3DCard prop1="value1" prop2="value2" />;
'use client';
import cn from '../cn';
import React, {
createContext,
useState,
useContext,
useRef,
useEffect
} from 'react';
const MouseEnterContext = createContext<
[boolean, React.Dispatch<React.SetStateAction<boolean>>] | undefined
>(undefined);
export const CardContainer = ({
children,
className,
containerClassName
}: {
children?: React.ReactNode;
className?: string;
containerClassName?: string;
}) => {
const containerRef = useRef<HTMLDivElement>(null);
const [isMouseEntered, setIsMouseEntered] = useState(false);
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
if (!containerRef.current) {
return;
}
const { left, top, width, height } =
containerRef.current.getBoundingClientRect();
const x = (e.clientX - left - width / 2) / 25;
const y = (e.clientY - top - height / 2) / 25;
containerRef.current.style.transform = `rotateY(${x}deg) rotateX(${y}deg)`;
};
const handleMouseEnter = (e: React.MouseEvent<HTMLDivElement>) => {
setIsMouseEntered(true);
if (!containerRef.current) {
return;
}
};
const handleMouseLeave = (e: React.MouseEvent<HTMLDivElement>) => {
if (!containerRef.current) {
return;
}
setIsMouseEntered(false);
containerRef.current.style.transform = `rotateY(0deg) rotateX(0deg)`;
};
return (
<MouseEnterContext.Provider value={[isMouseEntered, setIsMouseEntered]}>
<div
className={cn('items-center justify-center', containerClassName)}
style={{
perspective: '1000px'
}}
>
<div
ref={containerRef}
onMouseEnter={handleMouseEnter}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
className={cn(
'relative items-center justify-center transition-all duration-200 ease-linear',
className
)}
style={{
transformStyle: 'preserve-3d'
}}
>
{children}
</div>
</div>
</MouseEnterContext.Provider>
);
};
export const CardBody = ({
children,
className
}: {
children: React.ReactNode;
className?: string;
}) => {
return (
<div
className={cn(
'[transform-style:preserve-3d] [&>*]:[transform-style:preserve-3d]',
className
)}
>
{children}
</div>
);
};
export const CardItem = ({
as: Tag = 'div',
children,
className,
translateX = 0,
translateY = 0,
translateZ = 0,
rotateX = 0,
rotateY = 0,
rotateZ = 0,
...rest
}: {
as?: React.ElementType;
children: React.ReactNode;
className?: string;
translateX?: number | string;
translateY?: number | string;
translateZ?: number | string;
rotateX?: number | string;
rotateY?: number | string;
rotateZ?: number | string;
}) => {
const ref = useRef<HTMLDivElement>(null);
const [isMouseEntered] = useMouseEnter();
const handleAnimations = () => {
if (!ref.current) {
return;
}
if (isMouseEntered) {
ref.current.style.transform = `translateX(${translateX}px) translateY(${translateY}px) translateZ(${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`;
} else {
ref.current.style.transform = `translateX(0px) translateY(0px) translateZ(0px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)`;
}
};
useEffect(() => {
handleAnimations();
}, [isMouseEntered]);
return (
<Tag
ref={ref}
className={cn('w-max-fit transition duration-200', className)}
{...rest}
>
{children}
</Tag>
);
};
// Create a hook to use the context
export const useMouseEnter = () => {
const context = useContext(MouseEnterContext);
if (context === undefined) {
throw new Error('useMouseEnter must be used within a MouseEnterProvider');
}
return context;
};