컴포넌트

Tooltip

요소에 대한 짧은 설명을 표시합니다.

모션

100ms 동안 작은 확대와 투명도 변화를 적용합니다. 움직임 감소 설정에서는 전환을 생략합니다. 공통 모션 규칙을 따릅니다.

설치

pnpm dlx ply-ui add tooltip

공통 설치 설정을 먼저 적용합니다.

사용법

Provider.delay로 표시 지연을 정하고 Positioner로 위치를 지정합니다.

필수 안내나 클릭해야 하는 콘텐츠는 Tooltip 대신 본문이나 Popover에 넣으세요.

구성

구성 요소역할
Provider여러 툴팁의 표시 지연을 설정합니다.
Root툴팁 하나의 상태를 관리합니다.
Trigger마우스 또는 키보드 포커스로 설명을 표시하는 대상입니다.
Portal / Positioner / Popup설명의 위치와 표면을 구성합니다.
Arrow대상 방향을 가리키는 표시입니다.

구현 코드

components/ui/tooltip.tsx
tooltip.tsx
"use client";

import type { ComponentProps } from "react";
import { Tooltip as Primitive } from "@base-ui/react/tooltip";
import { withClassName } from "../../lib/cx";
import "./tooltip.css";

// 동작과 접근성은 Base UI가 담당합니다. 이 파일은 스타일 연결만 담당합니다.
function TooltipTrigger({
  className,
  ...props
}: ComponentProps<typeof Primitive.Trigger>) {
  return (
    <Primitive.Trigger
      {...props}
      className={withClassName("rbx-button", className)}
    />
  );
}

function TooltipPopup({
  className,
  ...props
}: ComponentProps<typeof Primitive.Popup>) {
  return (
    <Primitive.Popup
      {...props}
      className={withClassName("rbx-tooltip", className)}
    />
  );
}

function TooltipPositioner({
  className,
  ...props
}: ComponentProps<typeof Primitive.Positioner>) {
  return (
    <Primitive.Positioner
      {...props}
      className={withClassName("rbx-positioner", className)}
    />
  );
}

function TooltipArrow({
  className,
  ...props
}: ComponentProps<typeof Primitive.Arrow>) {
  return (
    <Primitive.Arrow
      {...props}
      className={withClassName("rbx-popup-arrow", className)}
    />
  );
}

// Root/Portal 등 스타일 없는 파트와 제네릭 API는 원본을 그대로 보존합니다.
export const Tooltip = {
  ...Primitive,
  Trigger: TooltipTrigger,
  Popup: TooltipPopup,
  Positioner: TooltipPositioner,
  Arrow: TooltipArrow,
};
components/ui/tooltip.css
tooltip.css
@import "./button.css";
/* Tooltip: 공통 구조는 theme.css, 컴포넌트 전용 조정은 아래에 작성합니다. */
.rbx-tooltip {
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--rbx-color-content-emphasis);
  color: var(--rbx-color-surface-0);
  font-size: 0.875rem;
  box-shadow: 0 4px 16px var(--rbx-color-common-shadow);
  max-width: 280px;
}

.rbx-tooltip {
  transform-origin: var(--transform-origin);
  transition:
    opacity var(--rbx-motion-duration-feedback) var(--rbx-motion-ease-enter),
    scale var(--rbx-motion-duration-feedback) var(--rbx-motion-ease-enter);
}
.rbx-tooltip:is([data-starting-style], [data-ending-style]) {
  opacity: 0;
  scale: var(--rbx-motion-scale-overlay);
}
.rbx-tooltip[data-ending-style] {
  transition-timing-function: var(--rbx-motion-ease-exit);
}

목차