1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- import { Popover, Transition } from '@headlessui/react'
- import { Fragment, cloneElement, useRef } from 'react'
- import s from './style.module.css'
- type IPopover = {
- className?: string
- htmlContent: React.ReactNode
- trigger?: 'click' | 'hover'
- position?: 'bottom' | 'br'
- btnElement?: string | React.ReactNode
- btnClassName?: string | ((open: boolean) => string)
- }
- const timeoutDuration = 100
- export default function CustomPopover({
- trigger = 'hover',
- position = 'bottom',
- htmlContent,
- btnElement,
- className,
- btnClassName,
- }: IPopover) {
- const buttonRef = useRef<HTMLButtonElement>(null)
- const timeOutRef = useRef<NodeJS.Timeout | null>(null)
- const onMouseEnter = (isOpen: boolean) => {
- timeOutRef.current && clearTimeout(timeOutRef.current)
- !isOpen && buttonRef.current?.click()
- }
- const onMouseLeave = (isOpen: boolean) => {
- timeOutRef.current = setTimeout(() => {
- isOpen && buttonRef.current?.click()
- }, timeoutDuration)
- }
- return (
- <Popover className="relative">
- {({ open }: { open: boolean }) => {
- return (
- <>
- <div
- {...(trigger !== 'hover'
- ? {}
- : {
- onMouseLeave: () => onMouseLeave(open),
- onMouseEnter: () => onMouseEnter(open),
- })
- }
- >
- <Popover.Button
- ref={buttonRef}
- className={`group ${s.popupBtn} ${open ? '' : 'bg-gray-100'} ${!btnClassName ? '' : typeof btnClassName === 'string' ? btnClassName : btnClassName?.(open)}`}
- >
- {btnElement}
- </Popover.Button>
- <Transition
- as={Fragment}
- enter="transition ease-out duration-200"
- enterFrom="opacity-0 translate-y-1"
- enterTo="opacity-100 translate-y-0"
- leave="transition ease-in duration-150"
- leaveFrom="opacity-100 translate-y-0"
- leaveTo="opacity-0 translate-y-1"
- >
- <Popover.Panel
- className={`${s.popupPanel} ${position === 'br' ? 'right-0' : 'transform -translate-x-1/2 left-1/2'} ${className}`}
- {...(trigger !== 'hover'
- ? {}
- : {
- onMouseLeave: () => onMouseLeave(open),
- onMouseEnter: () => onMouseEnter(open),
- })
- }>
- <div
- className={s.panelContainer}
- {...(trigger !== 'hover'
- ? {}
- : {
- onMouseLeave: () => onMouseLeave(open),
- onMouseEnter: () => onMouseEnter(open),
- })
- }
- >
- {cloneElement(htmlContent as React.ReactElement, {
- onClose: () => onMouseLeave(open),
- })}
- </div>
- </Popover.Panel>
- </Transition>
- </div>
- </>
- )
- }}
- </Popover>
- )
- }
|