Skip to content

Commit

Permalink
New component -- Accordition
Browse files Browse the repository at this point in the history
  • Loading branch information
angeldevildev committed Sep 21, 2024
1 parent 82796bb commit ed02b8f
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 0 deletions.
67 changes: 67 additions & 0 deletions app/Components/Sections/Accordition.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client'

import React, { useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { ChevronDown } from 'lucide-react'

interface AccordionItem {
title: string
content: string
}

interface ModernAccordionProps {
items: AccordionItem[]
allowMultiple?: boolean
}

export default function ModernAccordion({ items, allowMultiple = false }: ModernAccordionProps) {
const [openItems, setOpenItems] = useState<number[]>([])

const toggleItem = (index: number) => {
setOpenItems(prev => {
if (allowMultiple) {
return prev.includes(index) ? prev.filter(i => i !== index) : [...prev, index]
} else {
return prev.includes(index) ? [] : [index]
}
})
}

return (
<div className="w-full max-w-2xl mx-auto space-y-2">
{items.map((item, index) => (
<div key={index} className="border border-gray-200 rounded-lg overflow-hidden">
<motion.button
className="w-full text-left p-4 flex justify-between items-center bg-white hover:bg-gray-50 transition-colors duration-200"
onClick={() => toggleItem(index)}
aria-expanded={openItems.includes(index)}
aria-controls={`accordion-content-${index}`}
>
<span className="text-lg font-medium text-gray-900">{item.title}</span>
<motion.div
animate={{ rotate: openItems.includes(index) ? 180 : 0 }}
transition={{ duration: 0.3 }}
>
<ChevronDown className="w-5 h-5 text-gray-500" />
</motion.div>
</motion.button>
<AnimatePresence initial={false}>
{openItems.includes(index) && (
<motion.div
id={`accordion-content-${index}`}
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}
>
<div className="p-4 bg-gray-50 text-gray-700">
{item.content}
</div>
</motion.div>
)}
</AnimatePresence>
</div>
))}
</div>
)
}
21 changes: 21 additions & 0 deletions app/Components/Sections/AccorditionData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import ModernAccordion from './Accordition'

const accordionItems = [
{
title: "What is React?",
content: "React is a JavaScript library for building user interfaces, particularly single-page applications."
},
{
title: "Why use TypeScript with React?",
content: "TypeScript adds static typing to JavaScript, which can help catch errors early and improve code quality and maintainability in React projects."
},
// Add more items as needed
]

export default function AccorditionData() {
return (
<div className="p-4">
<ModernAccordion items={accordionItems} allowMultiple={true} />
</div>
)
}
133 changes: 133 additions & 0 deletions content/docs/Components/Sections/accordition.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
title: Accordition
---

import PackageManagerTabs from '../../../../app/Components/package-manager-tabs';
import StyledContainer from '../../../../app/Components/StyledContainer';
import AccorditionData from '../../../../app/Components/Sections/AccorditionData';

<StyledContainer code={`'use client'
import React, { useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { ChevronDown } from 'lucide-react'
interface AccordionItem {
title: string
content: string
}
interface ModernAccordionProps {
items: AccordionItem[]
allowMultiple?: boolean
}
export default function ModernAccordion({ items, allowMultiple = false }: ModernAccordionProps) {
const [openItems, setOpenItems] = useState<number[]>([])
const toggleItem = (index: number) => {
setOpenItems(prev => {
if (allowMultiple) {
return prev.includes(index) ? prev.filter(i => i !== index) : [...prev, index]
} else {
return prev.includes(index) ? [] : [index]
}
})
}
return (
<div className="w-full max-w-2xl mx-auto space-y-2">
{items.map((item, index) => (
<div key={index} className="border border-gray-200 rounded-lg overflow-hidden">
<motion.button
className="w-full text-left p-4 flex justify-between items-center bg-white hover:bg-gray-50 transition-colors duration-200"
onClick={() => toggleItem(index)}
aria-expanded={openItems.includes(index)}
aria-controls={\`accordion-content-\${index}\`}
>
<span className="text-lg font-medium text-gray-900">{item.title}</span>
<motion.div
animate={{ rotate: openItems.includes(index) ? 180 : 0 }}
transition={{ duration: 0.3 }}
>
<ChevronDown className="w-5 h-5 text-gray-500" />
</motion.div>
</motion.button>
<AnimatePresence initial={false}>
{openItems.includes(index) && (
<motion.div
id={\`accordion-content-\${index}\`}
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}
>
<div className="p-4 bg-gray-50 text-gray-700">
{item.content}
</div>
</motion.div>
)}
</AnimatePresence>
</div>
))}
</div>
)
}`}>
<AccorditionData />
</StyledContainer>

### Dependencies

<PackageManagerTabs
commands={{
npm: "install lucide-react",
pnpm: "install lucide-react",
yarn: "add lucide-react",
}}
/>

<br />

<PackageManagerTabs
commands={{
npm: "install framer-motion",
pnpm: "add framer-motion",
yarn: "add framer-motion",
bun: "add framer-motion"
}}
/>

### Configuration and Re-usability

`AccorditionData.tsx`:

```tsx
import ModernAccordion from 'your-path'

// Questions:

const accordionItems = [
{
title: "What is React?",
content: "React is a JavaScript library for building user interfaces, particularly single-page applications."
},
{
title: "Why use TypeScript with React?",
content: "TypeScript adds static typing to JavaScript, which can help catch errors early and improve code quality and maintainability in React projects."
},
// Add more items as needed
]

export default function AccorditionData() {
return (
<div className="p-4">
{/**Component Calling*/}
<ModernAccordion items={accordionItems} allowMultiple={true} />
</div>
)
}
```

### Usage Methods

{/**Add the usage methods*/}

0 comments on commit ed02b8f

Please sign in to comment.