2025-05-28 00:41:23 +02:00

59 lines
1.5 KiB
TypeScript

'use client'
import React, { useState, useRef, useEffect } from 'react'
interface PopoverProps {
text: string
children: React.ReactNode
size?: 'sm' | 'md' | 'lg' | 'xl'
}
export default function Popover({ text, children, size = 'sm' }: PopoverProps) {
const [open, setOpen] = useState(false)
const buttonRef = useRef<HTMLButtonElement>(null)
const popoverRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
popoverRef.current &&
!popoverRef.current.contains(event.target as Node) &&
!buttonRef.current?.contains(event.target as Node)
) {
setOpen(false)
}
}
document.addEventListener('mousedown', handleClickOutside)
return () => document.removeEventListener('mousedown', handleClickOutside)
}, [])
const sizeClass = {
sm: 'max-w-xs',
md: 'max-w-sm',
lg: 'max-w-md',
xl: 'max-w-lg',
}[size]
return (
<div className="relative inline-block">
<button
ref={buttonRef}
type="button"
onClick={() => setOpen((prev) => !prev)}
className="mt-1 text-xs text-gray-400 dark:text-neutral-500"
>
{text}
</button>
{open && (
<div
ref={popoverRef}
className={`fixed z-10 mt-2 ${sizeClass} rounded-lg border border-gray-200 bg-white px-4 py-3 text-sm text-gray-700 shadow-md dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-300`}
>
{children}
</div>
)}
</div>
)
}