From 18f56afd8294dadabf03f4365f4225189968a36b Mon Sep 17 00:00:00 2001 From: Mahyar Khanbolooki Date: Mon, 11 Aug 2025 21:03:22 +0330 Subject: [PATCH] add: accordion component --- src/components/utils/Accordion.tsx | 94 ++++++++++++++++++++++++++++++ src/hooks/helpers/useToggle.tsx | 4 +- 2 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/components/utils/Accordion.tsx diff --git a/src/components/utils/Accordion.tsx b/src/components/utils/Accordion.tsx new file mode 100644 index 0000000..b08b6af --- /dev/null +++ b/src/components/utils/Accordion.tsx @@ -0,0 +1,94 @@ +'use client'; + +import useToggle from '@/hooks/helpers/useToggle'; +import clsx from 'clsx' +import { motion } from 'framer-motion'; +import { Icon } from 'iconsax-react' +import { ChevronDown } from 'lucide-react'; +import React, { useEffect } from 'react' + +interface DropdownProps extends React.HTMLAttributes { + initial?: boolean, + children?: React.ReactNode + title?: string + icon?: Icon + group?: string +}; + +function Accordion({ initial, group, title, icon: Icon, children, className, ...rest }: DropdownProps) { + const { state, toggle, set } = useToggle(initial); + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (event.target) { + const targetGroup = (event.target as HTMLElement).getAttribute('data-group'); + if (targetGroup && targetGroup === group) { + set?.(false) + } + } + }; + if (group && state) { + document.addEventListener('click', handleClickOutside); + } + + return () => { + document.removeEventListener('click', handleClickOutside); + }; + }, [group, set, state]); + + + return ( +
+ + + +
+ {children} +
+
+
+ ) +} + +export default Accordion \ No newline at end of file diff --git a/src/hooks/helpers/useToggle.tsx b/src/hooks/helpers/useToggle.tsx index 8f36859..a6ad6a7 100644 --- a/src/hooks/helpers/useToggle.tsx +++ b/src/hooks/helpers/useToggle.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' -const useToggle = () => { - const [state, setState] = useState(false); +const useToggle = (initial?: boolean) => { + const [state, setState] = useState(initial ?? false); const toggle = (e?: React.MouseEvent | null) => { if (e) {