Intro
μλ νμΈμ. μ΄λ²μκ°μλ 리μ‘νΈμμ ν΄νμ ꡬννλ λ°©λ², ν΄ν μΈλΆ μμ ν΄λ¦ μ ν΄νμ μ¨κΈ°λ λ°©λ²μ λν΄ μμλ³΄κ² μ΅λλ€.
Let's look at detail
μλμ κ°μ λΆλͺ¨ μ»΄ν¬λνΈκ° μλ€κ³ κ°μ ν΄λ΄ μλ€. 3κ°μ ν΄ν μ»΄ν¬λνΈκ° μκ³ , ν΄ν μ»΄ν¬λνΈμλ κ°κΈ° λ€λ₯Έ ν΄ν μ€λͺ μ propsλ‘ μ λ¬νκ³ μμ΅λλ€.
const SomeComponent: NextPage<Props> = props => {
return (
<article>
<dl>
<dt>
λ΄μ€
<Tooltip desc={'λ΄μ€ κ΄λ ¨ ν΄νμ
λλ€.'} />
</dt>
<dt>
μΌν
<Tooltip desc={'μΌν κ΄λ ¨ ν΄νμ
λλ€.'} />
</dt>
<dt>
μ§λ
<Tooltip desc={'μ§λ κ΄λ ¨ ν΄νμ
λλ€. '} />
</dt>
</dl>
</article>
);
}
export default SomeComponent;
ν΄ν μ»΄ν¬λνΈλ μλμ κ°μ΅λλ€. νμ§λ§ νμ¬ κ΅¬νλμ΄ μλ ν΄ν μ»΄ν¬λνΈλ λ¬Έμ κ° μμμ΅λλ€, μ νλ ν΄νμ΄ μμ λ λ€λ₯Έ ν΄νμ΄ μ νλμ΄λ, λμμ ν΄ν descκ° νμΆλ©λλ€. λν μΈλΆ μμμ ν΄λ¦ ν λ μ¬μ ν ν΄νμ΄ λ¨μ μμμ΅λλ€.
const Tooltip: NextPage<Props> = props => {
const [tooltip, setTooltip] = useState(false),
tooltipRef: any = useRef<HTMLDivElement>(null),
[offsetTop, setOffsetTop] = useState(0);
useEffect(() => {
const tooltipOffsetTop = tooltipRef?.current?.offsetTop + 30;
setOffsetTop(tooltipOffsetTop);
}, []);
return (
<span className={styles.tooltip} ref={tooltipRef}>
<button type="button" className={tooltip ? styles.active : ''} onClick={() => setTooltip(!tooltip)}>
βοΈ
</button>
{tooltip && (
<div style={{top: offsetTop}} onClick={() => setTooltip(false)}>
{props.desc}
</div>
)}
</span>
);
};
export default Tooltip;
How to solve the problem
ν΄λΉ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ μ λ handleOutsideClick μ΄λΌλ ν¨μλ₯Ό λ§λ€μμ΅λλ€. μ΄ ν¨μλ mousedown μ΄λ²€νΈλ₯Ό μμ νκ³ , μ νλ ν΄ν μμ μΈλΆλ₯Ό ν΄λ¦ν λ μ νλ ν΄νμ ν΄μ νλ μν μ ν©λλ€.
λν useEffect hooksλ₯Ό μ¬μ©νμ¬ μ»΄ν¬λνΈκ° mountλκ±°λ, tooltipRefκ°μ΄ λ³κ²½λ λλ§λ€ on / off κ° λ©λλ€. λ°λΌμ ν΄λΉ μ½λλ₯Ό ν΅ν΄ μ νλ ν΄νμ΄ μμ λ λ€λ₯Έ ν΄νμ μ ν μ μ νλ ν΄νμΌλ‘ ν΄μ λλ ν¨κ³Όλ₯Ό μ»μ μ μμ΅λλ€.
const Tooltip: NextPage<Props> = props => {
const [tooltip, setTooltip] = useState(false),
tooltipRef: any = useRef<HTMLDivElement>(null),
[offsetTop, setOffsetTop] = useState(0);
const toggleTooltip = () => {
setTooltip(!tooltip);
};
useEffect(() => {
const tooltipOffsetTop = tooltipRef?.current?.offsetTop + 30;
setOffsetTop(tooltipOffsetTop);
}, []);
useEffect(() => {
const handleOutsideClick = (event: MouseEvent) => {
if (tooltipRef.current && !tooltipRef.current.contains(event.target as Node)) {
setTooltip(false);
}
};
document.addEventListener('mousedown', handleOutsideClick);
return () => {
document.removeEventListener('mousedown', handleOutsideClick);
};
}, [tooltipRef]);
return (
<span className={styles.tooltip} ref={tooltipRef}>
<button type="button" className={tooltip ? styles.active : ''} onClick={toggleTooltip}>
βοΈ
</button>
{tooltip && (
<div style={{top: offsetTop}}>
{props.description}
</div>
)}
</span>
);
};
export default Tooltip;
https://developer.mozilla.org/en-US/docs/Web/API/Element/mousedown_event