Skip to Content

Tooltip

개요

Tooltip은 UI 요소에 마우스를 올렸을 때 짧은 설명을 표시하는 컴포넌트입니다. Cals에서는 예약 상태 설명, 아이콘 의미 설명, 버튼 기능 안내 등에 사용됩니다.

언제 사용하는가

  • 예약 상태 아이콘 설명
  • 버튼 기능 안내
  • 축약된 텍스트 전체 내용
  • 아이콘 의미 설명
  • 짧은 도움말 (1-2줄)

언제 사용하지 말아야 하는가

  • 긴 설명이나 복잡한 정보 → Popover 또는 Dialog 사용
  • 중요한 정보 → Alert 사용
  • 클릭 가능한 콘텐츠 → Popover 사용
  • 모바일에서 필수 정보 → 명시적으로 표시

설치

npx @vortex/cli add tooltip

기본 사용법

import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { Button } from "@/components/ui/button"; import { Info } from "lucide-react"; export default function TooltipDemo() { return ( <TooltipProvider> <Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon"> <Info className="h-4 w-4" /> </Button> </TooltipTrigger> <TooltipContent> <p>예약 상태 정보</p> </TooltipContent> </Tooltip> </TooltipProvider> ); }

Variants

Tooltip은 단일 스타일이지만, 용도에 따라 내용과 위치를 다르게 구성합니다.

Default Tooltip

기본 Tooltip입니다.

<Tooltip> <TooltipTrigger asChild> <Button variant="outline">마우스를 올리세요</Button> </TooltipTrigger> <TooltipContent> <p>기본 툴팁입니다</p> </TooltipContent> </Tooltip>

Icon Tooltip

아이콘 버튼에 대한 설명을 제공합니다.

<Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon"> <Calendar className="h-4 w-4" /> </Button> </TooltipTrigger> <TooltipContent> <p>달력 보기</p> </TooltipContent> </Tooltip>

Status Tooltip

상태 아이콘에 대한 설명을 제공합니다.

<Tooltip> <TooltipTrigger asChild> <Badge className="bg-blue-500">확정</Badge> </TooltipTrigger> <TooltipContent> <p>예약이 확정되었습니다</p> </TooltipContent> </Tooltip>

Multi-line Tooltip

여러 줄의 설명을 제공합니다.

<Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon"> <HelpCircle className="h-4 w-4" /> </Button> </TooltipTrigger> <TooltipContent className="max-w-xs"> <p>예약은 최소 24시간 전에 해주세요.</p> <p className="mt-1">당일 예약은 전화로 문의하세요.</p> </TooltipContent> </Tooltip>

Cals 브랜딩

브랜드 컬러

Cals의 Primary Pink를 활용한 브랜드 Tooltip 스타일입니다.

<Tooltip> <TooltipTrigger asChild> <Button className="bg-cals-primary hover:bg-cals-primary/90">Cals</Button> </TooltipTrigger> <TooltipContent className="bg-cals-primary text-white"> <p>Cals 예약 시스템</p> </TooltipContent> </Tooltip>

예약 상태 컬러

예약 상태별 Tooltip 스타일을 제공합니다.

<TooltipProvider> <div className="flex gap-2"> {/* Available - 예약 가능 */} <Tooltip> <TooltipTrigger asChild> <Badge className="bg-green-500 cursor-help">예약 가능</Badge> </TooltipTrigger> <TooltipContent className="bg-green-500 text-white"> <p>해당 시간대에 예약하실 수 있습니다</p> </TooltipContent> </Tooltip> {/* Pending - 승인 대기 */} <Tooltip> <TooltipTrigger asChild> <Badge className="bg-orange-500 cursor-help">승인 대기</Badge> </TooltipTrigger> <TooltipContent className="bg-orange-500 text-white"> <p>예약 승인을 기다리고 있습니다</p> </TooltipContent> </Tooltip> {/* Confirmed - 예약 확정 */} <Tooltip> <TooltipTrigger asChild> <Badge className="bg-blue-500 cursor-help">예약 확정</Badge> </TooltipTrigger> <TooltipContent className="bg-blue-500 text-white"> <p>예약이 확정되었습니다</p> </TooltipContent> </Tooltip> {/* Cancelled - 예약 취소 */} <Tooltip> <TooltipTrigger asChild> <Badge className="bg-red-500 cursor-help">예약 취소</Badge> </TooltipTrigger> <TooltipContent className="bg-red-500 text-white"> <p>예약이 취소되었습니다</p> </TooltipContent> </Tooltip> {/* Completed - 예약 완료 */} <Tooltip> <TooltipTrigger asChild> <Badge className="bg-purple-500 cursor-help">서비스 완료</Badge> </TooltipTrigger> <TooltipContent className="bg-purple-500 text-white"> <p>서비스가 완료되었습니다</p> </TooltipContent> </Tooltip> </div> </TooltipProvider>

브랜드 비교표

속성FoundationiCignalCals
Primary ColorNeutral GrayCorporate Blue #0066ccPrimary Pink #e91e63
Use Case범용 도움말기업 UI 가이드예약 상태 설명
ContentShort (1 line)Medium (2-3 lines)Short with Status
BackgroundDark GrayCorporate BlueStatus Color
Delay700ms500ms (빠른 피드백)700ms
ArrowYesYesYes

Props API

TooltipProvider

PropTypeDefaultDescription
delayDurationnumber700Tooltip 표시 지연 시간 (ms)
skipDelayDurationnumber300연속 표시 시 지연 시간 (ms)
disableHoverableContentbooleanfalseTooltip 콘텐츠 호버 비활성화

Tooltip

PropTypeDefaultDescription
openboolean-Tooltip 열림 상태 (controlled)
onOpenChange(open: boolean) => void-열림 상태 변경 핸들러
defaultOpenbooleanfalse초기 열림 상태 (uncontrolled)
delayDurationnumber-Provider 설정 오버라이드

TooltipTrigger

PropTypeDefaultDescription
asChildbooleanfalse자식 요소를 트리거로 사용

TooltipContent

PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""top"표시 위치
align"start" | "center" | "end""center"정렬 위치
sideOffsetnumber4트리거와의 간격 (px)
classNamestring-커스텀 CSS 클래스

접근성

  • Role: role="tooltip" 자동 적용
  • ARIA: aria-describedby 자동 연결
  • Keyboard: 키보드 포커스 시에도 표시
  • ESC Key: ESC 키로 닫기
  • Screen Reader: 스크린 리더가 자동으로 읽음
  • Focus: Tooltip 자체는 포커스를 받지 않음
  • Mobile: 터치 시에는 표시되지 않음 (접근성 고려 필요)

예제

예약 상태 아이콘

import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { Badge } from "@/components/ui/badge"; import { CheckCircle2, Clock, XCircle, Calendar, AlertCircle, } from "lucide-react"; export default function ReservationStatusTooltips() { return ( <TooltipProvider> <div className="flex gap-3"> {/* Available */} <Tooltip> <TooltipTrigger asChild> <button className="p-2 rounded-lg hover:bg-green-50"> <Calendar className="h-5 w-5 text-green-500" /> </button> </TooltipTrigger> <TooltipContent className="bg-green-500 text-white"> <p>예약 가능</p> </TooltipContent> </Tooltip> {/* Pending */} <Tooltip> <TooltipTrigger asChild> <button className="p-2 rounded-lg hover:bg-orange-50"> <Clock className="h-5 w-5 text-orange-500" /> </button> </TooltipTrigger> <TooltipContent className="bg-orange-500 text-white"> <p>승인 대기 중</p> </TooltipContent> </Tooltip> {/* Confirmed */} <Tooltip> <TooltipTrigger asChild> <button className="p-2 rounded-lg hover:bg-blue-50"> <CheckCircle2 className="h-5 w-5 text-blue-500" /> </button> </TooltipTrigger> <TooltipContent className="bg-blue-500 text-white"> <p>예약 확정</p> </TooltipContent> </Tooltip> {/* Cancelled */} <Tooltip> <TooltipTrigger asChild> <button className="p-2 rounded-lg hover:bg-red-50"> <XCircle className="h-5 w-5 text-red-500" /> </button> </TooltipTrigger> <TooltipContent className="bg-red-500 text-white"> <p>예약 취소</p> </TooltipContent> </Tooltip> {/* Completed */} <Tooltip> <TooltipTrigger asChild> <button className="p-2 rounded-lg hover:bg-purple-50"> <CheckCircle2 className="h-5 w-5 text-purple-500" /> </button> </TooltipTrigger> <TooltipContent className="bg-purple-500 text-white"> <p>서비스 완료</p> </TooltipContent> </Tooltip> </div> </TooltipProvider> ); }

액션 버튼 가이드

import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { Button } from "@/components/ui/button"; import { Edit, Trash2, Copy, Download, Share2 } from "lucide-react"; export default function ActionButtonTooltips() { return ( <TooltipProvider> <div className="flex gap-2"> <Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon"> <Edit className="h-4 w-4" /> </Button> </TooltipTrigger> <TooltipContent> <p>예약 수정</p> </TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon"> <Copy className="h-4 w-4" /> </Button> </TooltipTrigger> <TooltipContent> <p>예약 복제</p> </TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon"> <Download className="h-4 w-4" /> </Button> </TooltipTrigger> <TooltipContent> <p>예약 내역 다운로드</p> </TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon"> <Share2 className="h-4 w-4" /> </Button> </TooltipTrigger> <TooltipContent> <p>예약 정보 공유</p> </TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon"> <Trash2 className="h-4 w-4 text-red-500" /> </Button> </TooltipTrigger> <TooltipContent className="bg-red-500 text-white"> <p>예약 삭제</p> </TooltipContent> </Tooltip> </div> </TooltipProvider> ); }

예약 캘린더 시간대

import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { Button } from "@/components/ui/button"; export default function CalendarTimeSlots() { const timeSlots = [ { time: "09:00", status: "available", label: "예약 가능" }, { time: "10:00", status: "confirmed", label: "홍길동 - 컨설팅" }, { time: "11:00", status: "available", label: "예약 가능" }, { time: "14:00", status: "pending", label: "김철수 - 승인 대기" }, { time: "15:00", status: "confirmed", label: "이영희 - 미팅" }, { time: "16:00", status: "cancelled", label: "예약 취소됨" }, ]; const getStatusColor = (status: string) => { switch (status) { case "available": return "bg-green-100 text-green-700 hover:bg-green-200"; case "confirmed": return "bg-blue-100 text-blue-700 hover:bg-blue-200"; case "pending": return "bg-orange-100 text-orange-700 hover:bg-orange-200"; case "cancelled": return "bg-red-100 text-red-700 hover:bg-red-200"; default: return "bg-gray-100 text-gray-700 hover:bg-gray-200"; } }; const getTooltipColor = (status: string) => { switch (status) { case "available": return "bg-green-500 text-white"; case "confirmed": return "bg-blue-500 text-white"; case "pending": return "bg-orange-500 text-white"; case "cancelled": return "bg-red-500 text-white"; default: return ""; } }; return ( <TooltipProvider> <div className="grid grid-cols-3 gap-2"> {timeSlots.map((slot) => ( <Tooltip key={slot.time}> <TooltipTrigger asChild> <Button variant="outline" className={`${getStatusColor(slot.status)} border-none`} > {slot.time} </Button> </TooltipTrigger> <TooltipContent className={getTooltipColor(slot.status)}> <p>{slot.label}</p> </TooltipContent> </Tooltip> ))} </div> </TooltipProvider> ); }

다중 줄 Tooltip

import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { Button } from "@/components/ui/button"; import { HelpCircle } from "lucide-react"; export default function MultiLineTooltip() { return ( <TooltipProvider> <div className="flex items-center gap-2"> <span className="text-sm font-medium">예약 정책</span> <Tooltip> <TooltipTrigger asChild> <Button variant="ghost" size="icon" className="h-5 w-5"> <HelpCircle className="h-4 w-4 text-muted-foreground" /> </Button> </TooltipTrigger> <TooltipContent className="max-w-xs"> <div className="space-y-1"> <p className="font-semibold">예약 정책 안내</p> <p className="text-xs">• 최소 24시간 전 예약 필수</p> <p className="text-xs">• 당일 예약은 전화 문의</p> <p className="text-xs">• 취소 시 수수료 부과될 수 있음</p> </div> </TooltipContent> </Tooltip> </div> </TooltipProvider> ); }

관련 컴포넌트

  • Popover - 긴 설명 또는 인터랙티브 콘텐츠
  • Dialog - 상세 정보 또는 폼
  • Alert - 중요한 정보
  • Badge - 상태 라벨 표시
Last updated on