Layout Prop
Expanding Card
Example of how to use frame motion Keyframes.
View More
Expanding Card
expanding-card.tsx
import Modal from '@/components/animations/modal' import React from 'react' const LayoutProp = () => { return ( <div className="p-5"> <ExpandingCard refresh className='w-auto h-auto flex flex-col items-start border border-[#0000001f] dark:border-[#ffffff1f] rounded-[20px] box-border p-5' Head={ <FadeIn initial={0} animate={1} duration={1} refresh={false}> <div className="w-52 h-20 rounded-md from-orange-500 to-yellow-500 bg-gradient-to-t" ></div> </FadeIn> } beforeTrigger={ <div className='mt-3 text-center text-[14px] text-yellow-600 dark:text-yellow-200 cursor-pointer'>View More</div> } afterTrigger={ <div className='mt-3 text-center text-[14px] text-emerald-600 dark:text-emerald-200 cursor-pointer'>View Less</div> } > <div className='mt-3'> <div className='font-medium'>Card Tilte</div> <div className='text-[12px] opacity-80 max-w-80'>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Veniam nemo eaque error inventore dolor pariatur quis. Laborum omnis architecto voluptatibus nihil, maxime nemo nisi neque eveniet reprehenderit laboriosam dolor excepturi!</div> </div> </ExpandingCard> </div> ) } export default LayoutProp "use client" import React, { useEffect, useState } from 'react'; import { Preview } from '../common/display'; import { motion } from "framer-motion"; interface CardProps { children: React.ReactNode; Head: React.ReactNode; className?: string; beforeTrigger: React.ReactNode; afterTrigger: React.ReactNode; refresh:boolean; } const ExpandingCard = ({ children, className, Head, beforeTrigger, afterTrigger, refresh }: CardProps) => { const [isExpanded, setIsExpanded] = useState(false); const [count, setCount] = useState(0); return ( <Preview SetCount={setCount} isRefreshing={refresh} animeName='FadeIn'> <motion.div key={count} layout onClick={() => setIsExpanded(!isExpanded)} className={className}> <motion.div layout>{Head}</motion.div> {isExpanded && <motion.div layout> {children} </motion.div>} <motion.div layout> {isExpanded ? afterTrigger:beforeTrigger} </motion.div> </motion.div> </Preview> ); } export default ExpandingCard; interface PreviewerProps { children: React.ReactNode; SetCount: (count: number) => void; isRefreshing: boolean; animeName:string hideIcon?: boolean; } export const Preview = ({ children, SetCount, isRefreshing, animeName, hideIcon=false }: PreviewerProps) => { const [count, setCount] = useState(0); const [isLoading, setIsLoading] = useState(false); const handleClick = () => { setIsLoading(true); setCount(count + 1); SetCount(count + 1); setTimeout(() => { setIsLoading(false); }, 400); // Timeout duration matches the animation duration }; return ( <div className="w-full h-full flex flex-col"> <div className="w-full flex-1 flex justify-center items-center"> {children} </div> {isRefreshing && <div className="h-[50px] w-full px-6 rounded-b-[24px] flex justify-between"> <span>{animeName}</span>{!hideIcon && <RotateCw onClick={handleClick} className={isLoading ? 'animate-spin duration-200' : 'animate-none'} />} </div> } </div> ) };