Components
Tooltip
인터랙티브 요소의 보조 정보. Hover/focus/tap으로 표시.
Mobile
Tooltip은 모바일에서 사용하지 않는다 — 디자인 안티패턴이다. Hover/focus 트리거가 없는 환경에서 tooltip은 발견 가능성이 없는 숨겨진 정보가 된다. 사용자가 우연히 발견해야만 보이는 보조 정보는 정보가 없는 것과 같다.
모바일에서 같은 요구를 충족하려면 tooltip이 아닌 다른 패턴으로 재설계한다:
- Inline helper text —
caption1Regular text-stone-400을 컨트롤 아래/옆에 직접 노출. tooltip이 필요해지는 순간이 곧 inline 헬퍼가 필요한 순간이다 - Info icon
(i)→ Popover/BottomSheet — 길거나 부가적인 설명은 명시적 trigger로 변환. Popover Mobile 참조 accessibilityHint— 스크린 리더용 보조 설명. 시각적 노출과 별개로 a11y는 항상 적용
Long-press로 native tooltip을 띄우는 패턴은 발견 가능성이 낮아 일반 UI에 사용하지 않는다 (학습된 power user에게만 작동).
Preview
구조
TooltipProvider delayDuration (전역)
└─ Tooltip Root
├─ TooltipTrigger asChild — 트리거 요소 래핑
└─ TooltipContent Portal 내장 · sideOffset=4 · 다크 pillTooltipContent는 내부에 TooltipPrimitive.Portal을 포함하므로 호출부에서 Portal을 별도로 감쌀 필요 없음.
Token Mapping
| Token | Value | Description |
|---|---|---|
| bg | black (#000000) | 다크 표면 |
| text | white | inverse |
| typography | caption1Regular (12/16) · text-left | |
| radius | rounded-md (6px) | |
| padding | px-3 py-1.5 | |
| max-width | max-w-xs (320px) | 긴 내용 줄바꿈 |
| shadow | shadow-md | |
| sideOffset | 4px | trigger와의 간격 |
| z-index | z-50 |
Props
// TooltipContent
sideOffset?: number // 기본 4
side?: 'top' | 'right' | 'bottom' | 'left'
align?: 'start' | 'center' | 'end'
// TooltipProvider
delayDuration?: number // 기본 400msUsage
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
// TooltipContent는 Portal을 내장 — 별도 Portal 래퍼 불필요
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<button aria-label="즐겨찾기">
<StarIcon />
</button>
</TooltipTrigger>
<TooltipContent>
즐겨찾기에 추가
</TooltipContent>
</Tooltip>
</TooltipProvider>A11y
- Hover 전용 금지 — focus / tap으로도 접근 가능해야 함
- 모바일에서는 long-press 또는 explicit info icon 조합
TooltipTrigger에aria-label필수 (아이콘 버튼인 경우)
Do / Don't
- Do: 아이콘 버튼의 의미 보강, 단축키 안내에 사용
- Do:
asChild로 트리거 요소를 래핑해 DOM 중첩 방지 - Don't: 핵심 정보를 Tooltip 단독으로 전달 금지 (가려지면 사용자가 놓침)
- Don't: 한 화면에 동시 다중 Tooltip 열기 금지
