EmberClone/apps/web/src/components/Accordion.tsx

61 lines
1.7 KiB
TypeScript

import React, { useState } from 'react';
import { ChevronDown } from 'lucide-react';
interface AccordionItem {
id: string;
title: string;
content: React.ReactNode;
}
interface AccordionProps {
items: AccordionItem[];
allowMultiple?: boolean;
}
export default function Accordion({ items, allowMultiple = false }: AccordionProps) {
const [openIds, setOpenIds] = useState<Set<string>>(new Set());
const toggleItem = (id: string) => {
setOpenIds((prev) => {
const next = new Set(prev);
if (next.has(id)) {
next.delete(id);
} else {
if (!allowMultiple) {
next.clear();
}
next.add(id);
}
return next;
});
};
return (
<div className="flex flex-col gap-2 w-full">
{items.map((item) => {
const isOpen = openIds.has(item.id);
return (
<div
key={item.id}
className="border border-slate-200 dark:border-slate-800 rounded-lg overflow-hidden"
>
<button
onClick={() => toggleItem(item.id)}
className="flex items-center justify-between w-full p-4 text-left font-medium transition-colors hover:bg-slate-50 dark:hover:bg-slate-900"
>
<span>{item.title}</span>
<ChevronDown
className={`w-5 h-5 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}
/>
</button>
{isOpen && (
<div className="p-4 pt-0 border-t border-slate-100 dark:border-slate-800 text-slate-600 dark:text-slate-400">
{item.content}
</div>
)}
</div>
);
})}
</div>
);
}