File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
08-14
08-14
08-18
08-18
08-18
08-14
08-19
08-18
08-18
08-18
08-18
08-18
File name
Commit message
Commit date
08-19
import type { ReactNode, Ref } from "react";
import { cx } from "../../utils";
/** 꼬리가 판의 위에 붙는지 아래에 붙는지. 판이 트리거의 아래/위 어느 쪽에 뜨는지가 따라온다. */
export type FoxTooltipRichDirection = "top" | "bottom";
/** 꼬리가 판의 가로 어디에 붙는지. */
export type FoxTooltipRichArrow = "left" | "center" | "right";
export interface FoxTooltipRichProps {
/**
* `top`이면 꼬리가 판 위에 붙는다 — 트리거 아래에 뜨는 말풍선이다.
* `bottom`이면 꼬리가 판 아래에 붙는다 — 트리거 위에 뜨는 말풍선이다.
*/
direction?: FoxTooltipRichDirection;
/** 꼬리의 가로 위치. 판 가장자리에서 24px 안쪽에 선다(가운데는 예외). */
arrow?: FoxTooltipRichArrow;
/** 굵은 제목 줄. 넘기지 않으면 렌더링하지 않는다. */
title?: ReactNode;
/**
* 본문. **150자 내외의 글자만 담는다**(시안 주석) — 버튼·링크 같은 누를 것을 넣지 않는다.
* 누를 것이 필요하면 툴팁이 아니라 `FoxPopover`다.
*/
message?: ReactNode;
/** 참이면 렌더하지 않는다(DOM에 남지 않는다). */
hidden?: boolean;
id?: string;
/** 배치 조정용. 트리거 옆에 놓는 위치와 시안의 폭(360px)을 여기로 덮는다. */
className?: string;
ref?: Ref<HTMLDivElement>;
}
const DIRECTION_CLASS: Record<FoxTooltipRichDirection, string> = {
top: "fox-tooltip-rich--top",
bottom: "fox-tooltip-rich--bottom",
};
const ARROW_CLASS: Record<FoxTooltipRichArrow, string> = {
left: "fox-tooltip-rich--arrow-left",
center: "fox-tooltip-rich--arrow-center",
right: "fox-tooltip-rich--arrow-right",
};
/**
* @fox 리치 툴팁. 제목과 본문을 담은 말풍선이다.
*
* `FoxPopover`와 판·꼬리의 구조가 같지만 **누를 것이 하나도 없다** — 닫기도 액션 버튼도
* 없고, 시안 주석대로 150자 내외의 글자만 담는다. 그래서 여닫는 것은 전적으로 트리거의
* 몫이다(가리키거나 포커스가 닿는 동안 보이는 식). 사용자가 눌러야 할 것이 생기면 그때는
* 툴팁이 아니라 팝오버다 — 잠깐 떴다 사라지는 판 안의 버튼은 누를 수 없다.
*
* 테두리도 그 차이를 따른다: 팝오버는 진한 선(`border-neutral-strong`)이고 이쪽은 한 단계
* 옅은 선(`border-neutral-default`)이다.
*
* **상태를 갖지 않고 스스로 자리를 잡지도 않는다.** 트리거 옆 어디에 놓을지는 `className`으로
* 주고, `direction`·`arrow`는 꼬리가 어디에 붙는지만 정한다.
*
* ⚠️ 이 조각은 보조기술에 아무 역할도 주지 않는다. 툴팁으로 읽히려면 트리거가
* `aria-describedby`로 이 요소의 `id`를 가리켜야 한다 — 그 배선은 트리거 쪽이 맡는다.
*
* ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"`
* (또는 개별 파티셜)로 한 번 불러와야 한다.
*/
export function FoxTooltipRich({
direction = "top",
arrow = "left",
title,
message,
hidden = false,
id,
className,
ref,
}: FoxTooltipRichProps) {
if (hidden) {
return null;
}
// 꼬리는 CSS가 그린다 — 이 요소는 자리만 잡는다(스타일 파일 참고).
const arrowSlot = (
<div className="fox-tooltip-rich__arrow-area" aria-hidden="true">
<span className="fox-tooltip-rich__arrow" />
</div>
);
return (
<div
ref={ref}
id={id}
className={cx(
"fox-tooltip-rich",
DIRECTION_CLASS[direction],
ARROW_CLASS[arrow],
className
)}
>
{direction === "top" ? arrowSlot : null}
<div className="fox-tooltip-rich__content">
{title === undefined && message === undefined ? null : (
<div className="fox-tooltip-rich__body">
{title === undefined ? null : (
<div className="fox-tooltip-rich__title-row">
<strong className="fox-tooltip-rich__title">{title}</strong>
</div>
)}
{message === undefined ? null : (
<div className="fox-tooltip-rich__message-row">
<span className="fox-tooltip-rich__message">{message}</span>
</div>
)}
</div>
)}
</div>
{direction === "bottom" ? arrowSlot : null}
</div>
);
}