67 lines
1.6 KiB
TypeScript
67 lines
1.6 KiB
TypeScript
![]() |
import { createEffect, createSignal, JSX, JSXElement, onMount, Show } from 'solid-js'
|
||
|
import usePopper from 'solid-popper'
|
||
|
import styles from './Popover.module.scss'
|
||
|
|
||
|
type Props = {
|
||
|
children: (setTooltipEl: (el: HTMLElement | null) => void) => JSX.Element
|
||
|
content: string
|
||
|
}
|
||
|
|
||
|
export const Popover = (props: Props) => {
|
||
|
const [show, setShow] = createSignal(false)
|
||
|
const [anchor, setAnchor] = createSignal<HTMLElement>()
|
||
|
const [popper, setPopper] = createSignal<HTMLElement>()
|
||
|
|
||
|
usePopper(anchor, popper, {
|
||
|
modifiers: [
|
||
|
{
|
||
|
name: 'offset',
|
||
|
options: {
|
||
|
offset: [0, 8]
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
name: 'flip',
|
||
|
options: {
|
||
|
fallbackPlacements: ['top', 'bottom']
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
})
|
||
|
|
||
|
const showEvents = ['mouseenter', 'focus']
|
||
|
const hideEvents = ['mouseleave', 'blur']
|
||
|
|
||
|
const handleMouseOver = () => setShow(true)
|
||
|
const handleMouseOut = () => setShow(false)
|
||
|
|
||
|
onMount(() => {
|
||
|
showEvents.forEach((event) => {
|
||
|
anchor().addEventListener(event, handleMouseOver)
|
||
|
})
|
||
|
hideEvents.forEach((event) => {
|
||
|
anchor().addEventListener(event, handleMouseOut)
|
||
|
})
|
||
|
return () => {
|
||
|
showEvents.forEach((event) => {
|
||
|
anchor().removeEventListener(event, handleMouseOver)
|
||
|
})
|
||
|
hideEvents.forEach((event) => {
|
||
|
anchor().removeEventListener(event, handleMouseOut)
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
|
||
|
return (
|
||
|
<>
|
||
|
{props.children(setAnchor)}
|
||
|
<Show when={show()}>
|
||
|
<div ref={setPopper} class={styles.tooltip} role="tooltip">
|
||
|
{props.content}
|
||
|
<div class={styles.arrow} data-popper-arrow={true} />
|
||
|
</div>
|
||
|
</Show>
|
||
|
</>
|
||
|
)
|
||
|
}
|