-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from Jenish-Dhanani/feat/accordion-animation
feat: Added framer motion animation to accordion open and close
- Loading branch information
Showing
2 changed files
with
122 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,46 @@ | ||
.accordion { | ||
|
||
overflow: hidden; | ||
width: 100%; | ||
} | ||
|
||
.accordion-item { | ||
border-bottom: 1px solid #ddd; | ||
margin: 8px 0px; | ||
border: 1px solid #ddd; | ||
border-radius: 4px; | ||
} | ||
.expand{ | ||
width: 100%; | ||
max-width: 15px; | ||
} | ||
.accordion-title { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
padding: 15px; | ||
cursor: pointer; | ||
background-color: #f5f5f5; | ||
border-bottom: 1px solid #ddd; | ||
} | ||
|
||
.accordion-title:hover { | ||
background-color: #e0e0e0; | ||
} | ||
|
||
.accordion-title.active { | ||
background-color: #ddd; | ||
} | ||
|
||
.accordion-content { | ||
padding: 15px; | ||
background-color: lightcyan; | ||
} | ||
overflow: hidden; | ||
width: 100%; | ||
} | ||
|
||
.expand { | ||
transition: transform 0.3s ease-in-out; | ||
} | ||
|
||
.rotate { | ||
transform: rotate(180deg); | ||
} | ||
.accordion-item { | ||
border-bottom: 1px solid #ddd; | ||
margin: 8px 0px; | ||
border: 1px solid #ddd; | ||
border-radius: 4px; | ||
overflow: hidden; | ||
} | ||
.expand { | ||
width: 100%; | ||
max-width: 15px; | ||
} | ||
.accordion-title { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
padding: 15px; | ||
cursor: pointer; | ||
background-color: #f5f5f5; | ||
border-bottom: 1px solid #ddd; | ||
} | ||
|
||
.accordion-title:hover { | ||
background-color: #e0e0e0; | ||
} | ||
|
||
.accordion-title.active { | ||
background-color: #ddd; | ||
} | ||
|
||
.accordion-content { | ||
padding: 15px; | ||
background-color: lightcyan; | ||
} | ||
|
||
.expand { | ||
transition: transform 0.3s ease-in-out; | ||
} | ||
|
||
.rotate { | ||
transform: rotate(180deg); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,86 @@ | ||
// Import necessary React components and styling | ||
import React, { useState } from 'react'; | ||
import "./Accordion.css"; | ||
import Expand from '../assets/expand_more.png' | ||
export default function Accordion({items}) { | ||
import { motion, AnimatePresence } from 'framer-motion'; | ||
import './Accordion.css'; | ||
import Expand from '../assets/expand_more.png'; | ||
|
||
// Individual Accordion Item component | ||
const AccordionItem = ({ item, index, isActive, onClick }) => { | ||
// Destructure title and content from item | ||
const { title, content } = item; | ||
|
||
return ( | ||
// Use Framer Motion for layout animation | ||
<motion.div className='accordion-item' layout> | ||
{/* Title section with onClick handler */} | ||
<motion.div | ||
className={`accordion-title ${isActive ? 'active' : ''}`} | ||
onClick={() => onClick(index)} | ||
> | ||
{title} | ||
{/* Expand icon with rotation animation */} | ||
<motion.img | ||
className={`expand ${isActive ? 'rotate' : ''}`} | ||
src={Expand} | ||
alt='expand' | ||
initial={false} | ||
/> | ||
</motion.div> | ||
{/* AnimatePresence for handling enter/exit animations */} | ||
<AnimatePresence> | ||
{/* Container for content with background color animation */} | ||
<motion.div | ||
key={index} | ||
initial={false} | ||
animate={{ backgroundColor: isActive ? '#f1f1f1' : '#fff' }} | ||
> | ||
<AnimatePresence> | ||
{/* Content animation when item is active */} | ||
{isActive && ( | ||
<motion.div | ||
key='content' | ||
layout | ||
initial={{ opacity: 0, height: 0 }} | ||
animate={{ opacity: 1, height: 'auto' }} | ||
exit={{ opacity: 0, height: 0 }} | ||
> | ||
{/* Actual content of the accordion item */} | ||
<div className='accordion-content'>{content}</div> | ||
</motion.div> | ||
)} | ||
</AnimatePresence> | ||
</motion.div> | ||
</AnimatePresence> | ||
</motion.div> | ||
); | ||
}; | ||
|
||
// Main Accordion component that maps over items | ||
const Accordion = ({ items }) => { | ||
// State to track the active index | ||
const [activeIndex, setActiveIndex] = useState(null); | ||
|
||
// Handle click to toggle active index | ||
const handleClick = (index) => { | ||
setActiveIndex(activeIndex === index ? null : index); | ||
}; | ||
|
||
return ( | ||
<div className="accordion"> | ||
{items.map((item, index) => ( | ||
<div key={index} className="accordion-item"> | ||
<div | ||
className={`accordion-title ${activeIndex === index ? 'active' : ''}`} | ||
onClick={() => handleClick(index)} | ||
> | ||
{item.title} | ||
<img | ||
className={`expand ${activeIndex === index ? 'rotate' : ''}`} | ||
src={Expand} | ||
alt="expand" | ||
/> | ||
</div> | ||
{activeIndex === index && ( | ||
<div className="accordion-content">{item.content}</div> | ||
)} | ||
</div> | ||
))} | ||
</div> | ||
// Container for the entire accordion | ||
<div className='accordion'> | ||
{/* Map over items and render AccordionItem for each */} | ||
{items.map((item, index) => ( | ||
<AccordionItem | ||
key={index} | ||
item={item} | ||
index={index} | ||
isActive={activeIndex === index} | ||
onClick={handleClick} | ||
/> | ||
))} | ||
</div> | ||
); | ||
} | ||
}; | ||
|
||
// Export the Accordion component as the default export | ||
export default Accordion; |