범용적으로 사용할 수있는 Tooltip 개발기를 공유하고자 한다.

툴팁을 개발할 때 hover 되면 툴팁이 나오도록 설계 했기 때문에 hover 여부를 파악하기 위해 useHover hooks 를 만들어 hover 여부를 판단하는 커스텀훅을 개발하였다.
// hooks/useHover.ts
import { useState, useRef, useEffect } from 'react';
export function useHover<T extends HTMLElement = HTMLElement>() {
const [isHover, setIsHover] = useState(false);
const ref = useRef<T | null>(null);
const handleMouseEnter = () => setIsHover(true);
const handleMouseLeave = () => setIsHover(false);
useEffect(() => {
const node = ref.current;
if (node) {
node.addEventListener('mouseenter', handleMouseEnter);
node.addEventListener('mouseleave', handleMouseLeave);
}
return () => {
if (node) {
node.removeEventListener('mouseenter', handleMouseEnter);
node.removeEventListener('mouseleave', handleMouseLeave);
}
};
}, []);
return { ref, isHover };
}
범용적으로 hover 여부를 처리하기 위해 제네릭을 통해 ref(DOM) 의 타입을 처리하였다.
hover 여부를 판단하기 위해 state 와 mouseenter, mouseleave 이벤트를 통해 dom 진입 및 벗어남을 감지하여 hover 활성화 여부를 파악했다.
// Tooltip.tsx
import { PropsWithChildren } from 'react';
import * as S from './Tooltip.styles.tsx';
import { theme } from '@/styles/theme.ts';
import { useHover } from '@/hooks/usHover.ts';
type TooltipProps = {
content: string;
placement?: 'top' | 'right' | 'bottom' | 'left';
color?: string;
};
export function Tooltip({
content,
placement = 'right',
color = theme.color.gray900,
children,
}: PropsWithChildren<TooltipProps>) {
const { ref: tooltipRef, isHover: isVisible } = useHover<HTMLDivElement>();
return (
<S.Tooltip ref={tooltipRef}>
{children}
{isVisible && (
<S.Content className={placement} style={{ backgroundColor: color }}>
{content}
</S.Content>
)}
</S.Tooltip>
);
}
import styled from '@emotion/styled';
import { theme } from '@/styles/theme.ts';
const { color } = theme;
export const Tooltip = styled.div`
position: relative;
display: inline-flex;
white-space: nowrap;
`;
export const Content = styled.div`
position: absolute;
z-index: 100;
min-height: 40px;
padding: 10px 12px;
font-size: 13px;
line-height: 1.3;
color: ${color.white};
border: 1px solid ${color.gray100};
border-radius: 8px;
box-shadow: 0 2px 8px rgb(0 0 0 / 10%);
margin: 0 10px;
&.top {
bottom: 100%;
left: 50%;
margin-bottom: 5px;
transform: translateX(-50%);
}
&.right {
top: 50%;
left: 100%;
margin-left: 12px;
transform: translateY(-50%);
}
&.bottom {
top: 100%;
left: 50%;
margin-top: 6px;
transform: translateX(-50%);
}
&.left {
top: 50%;
right: 100%;
margin-right: 12px;
transform: translateY(-50%);
}
`;
Tooltip 스타일을 기준으로 하기 위해 position 을 relative 로 정의하였다. Content 가 실제 Tooltip 의 내용으로 해당 위치(top, right...) 에 따라 스타일을 지정했다.hasArrow-> 시간 날 때 꼭하자!