Tooltip
Tooltip
특정 요소 위에 마우스를 올리거나 다른 이벤트가 발생했을 때 툴팁을 렌더링하는 컴포넌트예요.
출처: 문서
본문
사용법 (Usage)
import { Tooltip, Button } from '@mantine/core';
function Demo() {
return (
<Tooltip label="Button with tooltip">
<Button>Button</Button>
</Tooltip>
);
}
Tooltip children
Tooltip은 단일 자식으로 요소 또는 컴포넌트를 요구해요. 문자열, 프래그먼트, 숫자, 여러 개의 요소/컴포넌트는 지원되지 않으며 오류를 발생시켜요. 커스텀 컴포넌트는 루트 요소 ref를 얻을 수 있는 prop을 제공해야 해요. 모든 Mantine 컴포넌트는 기본적으로 ref를 지원해요.
import { Badge, Tooltip } from '@mantine/core';
function Demo() {
return (
<>
<Tooltip label="OK">
<button>Native button – ok</button>
</Tooltip>
<Tooltip label="OK">
<Badge>Mantine component – ok</Badge>
</Tooltip>
{/* Raw string, NOT OK – will throw an error */}
{/* <Tooltip label="Error">Raw string</Tooltip> */}
{/* Number, NOT OK – will throw an error */}
{/* {2} */}
{/* Fragment and multiple nodes NOT OK – will throw an error */}
</>
);
}
Tooltip target
target prop은 children의 대안이에요. 문자열(선택자), HTML 요소, 또는 HTML 요소가 있는 ref 객체를 받아요. 툴팁 대상을 JSX 요소로 렌더링하지 않을 때 target prop을 사용해요.
문자열 선택자와 함께 target prop을 사용하는 예시:
import { Button, Tooltip } from '@mantine/core';
function Demo() {
return (
<>
<Button id="target-1">Hover me to see tooltip</Button>
<Tooltip label="Tooltip" target="#target-1" />
</>
);
}
필수 ref prop (Required ref prop)
Tooltip 안에 렌더링되는 커스텀 컴포넌트는 ref prop을 지원해야 해요.
// 동작하지 않는 코드 예시
import { Tooltip } from '@mantine/core';
function MyComponent() {
return <div>My component</div>;
}
// MyComponent가 ref를 지원하지 않으므로 동작하지 않아요
// function Demo() {
// return (
// <Tooltip label="X">
// <MyComponent />
// </Tooltip>
// );
// }
컴포넌트는 ref prop을 지원해야 해요.
// 동작하는 코드 예시
import { Tooltip } from '@mantine/core';
const MyComponent = ({ ref, ...props }) => (
<div ref={ref} {...props}>My component</div>
);
// ref가 전달되므로 올바르게 동작해요
function Demo() {
return (
<Tooltip label="OK">
<MyComponent />
</Tooltip>
);
}
색상 (Color)
import { Tooltip, Button } from '@mantine/core';
function Demo() {
return (
<Tooltip label="With tooltip" color="red">
<Button>With tooltip</Button>
</Tooltip>
);
}
오프셋 (Offset)
offset prop을 숫자로 설정하면 대상 요소에 대한 툴팁 위치를 바꿀 수 있어요. 이 방법으로는 주축(main axis)에서만 툴팁 오프셋을 제어할 수 있어요.
import { Tooltip, Button } from '@mantine/core';
function Demo() {
return (
<Tooltip label="Button with tooltip" position="top" offset={20}>
<Button>Button with tooltip</Button>
</Tooltip>
);
}
두 축 모두에서 오프셋을 제어하려면 mainAxis와 crossAxis 속성을 가진 객체를 전달해요.
import { Tooltip, Button } from '@mantine/core';
function Demo() {
return (
<Tooltip label="Button with tooltip" offset={{ mainAxis: 12, crossAxis: 8 }}>
<Button>Button with tooltip</Button>
</Tooltip>
);
}
화살표 (Arrow)
withArrow prop을 설정하면 툴팁에 화살표를 추가할 수 있어요. 화살표는 transform: rotate(45deg)로 회전된 div 요소예요.
arrowPosition prop은 position이 Popover 컴포넌트에서 *-start·*-end 값으로 설정됐을 때 툴팁이 대상 요소에 대해 어떻게 위치하는지 결정해요. 기본값은 center로, 가능하면 화살표가 대상 요소의 중앙에 위치해요.
arrowPosition을 side로 바꾸면 화살표가 대상 요소의 측면에 위치하게 되고, arrowOffset prop으로 화살표 오프셋을 제어할 수 있어요. arrowPosition이 center일 때는 arrowOffset prop이 무시된다는 점에 주의해요.
arrowPosition을 merge로 설정하면 화살표가 툴팁의 해당 모서리와 합쳐진 직각삼각형을 이루고, 그 모서리의 테두리 반경은 제거돼요. 이 모드는 *-start·*-end 위치에서만 동작해요. arrowPosition이 merge일 때는 arrowOffset과 arrowRadius props가 무시된다는 점에 주의해요.
import { Tooltip, Button } from '@mantine/core';
function Demo() {
return (
<Tooltip label="Button with tooltip" withArrow arrowPosition="side" arrowOffset={8}>
<Button>Button with tooltip</Button>
</Tooltip>
);
}
제어 컴포넌트 (Controlled)
import { useState } from 'react';
import { Tooltip, Button } from '@mantine/core';
function Demo() {
const [opened, setOpened] = useState(true);
return (
<Tooltip label="Tooltip" opened={opened}>
<Button onClick={() => setOpened((o) => !o)}>Toggle color scheme</Button>
</Tooltip>
);
}
이벤트 변경 (Change events)
툴팁을 트리거하는 이벤트는 events prop으로 변경할 수 있어요. 툴팁을 트리거할 이벤트를 결정하는 다음 속성들이 있는 객체를 받아요.
hover– 마우스 호버 이벤트, 기본truefocus– 대상 요소 클릭을 제외한 focus/blur 이벤트, 기본falsetouch– 터치스크린 기기용 이벤트, 기본false
import { Tooltip } from '@mantine/core';
function Demo() {
return <Tooltip events={{ hover: true, focus: true, touch: true }} label="tooltip">target</Tooltip>;
}
상호작용형 툴팁 (Interactive tooltip)
기본적으로 툴팁은 포인터가 대상 요소를 벗어나자마자 닫히고, 툴팁 본문은 포인터 이벤트를 무시해요. interactive prop을 설정하면 포인터가 대상에서 툴팁으로 이동해 콘텐츠 위에 머무는 동안 툴팁을 열린 상태로 유지해요.
import { Button, Tooltip } from '@mantine/core';
function Demo() {
return (
<Tooltip label="Tooltip content" interactive>
<Button>Hover to read the tooltip</Button>
</Tooltip>
);
}
interactive prop은 WCAG 2.1 성공 기준 1.4.13: 호버 또는 포커스 시 콘텐츠의 호버 가능 조건을 충족하므로, 포인터가 툴팁 본문에 도달해 콘텐츠를 읽거나 선택할 수 있게 해요.
툴팁 안에는 상호작용형 또는 포커스 가능한 콘텐츠(링크, 버튼, 입력)를 넣지 마세요. 상호작용형 콘텐츠는 마우스, 키보드, 터치로 모두 접근 가능한 Popover에 넣어야 해요.
상호작용형 툴팁은 포인터 이벤트를 받는다는 점에 주의해요. 열려 있는 동안 툴팁이 겹치는 요소의 클릭과 호버 이벤트를 가로채요. 툴팁은 닫히기 시작하면 즉시 포인터 이벤트 수신을 중단해요. interactive prop은 항상 마우스를 따라가는 Tooltip.Floating에서는 지원되지 않아요.
여러 줄 (Multiline)
여러 줄 모드를 활성화하려면 multiline prop과 style prop인 w(너비)를 설정해요.
import { Tooltip, Button } from '@mantine/core';
function Demo() {
return (
<Tooltip multiline w={220} label="Multiline tooltip" withArrow>
<Button>Multiline tooltip</Button>
</Tooltip>
);
}
인라인 (Inline)
inline prop을 설정하면 인라인 요소와 함께 Tooltip을 사용할 수 있어요.
import { Tooltip, Mark, Text } from '@mantine/core';
function Demo() {
return (
<Text>
Stantler's magnificent antlers were traded at high prices as works of art.{' '}
<Tooltip inline label="When visiting a junkyard">
<Mark>When visiting a junkyard</Mark>
</Tooltip>
, you may catch sight of it having an intense fight with Murkrow over shiny objects.
</Text>
);
}
트랜지션 변경 (Change transition)
Tooltip은 Transition 컴포넌트로 만들어졌어요. transitionProps props를 지원해요.
import { Button, Tooltip } from '@mantine/core';
function Demo() {
return (
<Tooltip label="Button with tooltip" transitionProps={{ transition: 'pop', duration: 300 }}>
<Button>Button with tooltip</Button>
</Tooltip>
);
}
사용 가능한 모든 미리 만들어진 트랜지션: fade, fade-up, fade-down, fade-left, fade-right, scale, scale-y, scale-x, skew-up, skew-down, rotate-left, rotate-right, slide-down, slide-up, slide-left, slide-right, pop, pop-bottom-left, pop-bottom-right, pop-top-left, pop-top-right.
열림·닫힘 지연 (Close and open delay)
openDelay와 closeDelay props를 밀리초 단위로 설정해 툴팁 열기/닫기 이벤트를 지연시킬 수 있어요.
import { Button, Tooltip, Group } from '@mantine/core';
function Demo() {
return (
<Group>
<Tooltip label="Tooltip" openDelay={500}>
<Button>Delay open - 500ms</Button>
</Tooltip>
<Tooltip label="Tooltip" closeDelay={500}>
<Button>Delay close - 500ms</Button>
</Tooltip>
</Group>
);
}
Tooltip delay group
Tooltip.Group 컴포넌트는 여러 툴팁의 열기·닫기 지연을 동기화하는 데 사용할 수 있어요.
import { Tooltip, Button, Group } from '@mantine/core';
function Demo() {
return (
<Tooltip.Group openDelay={500} closeDelay={100}>
<Group>
<Tooltip label="Tooltip 1"><Button>Button 1</Button></Tooltip>
<Tooltip label="Tooltip 2"><Button>Button 2</Button></Tooltip>
<Tooltip label="Tooltip 3"><Button>Button 3</Button></Tooltip>
</Group>
</Tooltip.Group>
);
}
플로팅 툴팁 (Floating tooltip)
Tooltip.Floating 컴포넌트는 Tooltip 컴포넌트와 같은 API를 갖지만, 툴팁이 마우스를 따라가요.
import { Box, Tooltip } from '@mantine/core';
function Demo() {
return (
<Tooltip.Floating label="Hover over the box to see tooltip">
<Box>Hover over the box to see tooltip</Box>
</Tooltip.Floating>
);
}
접근성 (Accessibility)
Tooltip은 WAI-ARIA tooltip 패턴을 따르는 것을 목표로 해요.
- 툴팁 본문은
role="tooltip"속성을 가져요 - 대상 요소는
aria-describedby속성을 가져요 Tooltip.Floating은 화면 판독기에서 무시돼요- 비제어 툴팁은 포인터나 포커스를 움직이지 않고
Escape로 닫혀요
기본적으로 Tooltip은 포커스 이벤트에 의해 트리거되지 않으므로, 화면 판독기를 사용하거나 키보드로 내비게이션하는 사용자는 툴팁 콘텐츠를 얻지 못해요. events prop을 설정해 focus/blur 툴팁 이벤트를 활성화해요.
import { Button, Tooltip } from '@mantine/core';
// 화면 판독기에서 툴팁이 보이도록 함
function Demo() {
return (
<Tooltip label="Button with tooltip" events={{ hover: true, focus: true, touch: true }}>
<Button>Button with tooltip</Button>
</Tooltip>
);
}
WCAG 2.1 성공 기준 1.4.13: 호버 또는 포커스 시 콘텐츠는 호버 시 나타나는 콘텐츠가 닫을 수 있고(dismissable), 호버 가능하며(hoverable), 지속적(persistent)이어야 한다고 추가로 요구해요. Tooltip은 기본적으로 지속적이고, 열린 상태를 제어하지 않으면 닫을 수 있어요(Escape가 포인터를 움직이지 않고 닫음 – opened prop을 제어하려면 Escape 처리를 직접 해야 해요). Tooltip은 기본적으로 호버 가능하지 않아요. 툴팁 본문을 호버 가능하게 하려면 interactive prop을 설정해요.
import { Button, Tooltip } from '@mantine/core';
// 포인터가 콘텐츠 위에 있는 동안 툴팁이 열린 상태로 유지돼요
function Demo() {
return (
<Tooltip label="Button with tooltip" interactive>
<Button>Button with tooltip</Button>
</Tooltip>
);
}