Skip to content

Commit

Permalink
Merge pull request #51 from Jenish-Dhanani/feat/accordion-animation
Browse files Browse the repository at this point in the history
feat: Added framer motion animation to accordion open and close
  • Loading branch information
vaishnavi-3969 authored Oct 23, 2023
2 parents c72cd96 + f622a5d commit 22857d4
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 68 deletions.
88 changes: 44 additions & 44 deletions src/components/Accordion.css
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);
}
102 changes: 78 additions & 24 deletions src/components/Accordion.js
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;

0 comments on commit 22857d4

Please sign in to comment.