diff --git a/components/atoms/index.ts b/components/atoms/index.ts index 0fa7156..bc5b5d6 100644 --- a/components/atoms/index.ts +++ b/components/atoms/index.ts @@ -3,4 +3,6 @@ export * from './vertical-line'; export * from './link-btn'; export * from './card'; export * from './tag'; -export * from './file-input'; \ No newline at end of file +export * from './popover'; +export * from './btn'; +export * from './file-input'; diff --git a/components/atoms/popover/component.tsx b/components/atoms/popover/component.tsx new file mode 100644 index 0000000..e85efc2 --- /dev/null +++ b/components/atoms/popover/component.tsx @@ -0,0 +1,63 @@ +'use client'; +import { cn } from '@/lib/cn'; +import { Btn } from '@/components/atoms/btn'; +import { useState, useEffect, useRef } from 'react'; + +interface Props extends React.HTMLProps { + text: React.ReactNode; + children?: React.ReactNode; +} + +export const Popover: React.FC = ({ + text, + children, + className, + ...props +}) => { + const [isVisible, setIsVisible] = useState(false); + const buttonRef = useRef(null); + const contentRef = useRef(null); + + const toggleVisibility = () => { + setIsVisible(!isVisible); + }; + + useEffect(() => { + const handleOutsideClick = (event: MouseEvent) => { + if ( + contentRef.current && + !contentRef.current.contains(event.target as Node) && + buttonRef.current && + !buttonRef.current.contains(event.target as Node) + ) { + setIsVisible(false); + } + }; + + document.addEventListener('mousedown', handleOutsideClick); + return () => { + document.removeEventListener('mousedown', handleOutsideClick); + }; + }, []); + + return ( +
+ + {text} + + + {isVisible && ( +
+ {children} +
+ )} +
+ ); +}; diff --git a/components/atoms/popover/index.ts b/components/atoms/popover/index.ts new file mode 100644 index 0000000..fb1ea5d --- /dev/null +++ b/components/atoms/popover/index.ts @@ -0,0 +1,2 @@ +export { Popover as default } from './component'; +export * from './component';