import type { ReactNode, Ref } from "react"; import { cx } from "../../utils"; /** 꼬리가 판의 위에 붙는지 아래에 붙는지. 판이 트리거의 아래/위 어느 쪽에 뜨는지가 따라온다. */ export type FoxTooltipDirection = "top" | "bottom"; export interface FoxTooltipProps { /** * `top`이면 꼬리가 판 위에 붙는다 — 트리거 아래에 뜨는 말풍선이다. * `bottom`이면 꼬리가 판 아래에 붙는다 — 트리거 위에 뜨는 말풍선이다. * * 가로 위치를 고르는 값은 없다 — 시안이 꼬리를 언제나 가운데에 둔다(`FoxTooltipRich`와 * 다른 점이다). */ direction?: FoxTooltipDirection; /** 보여 줄 글자. 한 줄짜리 짧은 말이다 — 길어지면 `FoxTooltipRich`를 쓴다. */ message: ReactNode; /** 참이면 렌더하지 않는다(DOM에 남지 않는다). */ hidden?: boolean; id?: string; /** 배치 조정용. 트리거 옆에 놓는 위치를 여기로 준다. */ className?: string; ref?: Ref; } const DIRECTION_CLASS: Record = { top: "fox-tooltip--top", bottom: "fox-tooltip--bottom", }; /** * @fox 툴팁. 어두운 판에 짧은 글 한 줄을 담은 말풍선이다. * * `FoxTooltipRich`의 작은 형제다 — 제목이 없고, 꼬리가 언제나 가운데이며, 판이 글자만큼만 * 넓어진다. 여기도 **누를 것이 하나도 없다**: 잠깐 떴다 사라지는 판 안의 버튼은 누를 수 없다. * * **상태를 갖지 않고 스스로 자리를 잡지도 않는다.** 언제 보일지와 트리거 옆 어디에 놓을지는 * 호출부가 정하고, `direction`은 꼬리가 위아래 중 어디에 붙는지만 정한다. * * ⚠️ 이 조각은 보조기술에 아무 역할도 주지 않는다. 툴팁으로 읽히려면 트리거가 * `aria-describedby`로 이 요소의 `id`를 가리켜야 한다 — 그 배선은 트리거 쪽이 맡는다. * * ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"` * (또는 개별 파티셜)로 한 번 불러와야 한다. */ export function FoxTooltip({ direction = "top", message, hidden = false, id, className, ref, }: FoxTooltipProps) { if (hidden) { return null; } const arrowSlot = ( ); return (
{direction === "top" ? arrowSlot : null}
{message}
{direction === "bottom" ? arrowSlot : null}
); } /** * 시안 꼬리. 여기서는 `FoxPopover`·`FoxTooltipRich`처럼 CSS로 그리지 않고 SVG를 쓴다 — * 저쪽은 테두리가 있어 1px 이음새를 맞춰야 했지만 이 판은 테두리 없이 한 색이라 그럴 일이 * 없고, 시안의 꼬리 **끝이 살짝 둥글어** CSS 삼각형으로는 그 모양이 나오지 않는다. * * 색은 리터럴 대신 `currentColor`라 스타일이 판과 같은 값을 준다. 마스크가 없어 문서에서 * id가 겹칠 일도 없다. */ function ArrowMark() { return ( ); }