툴팁 (Tooltip)
툴팁의 종류·placement·색 톤과 위치 안내 툴팁을 확인하고, 사용 기준과 호출 방법을 찾아보세요.
JS + CSS · Web · 진행 중(WIP) · 문서 포맷 시범 적용
Interactive playground
setupTooltip() 이 처리하는 실제 경로예요. 종류는 라벨의 줄바꿈 하나로 갈립니다 — `title` 에 개행이 있으면 멀티라인 버블이 되고, 셀렉터나 별도 속성은 필요 없어요. 색 톤은 종류·placement 와 직교하는 축이라 어떤 조합과도 겹칠 수 있습니다. <button class="ds-btn ds-btn--line ds-btn--dark ds-btn--sm"
data-ds-tip="top"
title="삭제">
급여대장 반영
</button> 마지막 표시: —— 각 대상에 마우스를 올려 보세요 (툴팁은 실제 .ds-tooltip). 아래 줄은 실제 setupTooltip()이 처리하므로 이 표시기가 갱신되지 않습니다
select)이고, 2번째는 data-ds-tip 으로 placement 를 지정한 경우, 3번째는 opt-in 이 하나도 없는 평범한 요소에 여러 줄 title 만 준 경우, 4번째 줄은 줄 전체에 data-ds-tip-tone="light" 를 한 번 걸어 둔 밝은 톤입니다. right placement 는 접힌 LNB 메뉴 셀렉터 전용이라 여기서만 볼 수 있어요. 종류(한 줄 · 멀티라인) · placement · 색 톤을 골라 대상에 마우스를 올리면, 앱과 같은 싱글톤 setupTooltip() 이 처리하는 실제 툴팁이 뜹니다. 네 줄짜리 전체 데모는 「모아보기」 탭에 있습니다.
⚠️ docs 환경 차이: 툴팁은
position: fixedbody-level 요소라 위 영역 밖(뷰포트 기준)에 뜰 수 있습니다 — 실제 앱과 동일한 동작이며, 데모 카드 안에 가두려면positionoverride(강제)가 필요해 일부러 하지 않았습니다.
규칙 (강제) · 코딩 에이전트용
싱글톤 hover 툴팁의 강제 규칙. 상세·placement·토큰은 아래 본문.
- 종류는 2가지뿐이다 — 한 줄(기본) · 멀티라인 상세 도움말. 판정 기준은 라벨의 줄바꿈 하나이며
tooltip.ts가 자동으로 한다. 세 번째 종류를 만들지 말 것(새 클래스·새 버블 스타일 금지). 아래 색 톤은 종류가 아니라 직교 축이다 — 톤을 늘리는 것도 금지(값은light하나). - 색 톤은 2가지, 켜는 법은
data-ds-tip-tone="light"하나다 — 기본은 어두운 알약이고, 대상 또는 그 조상에 이 속성이 있으면 밝은 버블(.ds-tooltip--light)로 바뀐다(밝은 배경 +--color-label-alternative글자 + 1px 라인). 어떤 종류·어떤 placement와도 조합된다..ds-tooltip--light를 마크업에 직접 붙이지 말 것(싱글톤 요소는tooltip.ts가 매 표시마다 다시 판정한다). 밝은 톤이 필요하다고 툴팁을 손으로 만들지 말 것. - 멀티라인은 어디에나 쓸 수 있다 —
title에 줄바꿈(\n)만 있으면 버튼·표 셀·배지·구간 제목 등 셀렉터에 없는 요소도 자동 대상이 된다.data-ds-tip은 placement를 바꿀 때만 쓴다(기본top). 줄바꿈이 곧 opt-in이다. - 한 줄 툴팁은 반대다 — 아래 자동 셀렉터에 걸리거나
data-ds-tip으로 opt-in한 대상에서만 뜬다. 한 줄title을 아무 요소에나 달아도 DS 툴팁이 되지는 않는다(브라우저 기본 툴팁 그대로). setupTooltip()을 앱 시작 시 한 번 호출. body에 싱글톤.ds-tooltip1개가 이벤트 위임으로 모든(동적 포함) 대상의 hover를 처리 — 툴팁 요소를 직접 만들지 말 것(재호출은 no-op).- 4 placement:
right(접힌 LNB 메뉴) ·top(.icon-btn·.ds-btn--icon·표 액션·잘린 라벨·[data-ds-tip='top'], 대상 위·아래 화살표) ·compact(select/.ms-dropdown__trigger현재 선택값, 좌측정렬·화살표 없음) ·compact-center([data-ds-tip='compact-center']전용 — compact 버블을 트리거 중앙 정렬 + 아래 화살표). top·compact·compact-center 모두 상단 공간 부족 시 아래로 flip. - 자동 대상:
.icon-btn·.ds-btn--icon·select·.ms-dropdown__trigger등 위 셀렉터는 마크업 변경 없이 자동. opt-in은data-ds-tip="top|compact|compact-center"+title. <select>의 예외: title 에 줄바꿈이 있으면 compact(현재 선택값) 대신 상세 도움말(multiline) 로 뜬다 — 「줄바꿈 title 은 어떤 요소든 상세 툴팁」 규칙이 자동 compact 보다 앞선다(역할 편집 매트릭스의 권한 설명). 한 줄 title 이나 title 없음은 종전대로 compact.- 띄우는 방식(트리거)은 기본 hover, 예외로 클릭 하나 — 내용이 길어 hover 로 뜨면 옆 조작(체크박스 등)을 가리는 도움말은
data-ds-tip-trigger="click"을 단 작은?버튼에만 건다. hover 로는 뜨지 않고 클릭할 때만 뜨며, 버튼을 벗어나면 닫힌다(같은 버튼을 다시 눌러도 닫힘). 트리거는 종류 · 톤 · placement 와 직교하는 축이라 새 버블이 아니다 — 보통data-ds-tip="compact"(좌측 정렬 · 화살표 없음) +data-ds-tip-tone="light"+ 여러 줄title과 함께 쓴다. 값은click하나뿐이다. 사용처: admin 역할 추가 · 수정의 기능 묶음?. - title 보존: hover 시 네이티브
title을aria-label/data-tip-title로 이관(브라우저 기본 툴팁 방지) → leave 시 복원. 별도 처리 불필요. - 잘린 라벨 대상(
.role-card__pill등)은 실제 말줄임 됐을 때만(scrollWidth > clientWidth) 표시. - 멀티라인 상세 도움말:
title에 줄바꿈(\n)이 포함되면tooltip.ts가.ds-tooltip--multiline을 자동 부여 —pre-line+max-width: min(320px, 100vw-32px)+ 좌측 정렬. 클래스를 수동으로 붙이지 말 것(자동 판정이 정본). - 가로 위치는 자동 보정된다: 중앙 정렬 버블(
top·compact-center)이 화면 밖으로 나가면 뷰포트 안으로 되돌리고 화살표만 대상 쪽에 남긴다(clampTooltipX+--ds-tip-arrow-x). 화면 가장자리 버튼이라고 멀티라인을 피할 필요 없다 — 다만--ds-tip-arrow-x를 CSS에서 임의로 덮어쓰지 말 것. - 색은
--ds-tip-bg/--ds-tip-fg두 변수로만 읽는다 — 버블 배경과 4개 placement의 화살표가 같은 변수를 본다. 톤을 손보려면 이 변수만 덮을 것이고, placement 규칙에 색을 다시 적지 말 것(화살표 3곳이 조용히 어긋난다). .ds-tooltip의width: max-content를 지우지 말 것:width:auto로 되돌리면 fixed 요소의 shrink-to-fit이 자기left기준 잔여 공간으로 계산돼, 오른쪽 끝 버블이 스스로 좁아지며 세로로 길어진다(2026-07-27 재현·수정).- 색은 토큰(
--color-neutral-900/--ds-bw-white), 그림자만 하드코딩 유지(매칭 토큰 없음 — 결정). 툴팁 룩은.ds-tooltip= DS 소유(마크업 변경 불필요). - 위치 안내 툴팁은 별개 케이스다 — AI 어시스턴트 「기능 바로가기」가 대상 옆에 띄우는 닫기형 툴팁(
.ds-guidance-hint+ 강조선.ds-guidance-outline)은 위 싱글톤 hover 툴팁의 세 번째 종류가 아니다.createGuidanceHighlight()(packages/components/src/guidance/)만 만든다 — 마크업을 손으로 쓰지 말 것. 기본 색은 배경--color-purple-500· 글자--ds-bw-white· 강조선--color-purple-400, 닫기는 아이콘 버튼ds-btn--icon ds-btn--white ds-btn--xs+ic-close. 색 변형은.ds-guidance--<이름>이--ds-guidance-bg/--ds-guidance-fg/--ds-guidance-line세 변수만 덮어 추가한다(placement 규칙에 색 재선언 금지). 강조선은 화면·열린 AI 도크 가장자리에서 잘리지 않도록 JS 가 상자를 화면 안으로 줄인다. → 위치 안내 툴팁 - 자매 유틸
positionFloatingMenu(trigger, menu)— ms-dropdown 등 떠 있는 메뉴를 모달 안에서 아래 공간 부족 시 위로 flip(툴팁 아님). - 다크 모드(2026-10-13) — 도움말 배지
.ds-help-badge테두리line-strong· 글자label-muted, hover 면bg-inverse(라이트 neutral-900 · 다크 neutral-50 — 반전 면이라 다크에서 밝아진다). 툴팁 버블은--ds-tip-bg/--ds-tip-fg=bg-inverse/label-inverse라 같은 방식으로 반전된다. 확인: Playground 「미리보기 테마 → 다크」.
진행 중 (Tooltip — work in progress)
- 툴팁의 종류는 2가지다 — 한 줄(기본,
nowrap검은 알약)과 멀티라인 상세 도움말(title에 줄바꿈이 있으면 자동). 아래 placement는 어디에 뜨는가를 정하는 별개의 축이고, 어떤 종류인가는 오직 라벨에 줄바꿈이 있느냐로 갈린다. - 멀티라인은 대상 제한이 없다 — 버튼·표 셀·배지·구간 제목 등 아무 요소에나 여러 줄
title만 주면 뜬다(data-ds-tip불필요). 한 줄 툴팁만 아래 셀렉터 목록에 걸린 대상으로 제한된다. - 싱글톤 hover 툴팁.
setupTooltip()을 앱 시작 시 한 번 호출하면, body-level 단일 요소(.ds-tooltip)가 이벤트 위임으로 모든(동적 포함) 대상의 hover를 처리. - 4가지 placement: right(접힌 LNB 메뉴) · top(아이콘 버튼·잘린 라벨·멀티라인 기본값) · compact(
<select>/ms-dropdown현재 선택값) · compact-center(?도움말 배지 등 작은 트리거 — 가운데 정렬). - top·compact·compact-center는 상단 공간 부족 시 아래로 flip(collision flip) — 대상 아래에 뜨고 화살표가 위를 가리킴. compact=PR #247, top=
design/adjust-table(짧은 임베드 iframe 상단의 아이콘 버튼 등에서 잘리던 문제 해결). - 가로도 보정한다(2026-07-27) — 화면 좌·우 끝에서는 버블을 안으로 되돌리고 화살표만 대상 위에 남긴다.
- 색 톤은 2가지(2026-07-27) — 기본 어두운 알약과 밝은 버블(
data-ds-tip-tone="light"). 톤은 종류(한 줄/멀티라인)·placement와 직교하는 축이며, 세 번째 종류가 아니다. → 색 톤 - ✅ 색은 토큰화 완료(
--color-neutral-900/--ds-bw-white, 시각 변화 0). 그림자만 하드코딩 유지(매칭 토큰 없어 결정상 보류) — 검토 필요 사항 참고.
동작 원리
- 싱글톤:
setupTooltip()최초 호출 시installed플래그 설정 → 재호출 no-op. body에.ds-tooltip1개만 생성. - 이벤트 위임:
document에pointerover(capture)·pointerleave·click리스너. 동적으로 추가된 노드도 자동 커버. - 위치: 대상의
getBoundingClientRect()기준position: fixed로 배치 → 어떤 overflow도 뚫고 표시(z-index 최대). - title 보존: hover 시 네이티브
title을 제거(브라우저 기본 툴팁 방지)하고data-tip-title/aria-label로 옮김 → leave 시 복원. - 대상 판정 순서: 접힌 LNB →
compact-center→compact→top→ 잘린 라벨 → 멀티라인 fallback([title]·[data-tip-title]중 줄바꿈 있는 것). 명시적으로 opt-in한 placement가 항상 먼저 이기고, 아무것도 안 걸린 요소만 마지막 규칙으로 내려온다. - fallback이
[data-tip-title]까지 보는 이유: 툴팁이 뜨는 동안 대상의title은 제거돼 있다.[title]만 보면 hover 중 재판정에서 대상이 사라져 show → hide → title 복원 → show 로 깜빡인다(구현 시 실제로 밟은 함정). - flip·화살표 초기화: 싱글톤 요소 1개를 재사용하므로
show()마다data-flip과--ds-tip-arrow-x를 먼저 지운 뒤 위치를 다시 계산 → 직전 대상에서 flip·가로보정됐던 잔재(뒤집힌 화살표·어긋난 화살표 위치)가 다음 툴팁으로 새지 않음.
호출 패턴
import { setupTooltip } from "@hereby/components";
// 앱 시작 시 한 번 (Alpine.start() 이후도 OK — 이벤트 위임이라 동적 노드 커버)
setupTooltip();→ 이후 마크업 변경 없이, 위 셀렉터에 맞는 요소는 자동으로 툴팁이 붙음. opt-in이 필요하면 data-ds-tip="compact"(또는 "top") + title 부여.
사용처
- admin — 표 액션 아이콘(
.icon-btn), 조직 트리 액션, 접힌 LNB 메뉴, 모든<select>/ms-dropdown - team-manager 등 공유 앱 — 동일 (
setupTooltip()한 번 호출로 전역 적용) setupTooltip()호출 앱 — admin · team-manager · hr-system · general-affairs · management-dashboard · landing- 멀티라인(개행 title) — admin 근무 유형 모달 ⓘ 2개 · hr-system 시트 「열 설정」
?배지 · hr-system 시트 수식 힌트ƒ(멀티라인 상세 도움말 표). 범위 확장 이후로는 여러 줄title을 새로 다는 곳이 곧 사용처라 이 목록은 스냅샷이다
Placement & 대상
| placement | 대상 셀렉터 | 위치 | 비고 |
|---|---|---|---|
| right | .ds-lnb--collapsed .ds-lnb__menu | LNB 우측, 좌측 화살표 | 접힌 사이드바 메뉴 라벨 |
| top | .icon-btn, .ds-btn--icon, .org-tree__action-btn, [data-ds-tip='top'] | 대상 위, 아래 화살표. 상단 부족 시 아래로 flip(data-flip="down", 화살표가 위 가리킴) | 표 액션 아이콘 등 |
| top (truncate) | .role-card__group-label, .role-card__pill, .cell-trunc-tip | 대상 위 | 실제로 말줄임 됐을 때만 (scrollWidth > clientWidth) |
| compact | select, .ms-dropdown__trigger, [data-ds-tip='compact'] | 대상 좌측 정렬·위, 화살표 없음 | 현재 선택된 옵션/라벨 텍스트 자동 표시. 상단 부족 시 아래 flip |
| compact-center | [data-ds-tip='compact-center'] | 대상 가운데 정렬·위, 아래 화살표 | compact와 같은 작은 버블이지만 중앙 정렬 — ? 도움말 배지처럼 좁은 트리거용(좌측 정렬이면 어긋나 보임). 상단 부족 시 아래 flip |
| top (멀티라인 자동) | [title] 중 줄바꿈이 있는 것 — 셀렉터 무관 | top과 동일 | 위 셀렉터에 하나도 안 걸린 요소(버튼·셀·제목…)의 상세 도움말. 다른 규칙이 먼저 매칭되면 그쪽 placement가 이긴다 |
가로 방향 충돌 처리 — 중앙 정렬(
top·compact-center) 버블은 뷰포트를 벗어나면 안쪽으로 밀고(양옆 8px 여백), 화살표만 대상 위에 남긴다(--ds-tip-arrow-x). 계산은 순수 함수clampTooltipX()에 분리돼 있어 단위 테스트로 고정돼 있다. 좌측 정렬compact도 같은 방식으로 되돌린다(clampTooltipLeft()).
멀티라인 상세 도움말 (자동)
title 속성에 줄바꿈(\n)이 포함된 대상은 show() 시점에 .ds-tooltip--multiline이 자동 토글된다 — white-space: pre-line + max-width: 320px + text-align: left. 설정 화면의 ⓘ 도움말 아이콘처럼 여러 줄 설명이 필요한 곳에서 data-ds-tip="top" + 여러 줄 title만 주면 된다(HTML 속성 안의 실제 줄바꿈은 보존된다). 한 줄 라벨로 돌아오면 클래스도 자동 해제되므로 수동 관리 금지.
발동 조건은 하나다 — 평가된 title 문자열에 실제 개행이 있을 것. 셀렉터도 data-ds-tip도 필요 없다(2026-07-27 범위 확장). 버튼, 표 셀, 배지, 구간 제목, <div role="button"> 무엇이든 여러 줄 title만 주면 상세 도움말 버블이 뜬다.
<!-- 이게 전부다. opt-in 속성 없음 -->
<button class="ds-btn ds-btn--line ds-btn--dark ds-btn--sm"
title="이 시트의 반영 대상 열에서 수당·공제 레코드를 만듭니다. 마지막 반영 이후 바뀐 내용이 없으면 버튼이 비활성화돼요.">
급여대장 반영
</button>- placement 기본값은
top(대상 위 가운데). 작은 원형 트리거에서 더 어울리는compact-center가 필요하면 그때만data-ds-tip="compact-center"를 준다. - Alpine 바인딩에서는
\n을 쓴다 —:title="'1줄\n2줄'". 정적 속성 안에서는 실제 줄바꿈 또는 . 주의: 정적 HTML에 을 쓰면 파서가 실제 LF로 바꾸므로, Alpine 표현식(:title="\…`"`) 안에 넣으면 JS 문자열이 끊겨 SyntaxError가 난다. - 소스에서 여러 줄에 걸친
:title="..."표현식은 개행이 아니다 — 판정은 평가 결과 문자열 기준이다.
현재 멀티라인 툴팁이 뜨는 곳:
| 화면 | 위치 | placement | 내용 |
|---|---|---|---|
| admin — 근무 유형 모달 | apps/admin/src/views/modals/shift-type-form.html (ⓘ) | top | 연차 차감 판정 (요일/듀티 기준 + 예시) |
| admin — 근무 유형 모달 | 〃 (ⓘ) | top | 공휴일에도 근무하는 유형 (보조 스위치) |
hr-system — 시트 헤더 수식 힌트 ƒ | apps/hr-system/src/views/tabs/sheets/grid.html | top (기본값) | 수식 + 「헤더 더블클릭으로 편집」 — 범위 확장으로 자동 승격(마크업 무수정, 기존엔 브라우저 기본 툴팁) |
| hr-system — 시트 툴바 반영 상태 칩 | 〃 (「반영 필요」/「반영됨」 칩, 문구는 commit-compute.ts의 commitStatusTooltip) | top | 1줄=지금 상태, 2줄=다시 반영하는 경로(누를 버튼 + 막혔을 때 먼저 풀 것) |
| hr-system — 급여대장 「소스 전체 반영」 버튼 | 〃 (문구는 commit-compute.ts의 ledgerCommitTooltip) | top | 1줄=값이 소스 시트에서 온다(대장엔 반영 버튼이 없다), 2줄=미반영 소스 N개 + 이 버튼이 하는 일 |
| hr-system — 시트 사이드바 「작업 중」 점 | apps/hr-system/src/views/tabs/sheets/sidebar.html (문구는 commit-compute.ts의 sheetDotTooltip) | top | 1줄=상태 이름(작업 중), 2줄=점 색이 뜻하는 반영 상태(반영 필요 / 반영 완료), 3줄=마지막 값 수정 시각(「3시간 전 수정」). 반영 개념이 없는 시트는 2줄째를 뺀다 |
색 톤 (어두움 / 밝음)
툴팁에는 축이 셋 있고 서로 독립입니다 — 종류(한 줄 / 멀티라인, 라벨의 줄바꿈으로 자동), placement(어디에 뜨는가), 색 톤(어떤 색인가). 톤은 2026-07-27에 추가된 세 번째 축이고, 종류가 3개가 된 것이 아닙니다.
| 톤 | 켜는 법 | 배경 | 글자 | 테두리 | 쓰는 자리 |
|---|---|---|---|---|---|
| 어두움(기본) | 아무것도 안 함 | --color-neutral-900 | --ds-bw-white | 없음 | 대부분의 화면 — 강한 대비로 확실히 읽힘 |
| 밝음 | data-ds-tip-tone="light" | --color-bg-normal | --color-label-alternative | 1px --color-line-normal | 밝은 패널·카드 위에서 검은 알약이 과하게 튀는 자리 |
<!-- 트리거 하나만 밝게 -->
<button class="icon-btn" data-ds-tip-tone="light" title="삭제">…</button>
<!-- 패널 단위로 한 번에 (안쪽 트리거는 마크업 무수정) -->
<div class="ds-modal__body" data-ds-tip-tone="light">…</div>- 조상까지 봅니다 —
tooltip.ts가closest('[data-ds-tip-tone="light"]')로 판정하므로, 화면·패널 루트에 한 번만 걸면 그 안의 모든 툴팁이 밝은 톤이 됩니다. 밝은 톤은 보통 트리거 하나가 아니라 표면 단위 결정이라 이렇게 뒀습니다. - 값은
light하나뿐입니다. 기본이 어두움이므로dark같은 값을 만들 필요가 없고, 톤을 늘리는 것은 금지입니다(종류 3개 금지와 같은 이유 — 버블 스타일이 갈라지기 시작하면 되돌리기 어렵습니다). .ds-tooltip--light를 손으로 붙이지 마세요. 버블은 body에 하나뿐인 싱글톤이라, 클래스는show()가 표시할 때마다 다시 켜고 끕니다(직전 대상의 톤이 다음 툴팁으로 새지 않게).
구현 메모 — 색은 변수 2개로 뒤집습니다. .ds-tooltip이 --ds-tip-bg/--ds-tip-fg를 선언하고 버블 배경과 4개 placement의 화살표(::before)가 모두 같은 변수를 읽습니다. 그래서 톤 모디파이어는 변수 2개만 덮으면 되고, placement별로 색을 다시 적을 필요가 없습니다(예전처럼 화살표마다 색을 하드코딩하면 톤 추가 때 3곳을 빠뜨리기 쉽습니다).
밝은 톤에만 테두리가 있는 이유는 흰 버블이 흰 배경 위에서 경계를 잃기 때문입니다. 화살표도 함께 테두리를 받는데, 45° 회전한 사각형이라 바깥을 향하는 두 변이 placement마다 다릅니다(아래 방향 = bottom+right, 위 방향 = top+left, 왼쪽 방향 = left+bottom). 화살표 안쪽 절반은 버블 테두리 위에 겹쳐 그려지므로, 두 선이 정확히 이어지도록 화살표를 1px 더 바깥으로 밀어 둡니다.
compact 라벨 계산 (title 불필요)
<select>→ 현재 선택된option.text(title 에 줄바꿈이 있으면 그 title 을 상세 툴팁으로).ms-dropdown__trigger→ 다중 선택 시 체크된 항목 라벨 콤마 join, 0/1개면.ms-dropdown__label텍스트
위치 안내 툴팁 (AI 기능 바로가기)
AI 어시스턴트에서 「기능 바로가기」를 누르면 해당 화면으로 이동한 뒤, 대상 버튼·영역에 강조선을 두르고 그 옆에 위치 안내 툴팁을 띄웁니다. hover 툴팁과 생김새·등장 인터랙션은 같지만 쓰임이 달라 별개 케이스로 둡니다.
hover 툴팁 (.ds-tooltip) | 위치 안내 툴팁 (.ds-guidance-hint) | |
|---|---|---|
| 뜨는 때 | 마우스를 올리면 | AI 「기능 바로가기」 실행 시 |
| 닫히는 때 | 마우스가 떠나면 | × · ESC · 대상 클릭 · 다른 안내 · 화면/사용자 변경 (자동 종료 없음) |
| 개수 | body 에 싱글톤 1개 | 안내 1건당 1개 (새 안내가 이전 것을 대체) |
| 내용 | 라벨 한 줄 / 멀티라인 | 제목(B4 Bold) + 설명(B5) + 닫기 |
| 대상 표시 | 없음 | 대상 바깥 4px 강조선 (3px) |
색 (기본)
| 부분 | 토큰 |
|---|---|
| 말풍선 배경 · 화살표 | --color-purple-500 |
| 제목 · 설명 글자 | --ds-bw-white |
| 닫기 버튼 | 아이콘 버튼 ds-btn--icon ds-btn--white ds-btn--xs + ic-close (글리프 12 · 박스 18) |
| 대상 강조선 | --color-purple-400 |
색 변형. 말풍선·화살표·강조선은 --ds-guidance-bg / --ds-guidance-fg / --ds-guidance-line 세 변수만 읽습니다. 다른 색이 필요하면 design-system.css 에 .ds-guidance--<이름> 을 추가해 이 세 변수만 덮고, 호출할 때 tone: "<이름>" 을 넘깁니다(말풍선과 강조선 두 요소에 같은 클래스가 붙습니다). 아직 기본(purple) 외의 변형은 없습니다.
highlightGuidanceTarget(getTarget, signal, isCurrent, {
title: "직원 추가",
description: "이 버튼을 눌러 시작하세요.",
// tone: "<이름>", // .ds-guidance--<이름> 을 정의한 경우에만
});인터랙션. hover 툴팁과 같습니다 — 위치를 잡은 다음 프레임에 opacity 0→1 + 위에서 4px 내려오는 슬라이드(120ms). 화살표는 8px 마름모에 끝만 2px 라운드이고, 대상 위에 뜨면 아래를, 위쪽 공간이 부족해 아래로 옮기면 위를 가리킵니다. 가로 위치는 대상 오른쪽 끝에 맞추되 화면 안으로 되돌리고, 화살표만 대상 가운데를 가리킵니다.
강조선이 잘리지 않게. 강조선은 대상 바깥 4px 에 그리지만, 대상이 화면 가장자리나 열린 AI 도크(--ds-ai-dock-w)에 닿아 있으면 상자를 화면 안으로 줄여 네 변이 모두 보이게 합니다. 도크 폭만큼은 화면에서 빼고 계산하므로 말풍선도 도크 밑으로 들어가지 않습니다. 대상이 스크롤 영역 밖으로 나가면 강조선과 말풍선을 함께 숨깁니다.
사용된 토큰 (현재)
| 카테고리 | 값 | 상태 |
|---|---|---|
| 배경/글자 (어두운 톤) | --ds-tip-bg = var(--color-neutral-900) / --ds-tip-fg = var(--ds-bw-white) | ✅ 토큰화 완료 (값 동일, 시각 변화 0) |
| 배경/글자 (밝은 톤) | --ds-tip-bg = var(--color-bg-normal) / --ds-tip-fg = var(--color-label-alternative) | ✅ 토큰만 사용 |
| 테두리 (밝은 톤만) | 1px solid var(--color-line-normal) | ✅ 토큰만 사용 |
| 그림자 (기본) | 0 4px 12px rgba(0,0,0,0.25) | ⬜ 하드코딩 유지 (결정 — 매칭 토큰 없음) |
| 그림자 (compact) | dual rgba(7,7,7,0.06) | ⬜ 하드코딩 유지 (결정) |
| 그림자 (밝은 톤) | var(--ds-shadow-md) | ✅ 토큰 사용 (25% 검정은 밝은 버블 아래에서 탁함) |
| font-size | top 12px · compact 11px | 🟡 11px는 토큰(b6=12px)보다 작음 |
| radius | top 6px · compact 4px | --ds-radius-* 매핑 검토 |
| transition | 120ms | 🟡 motion scale 부족 |
단일 출처
| 파트 | 파일 |
|---|---|
| 유틸 | packages/components/src/tooltip.ts (setupTooltip) |
| 자매 유틸 | packages/components/src/positionFloatingMenu.ts (ms-dropdown 메뉴 flip) |
| 스타일 | packages/static/styles/design-system.css (.ds-tooltip[data-placement]) |
토큰 소유권: 툴팁 룩(색·shadow·arrow·placement transform)은
.ds-tooltip클래스 = DS 소유. 색은 토큰화 완료(--color-neutral-900/--ds-bw-white), 그림자는 하드코딩 유지(매칭 토큰 없음). 마크업·위치 계산은 JS(tooltip.ts)가 담당(컴포넌트 마크업 변경 불필요).
자매: positionFloatingMenu
positionFloatingMenu(trigger, menu) — 툴팁과 별개로, ms-dropdown 등 떠 있는 메뉴를 트리거 아래에 배치하되 모달(.ds-modal/.ds-mini-modal) 안에서 아래 공간 부족 시 위로 flip. 툴팁의 compact flip과 같은 "충돌 회피" 계열 유틸 (PR #247).
검토 필요 사항
- ✅ 색 토큰화 완료 — 배경/글자/화살표
#1b1b1b/#ffffff→var(--color-neutral-900)/var(--ds-bw-white)(값 동일, 시각 변화 0). 전 앱(admin·management-dashboard·team-manager) 일괄 적용. - ⬜ 그림자는 하드코딩 유지 (결정) — 기본
0 4px 12px rgba(0,0,0,0.25)는--ds-shadow-xs~xl어디와도 안 맞음. 새 토큰 가치가 생기면 그때 토큰화. - 🟡 compact 11px / dual shadow — Figma
tooltip-compact(10702:11728) 전용 값. 마이크로 토큰 정책 결정 후 매핑. - 🟡 transition 120ms —
--duration-*motion scale 부족. - ✅ collision flip — top·compact 상단 부족 시
data-flip="down"으로 아래 표시(화살표는 위를 가리킴). compact=PR #247, top=design/adjust-table에서 추가(싱글톤 flip 잔재 누수 수정 포함). - ✅ 밝은 톤 추가 완료(2026-07-27) —
data-ds-tip-tone="light". 색은 전부 토큰(--color-bg-normal/--color-label-alternative/--color-line-normal)이고 그림자도--ds-shadow-md를 씁니다. 어두운 톤의 그림자 2종은 그대로 하드코딩입니다(위 결정 유지). - 🟡 밝은 톤을 어느 화면에 적용할지는 미정 — 컴포넌트는 준비됐지만 실제 사용처는 아직 없습니다(현재 전 화면이 기본 어두운 톤). 「밝은 패널 위에서 검은 알약이 과하다」고 판단된 화면부터
data-ds-tip-tone="light"를 겁니다. - ✅ 가로 방향 충돌 처리 완료 — 멀티라인을 아무 요소에나 쓸 수 있게 되면서(2026-07-27) 화면 가장자리 트리거가 현실이 됐고,
clampTooltipX()/clampTooltipLeft()+--ds-tip-arrow-x로 버블을 안으로 되돌리고 화살표만 대상에 남기도록 넣었다. 같은 작업에서width: max-content누락으로 오른쪽 끝 버블이 스스로 좁아지던 문제도 함께 고쳤다.
목표 & 로드맵
| 항목 | 현재 | 목표 |
|---|---|---|
| 싱글톤 + 이벤트 위임 | ✅ | 유지 |
| 종류 2가지 (한 줄 / 멀티라인) | ✅ 라벨의 줄바꿈으로 자동 판정 | 유지 — 세 번째 종류 추가 금지 |
| 색 톤 2가지 (어두움 / 밝음) | ✅ data-ds-tip-tone="light" (직교 축) | 유지 — 톤 값 추가 금지 |
| 멀티라인 적용 범위 | ✅ 대상 제한 없음 (줄바꿈 = opt-in) | 유지 |
| 4 placement (right/top/compact/compact-center) | ✅ | 유지 |
| 세로 collision flip | ✅ data-flip (top·compact·compact-center) | 유지 |
| 가로 clamp | ✅ clampTooltipX + --ds-tip-arrow-x | 유지 |
| title→aria 이관 (a11y) | ✅ | 유지 |
| 색 토큰화 | ✅ 완료 (neutral-900 / bw-white) | 유지 |
| 그림자 토큰화 | ⬜ 하드코딩 유지(결정) | 매칭 토큰 생기면 전환 |
| compact 마이크로 토큰 | 🟡 11px/dual shadow | 토큰 정책 결정 후 매핑 |
변경 이력
| 날짜 | 내용 |
|---|---|
| 2026-10-20 | 클릭 트리거 추가 — data-ds-tip-trigger="click". hover 대신 클릭할 때만 뜨고 트리거를 벗어나면 닫히는 방식이다(다시 누르면 닫힘). 긴 도움말이 hover 로 떠서 옆 체크박스를 가리던 admin 역할 추가 · 수정의 기능 묶음 목록에서 시작했다 — 이름 옆 ? 버튼(line · muted · xs · 원형)에 compact · 밝은 톤 · 멀티라인과 함께 건다. 종류 2가지 · 톤 light 하나 규칙은 그대로이고, 트리거는 그와 직교하는 축이다(단위 테스트 3개 추가). 같은 작업에서 멀티라인 + compact 조합의 줄바꿈이 사라지던 문제를 고쳤다 — compact 의 white-space: normal 이 속성 선택자라 .ds-tooltip--multiline 의 pre-line 을 이기고 있었다 |
| 2026-10-08 | 위치 안내 툴팁(AI 기능 바로가기) 케이스 추가. AI 어시스턴트 「기능 바로가기」가 띄우던 노란 notice + 「닫기」 텍스트 버튼을 툴팁 모양으로 바꿨다 — 배경 --color-purple-500 · 글자 white · 닫기는 아이콘 버튼(white · xs, ic-close) · 화살표와 등장 인터랙션은 hover 툴팁과 동일. 대상 강조선은 orange 500 → --color-purple-400. 색은 --ds-guidance-bg/-fg/-line 세 변수로만 읽어 .ds-guidance--<이름> 으로 변형을 추가할 수 있다. 강조선이 화면 끝·열린 AI 도크에 닿으면 상자를 화면 안으로 줄여 테두리가 잘리지 않게 했다(단위 테스트 1개 추가). hover 툴팁의 「종류 2가지 · 톤 light 하나」 규칙은 그대로다 → 위치 안내 툴팁 |
| 2026-07-27 | 밝은 톤(light) 추가 — 색 톤이 종류·placement와 별개인 세 번째 축이 됐다. data-ds-tip-tone="light"를 대상 또는 그 조상에 걸면 밝은 배경 + --color-label-alternative 글자 + --color-line-normal 1px 라인 버블로 바뀐다(.ds-tooltip--light, tooltip.ts가 매 표시마다 판정). 구현은 .ds-tooltip에 --ds-tip-bg/--ds-tip-fg 두 변수를 두고 버블과 4개 placement의 화살표가 같은 변수를 읽게 바꾼 것이라, 톤 모디파이어가 placement별 색을 재선언하지 않는다(어두운 톤 값은 그대로 — 시각 변화 0). 밝은 버블은 흰 배경 위에서 경계를 잃으므로 테두리를 두르고, 화살표도 바깥을 향하는 두 변에만 같은 라인을 그린 뒤 1px 바깥으로 밀어 버블 테두리와 잇는다. 그림자는 25% 검정 대신 --ds-shadow-md. 미리보기에 4번째 줄(밝은 톤) 추가 |
| 2026-07-27 | 멀티라인 툴팁의 적용 범위 확장 — 툴팁 종류를 「한 줄 / 멀티라인」 2가지로 정리. 이제 title에 줄바꿈만 있으면 셀렉터·data-ds-tip 없이도 버튼·표 셀·배지·구간 제목 등 아무 요소에서 상세 도움말이 뜬다(기본 placement top). 확장에 따라 화면 가장자리 트리거가 현실이 되므로 가로 방향 보정을 함께 넣었다 — clampTooltipX()/clampTooltipLeft()(순수 함수, 단위 테스트 12개) + --ds-tip-arrow-x로 버블은 뷰포트 안으로, 화살표는 대상 위에 남긴다. 이 과정에서 오른쪽 끝 버블이 스스로 좁아지며 세로로 길어지던 버그를 재현·수정(width: max-content — fixed 요소의 shrink-to-fit이 자기 left 기준 잔여 공간으로 계산되던 문제). hr-system 시트 수식 힌트 ƒ는 마크업 수정 없이 자동 승격 |
| 2026-07-27 | 라이브 미리보기에 멀티라인 stage 추가 — Vue 재구현이 아니라 data-ds-tip + 여러 줄 title 마크업만 두고 docs가 이미 호출해 둔 실제 setupTooltip() 이 처리(top·multiline / compact-center·multiline / 한 줄 비교 3종). 데모 쪽 show()도 .ds-tooltip--multiline 자동 토글과 top의 아래로-flip을 반영해 실제 코드와 맞춤. 가로 방향 충돌 처리가 없다는 한계는 검토 필요 사항에 기록 |
| 2026-07-27 | 문서 정정 — placement는 3개가 아니라 4개(compact-center 누락분 추가: 셀렉터·중앙 정렬·아래 화살표·flip), top 자동 대상에 .ds-btn--icon 추가. 멀티라인 툴팁 사용처를 코드에서 전수 확인해 표로 기록(admin 근무 유형 모달 ⓘ 2 · hr-system 열 설정 ? 1). 발동 조건이 「개행 title」 하나가 아니라 「툴팁 대상 + 개행」 두 가지임을 명시 — hr-system 시트 수식 ƒ 힌트는 개행 title이지만 data-ds-tip이 없어 브라우저 기본 툴팁으로 뜬다(미전환 1건으로 기록). ⚠️ 이 두 가지 조건 서술은 같은 날 범위 확장으로 폐기됐다 — 지금은 개행 하나로 충분하고, ƒ 힌트도 DS 툴팁으로 승격됐다(윗줄 참고) |
| 2026-07-07 | top placement도 상단 잘림 시 아래로 flip 추가 — data-flip="down" + .ds-tooltip[data-placement="top"][data-flip="down"] CSS(화살표가 위 가리킴, 위쪽 tip 코너만 라운드). 짧은 임베드 iframe(admin 안 team-manager/hr-system) 상단의 아이콘 버튼에서 툴팁이 프레임 위로 잘리던 문제 해결. 싱글톤 재사용 요소라 show()가 매번 data-flip 선제거 → 직전 flip 잔재 누수도 수정 (design/adjust-table) |
| 2026-06-08 | .ds-tooltip 색 토큰화(배경·글자·화살표 → --color-neutral-900/--ds-bw-white, 시각 변화 0). 그림자는 하드코딩 유지(결정). 전 앱 일괄 적용 |
| 2026-06-08 | Tooltip 페이지 신규 작성 + 라이브 미리보기(<DemoTooltip>) (PR #247 기준) |
| PR #247 | setupTooltip 공유 싱글톤 + compact <select>/ms-dropdown 자동 툴팁 + 상단 잘림 시 아래로 flip |