Groo Design

Chart

숫자의 흐름 · 비율 · 세기를 그림으로 보이는 차트 — 수입 · 지출 추이(선), 기간별 합(막대), 카테고리 비율(도넛), 요일 × 시간 세기(열지도). 차트는 카드 본문 안에 두고, 같은 숫자를 범례 · 툴팁의 글로도 읽을 수 있게 한다. 숫자 하나는 Card 의 지표 카드, 줄과 열은 Table 이다.

SEED 에는 차트 컴포넌트도 차트 색도 없다 — 팔레트 7가족과 장식용 배너 색뿐이다. SEED 문서가 가진 차트는 Layout 의 High Density 대시보드 그림 한 장이다: 선 그래프 두 계열, 좌우 이중 축의 눈금 글자를 계열 색으로, 가로 격자만, 가리킨 자리의 세로 점선과 "■ 라벨 값" 툴팁, 차트 위의 지표 타일(범례 겸 합계). 그리고 Inclusive Design 의 원칙 — "색상만으로 정보를 전달하지 않고, 텍스트, 아이콘 등 다른 시각적 요소와 함께 제공합니다" · 대체 텍스트 · 애니메이션 줄이기(당근 SEED, Apache-2.0). 색은 groo 가 v110 · v111 에서 정했고, 축 · 툴팁 · 범례 · 빈 · 실패 · 접근성은 이 그림과 원칙 위에서 groo 가 정했다(2026-10-08 사용자 결정). 값은 groo 토큰이고, SEED 와 다른 자리는 맨 아래 "SEED 와 다른 점" 에 적었다. 옛 Chart 스펙(shadcn ChartContainer · 16:9 · 아래 점 범례 · 테두리 툴팁)을 대신한다.

수치 원본은 chart.yaml이고, 색 값은 DESIGN.md 의 v110(차트 10색) · v111(옅은 바탕)이다. 수치 표 자리([표: …])와 그림 자리([그림: …])는 사이트가 그 파일로 그린다 — GitHub 에서는 그 파일 · 그림 코드로 가는 링크로 보인다.

라이트

10월 수입 · 지출

10월 카테고리별 지출

10월 지출1,240,000원
  • 교통14%173,600원
  • 경조사10%124,000원
  • 주거9%111,600원
다크

10월 수입 · 지출

10월 카테고리별 지출

10월 지출1,240,000원
  • 교통14%173,600원
  • 경조사10%124,000원
  • 주거9%111,600원
수입 · 지출 추이(이중 축 · 지표 타일) · 카테고리 도넛(목록 범례) — 라이트 · 다크

직접 골라 보기

종류(선 · 막대 · 도넛 · 열지도) · 축(하나 · 둘) · 계열 수 · 데이터(있음 · 비었음 · 실패)를 고르면 스펙대로 그린 차트와 그 코드가 바뀐다. 지표 타일을 누르면 계열이 켜지고 꺼지고, 차트를 짚으면 툴팁이 뜬다.

10월 수입 · 지출

읽는 글—
타일을 누르면 계열을 켜고 끈다(마지막 하나는 남는다). 차트를 가리키거나 누르면 · ← → 로 툴팁. 계열이 셋이면 축 하나.
종류
축
계열 수
데이터
열지도 칸 폭
모드
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"
import { Chart, ChartLegendTiles, ChartTooltip, ChartTooltipContent, chartAxisProps, chartGridProps, formatAxisWon } from "@/components/ui/chart"

<ChartLegendTiles id="trend-legend" items={[{ key: "income", label: "수입", color: "blue", total: "4,200,000원" }, { key: "expense", label: "지출", color: "red", total: "1,240,000원" }]} hidden={hidden} onHiddenChange={setHidden} />
<Chart label="…" legendId="trend-legend" height={200}>
  <AreaChart data={daysUntilToday}>
    {/* 이중 축이면 격자도 축 하나에 건다 — 없으면 recharts 가 격자를 두 줄만 긋는다 */}
    <CartesianGrid {...chartGridProps} yAxisId="income" />
    <XAxis dataKey="day" {...chartAxisProps()} />
    <YAxis yAxisId="income" tickFormatter={formatAxisWon} {...chartAxisProps({ color: "blue" })} />
    <YAxis yAxisId="expense" orientation="right" tickFormatter={formatAxisWon} {...chartAxisProps({ color: "red" })} />
    <ChartTooltip content={<ChartTooltipContent headFormatter={formatDay} valueFormatter={formatWon} />} />
    {!hidden.has("income") && <Area yAxisId="income" dataKey="income" name="수입" stroke="var(--color-chart-blue)" />}
    {!hidden.has("expense") && <Area yAxisId="expense" dataKey="expense" name="지출" stroke="var(--color-chart-red)" />}
  </AreaChart>
</Chart>

Anatomy

10월 수입 · 지출

10월 카테고리별 지출

10월 지출1,240,000원
  • 교통14%173,600원
  • 경조사10%124,000원
ⓐ Legend Tileⓑ Tick Labelⓒ Grid Lineⓓ Seriesⓔ Crosshair · Pointⓕ Tooltipⓖ Donut Centerⓗ Legend List
선 차트는 위 지표 타일 · 그리는 자리 · 눈금 글자 · 가로 격자 · 가리킴 선 · 툴팁, 도넛은 조각 · 가운데 합계 · 목록 범례
부위설명
ⓐ Legend Tile지표 타일 — 선 · 막대 차트 위. 점 + 이름 + 합계, 누르면 계열을 켜고 끈다.
ⓑ Tick Label눈금 글자 — 11 · fg-neutral-subtle(이중 축이면 계열 색).
ⓒ Grid Line가로 격자 — 점선 stroke-neutral-subtle. 세로 격자 · 축 선 없음.
ⓓ Series계열 — 차트 10색(v110).
ⓔ Crosshair · Point가리킴 — 세로 점선 + 가리킨 점.
ⓕ Tooltip툴팁 — 떠 있는 표면, 머리 + "■ 라벨 값" 줄.
ⓖ Donut Center도넛 가운데 — 합계(돈은 원까지).
ⓗ Legend List도넛 범례 — 카테고리 목록 줄(색 네모 + 이름 + % + 금액).

부위

부위설명
root차트 상자 — 카드 본문 안, 폭 100%. 높이는 쓰는 자리가 정한다
tickLabel눈금 글자 — 가로축(날짜 · 기간) · 세로축(값)
gridLine가로 격자 — 점선, 세로 격자 · 축 선은 두지 않는다
series계열 — 선 · 막대 · 조각 · 칸의 색
line선 — 선 · 영역 차트
bar막대
point가리킨 점 — 가리킨 자리에만
crosshair가리킴 선 — 세로 점선
tooltip툴팁 — 떠 있는 표면
tooltipHead툴팁 머리 — 날짜 · 기간, 옅은 작은 글
tooltipRow툴팁 줄 — "■ 라벨 값"
swatch색 네모 — 툴팁 · 도넛 범례의 계열 표시
legendTile지표 타일 — 선 · 막대 차트 위. 범례 겸 합계, 누르면 계열을 켜고 끈다
legendList도넛 범례 — 카테고리 목록 줄(색 네모 + 이름 + % + 금액)
donutCenter도넛 가운데 — 합계
heatmapCell열지도 칸 — 정사각형, 세기 색
heatmapValue열지도 칸의 금액 — 칸 폭 112 이상에서만, 글자색이 칸 밝기를 따른다
focusRing키보드 포커스 링(웹)

Properties

색

계열 색은 차트 10색이다 — 라이트 팔레트 700 · 다크 800-dark(v110). 저장된 색이 있는 항목(카테고리 · 계좌)은 그 색이고, 색이 없는 항목은 그 차트에서 아직 쓰지 않은 색부터 배정 순서(blue → green → orange → violet → pink → indigo → red → yellow → brown)로 받는다 — 저장된 색과 같은 색이 두 번 나오지 않는다(사용자 결정). 회색은 "기타" 전용이다 — 항목이 10개를 넘으면 상위 9 + 회색 "기타" 로 묶고, 색이 없다고 회색을 주지 않는다. 수입은 blue, 지출은 red 다.

10월 카테고리별 지출

10월 지출1,165,600원
  • 식비33%384,400원
  • 교통14.9%173,600원
  • 쇼핑12.8%148,800원
  • 경조사10.6%124,000원
  • 주거9.6%111,600원
  • 생활8.5%99,200원
  • 구독 — 색 없음 → 남색6.4%74,400원
  • 의료 — 색 없음 → 노랑4.3%49,600원
1파랑저장됨 — 식비
2초록저장됨 — 교통
3주황저장됨 — 쇼핑
4보라저장됨 — 주거
5분홍저장됨 — 생활
6남색→ 구독
7빨강저장됨 — 경조사
8노랑→ 의료
9갈색—
10회색"기타" 전용
배정 순서저장된 색(점선)은 건너뛰고 아직 쓰지 않은 색부터 — 구독은 남색, 의료는 노랑. 회색은 "기타" 전용
저장된 빨강(경조사) · 색 없는 구독 · 의료 — 쓰지 않은 남색 · 노랑을 받는다

색 · 배정 순서

palette계열 색설명
bluecolor-chart-blue #1D6EC9 · 다크 #69ABFF배정 1번째 — 색을 고르지 않은 첫 항목 · 수입
greencolor-chart-green #167F3F · 다크 #25C062배정 2번째
orangecolor-chart-orange #BE490D · 다크 #FF8758배정 3번째
violetcolor-chart-violet #8B4DBA · 다크 #C793F3배정 4번째
pinkcolor-chart-pink #B83B7A · 다크 #F485B6배정 5번째
indigocolor-chart-indigo #5E60C8 · 다크 #99A1FE배정 6번째
redcolor-chart-red #D72323 · 다크 #FF8477배정 7번째 · 지출
yellowcolor-chart-yellow #8C7400 · 다크 #C5A721배정 8번째
browncolor-chart-brown #9A6536 · 다크 #CF9F77배정 9번째
graycolor-chart-gray #62697A · 다크 #B7BDCC — "기타" 전용 — 색이 없는 항목에 주지 않는다기타 전용 — 10개가 넘을 때 상위 9 다음의 "기타"

계열

속성값비고
계열 색chart-{색}palette 축 — 저장된 색이 있는 항목은 그 색, 없으면 아직 쓰지 않은 색부터 배정 순서대로. 회색은 "기타" 전용

축 · 격자

눈금 글자는 11 / 15 · fg-neutral-subtle · 고정폭 숫자다. 돈 축은 "만" 단위로 줄인다(400만 · 1.2만 — 줄임은 축 · 개수만, International Design). 빼기는 U+2212 이고, 세로축의 폭은 가장 긴 글자("−3,000만")가 잘리지 않게 잡는다. 격자는 가로 점선(3 · 3) stroke-neutral-subtle 만 긋는다 — 세로 격자 · 가로축 · 세로축 선은 없다. 가로축은 오늘에서 끝난다 — 오늘 뒤 날짜를 0 으로 그리지 않는다.

순자산 추이

축 하나 — 눈금 회색눈금 11 / 15 · fg-neutral-subtle · 고정폭 숫자, 가로 점선(3 · 3) 격자만 — 세로 격자 · 축 선 없음. "−3,000만" 까지 세로축 폭 안

순자산 추이

음수 축 글자가 잘린 것세로축 폭을 짧게 잡아 빼기(−)가 상자 밖으로 — 지금 자산 화면
축 — 눈금 11 · 가로 점선 격자 · 축 선 없음 · 음수 축 글자가 잘리지 않음

눈금 글자

속성값비고
눈금 글자text-t1 11px / 400 / 15px11 / 15 — 돈 축은 "만" 단위로 줄인다(400만 · 1.2만, 빼기 U+2212). 축의 폭은 가장 긴 글자("−3,000만")가 잘리지 않게
눈금 글자색color-fg-neutral-subtle #62697A · 다크 #A2A8B7
눈금 숫자 폭tabular-nums

격자

속성값비고
격자 두께1px
격자 모양dashed점선 3 · 3 — 가로 격자만. 세로 격자 · 가로축 · 세로축 선은 긋지 않는다
격자 색color-stroke-neutral-subtle #EDEFF3 · 다크 #353B4D

이중 축

수입 · 지출 추이처럼 두 계열의 크기가 열 배 넘게 다르면 왼쪽 · 오른쪽 축을 따로 둔다(사용자 결정 — SEED 그림과 같다). 이때 눈금 글자는 그 축이 맡은 계열의 색이다(왼쪽 수입 blue · 오른쪽 지출 red — 글자 기준 4.5 를 넘는다). 축이 하나면 눈금 글자는 회색이다. 두 선의 높이를 서로 견주지 않도록 툴팁 · 지표 타일이 두 값을 숫자로 보인다. 계열이 셋 이상이거나 단위가 같은 두 계열은 축 하나다.

10월 수입 · 지출

왼쪽 수입(blue 5.09) · 오른쪽 지출(red 5.06) — 눈금 글자가 그 축의 계열 색. 두 값은 타일 · 툴팁이 숫자로 보인다. 계열이 셋이거나 단위가 같은 두 계열은 축 하나
이중 축 — 왼쪽 0 ~ 400만(blue) · 오른쪽 0 ~ 40만(red)

축

axis눈금 글자색설명
single (기본)—세로축 하나 — 눈금 글자 옅은 회색(기본)
dualchart-{계열 색} — 왼쪽 축은 왼쪽 계열(수입 blue), 오른쪽 축은 오른쪽 계열(지출 red)의 색 — 700 · 800-dark 라 글자 기준 4.5 를 넘는다. 가로축은 fg-neutral-subtle 그대로왼쪽 · 오른쪽 두 축 — 눈금 글자가 그 계열 색

툴팁

차트를 짚으면(마우스 · 터치 · 키보드) 그 자리에 세로 점선과 점(10 — 계열 색 + 카드 면 색 테두리 2)이 서고 툴팁이 뜬다. 툴팁은 떠 있는 표면이다 — bg-layer-floating · shadow-s3 · 모서리 12 · 위아래 10 · 좌우 12, 테두리 없음. 머리는 날짜 · 기간(12 · fg-neutral-subtle), 줄은 "■ 라벨 값" — 색 네모 8 + 라벨 13 · fg-neutral-subtle(글자 역할 D5) + 값 13 · 700 · fg-neutral(오른쪽, 고정폭 숫자, 돈은 원까지)이다(SEED 그림). 점은 보통 가리킨 자리에만 찍는다(점이 적은 추이는 아래 "어느 차트를 쓰나").

늘 찍는 점 — dots — 점이 적은 추이(달마다 순자산처럼 몇 점뿐인 선)는 값마다 점을 늘 찍어 어디에 값이 있는지 보인다. 선 차트의 선택 하나로 켠다 — 이름은 웹 · 앱 모두 dots, 기본은 꺼짐이다. 늘 찍는 점은 가리킨 점에서 카드 면 색 테두리를 뺀 계열 색 원이고, 짚으면 가리킨 점이 그 위에 선다. 점이 적은 추이는 채움을 빼고 선 + 점으로 그린다("어느 차트를 쓰나")(2026-10-25 05-3 — 앱 PLineChart.dots 가 먼저 생겼다, 웹은 화면 className 으로 덮던 것을 같은 이름의 선택으로 옮긴다).

10월 수입 · 지출

가리킨 자리세로 점선 · 점 10(계열 색 + 카드 면 색 테두리 2) · 툴팁 — 점은 가리킨 자리에만
툴팁bg-layer-floating · shadow-s3 · 모서리 12 · 위아래 10 · 좌우 12 · 테두리 없음. 머리 12 fg-neutral-subtle, 줄 "■ 라벨 값" — 네모 8 · 라벨 13 fg-neutral-muted · 값 700 원까지
툴팁 — "10월 8일 (목)" · ■ 수입 120,000원 · ■ 지출 86,400원

툴팁

속성값비고
툴팁 최소 너비128px
툴팁 상하 여백spacing-x2_5 10px
툴팁 좌우 여백spacing-x3 12px
툴팁 모서리radius-r3 12px
툴팁 배경color-bg-layer-floating #FFFFFF · 다크 #2D3346떠 있는 표면 — 테두리 없음
툴팁 그림자shadow-s3
툴팁 줄 사이spacing-x1 4px머리 ↔ 줄 · 줄 사이
툴팁 z-index200z-floating — specs/z-index.md L3. 차트 상자 안에 그리면 상자 안 겹침(1)

툴팁 머리

속성값
툴팁 머리 글자text-t2 12px / 400 / 16px
툴팁 머리 글자색color-fg-neutral-subtle #62697A · 다크 #A2A8B7

툴팁 줄

속성값비고
툴팁 줄 글자text-t3 13px / 400 / 18px
툴팁 라벨 글자색color-fg-neutral-subtle #62697A · 다크 #A2A8B7라벨(계열 이름) — 덧붙인 정보라 축 · 툴팁 머리와 같은 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). 떠 있는 면 위 5.50 · 다크 5.27. 값은 fg-neutral · 700 · 고정폭 숫자, 오른쪽 맞춤. 돈은 줄이지 않고 원까지
네모 ↔ 라벨 ↔ 값spacing-x1_5 6px네모 ↔ 라벨 · 라벨 ↔ 값은 12 이상

색 네모

속성값비고
색 네모 크기8px툴팁 — 도넛 범례는 10
색 네모 모서리2px모서리 2 — 네모(■)

가리킨 점

속성값비고
가리킨 점 크기10px보통은 가리킨 자리에만 — 계열 색 원 + 카드 면 색 테두리 2. 점이 적은 추이는 채움 없이 값마다 찍어도 된다(chart.md "어느 차트를 쓰나"). 값마다 늘 찍는 점은 선 차트의 선택 dots(기본 꺼짐 — 웹 · 앱 같은 이름) — 이 원에서 테두리를 뺀 계열 색 원(지름 6 · 테두리 없음)이고, 가리키면 그 위에 이 점이 선다(2026-10-25 05-3 앱 PLineChart.dots)

가리킴 선

속성값비고
가리킴 선 두께1px
가리킴 선 모양dashed세로 점선 — 가리킨 날짜 · 기간 위
가리킴 선 색color-stroke-neutral-weak #E5E8EF · 다크 #404757

선 · 막대 범례 — 지표 타일

선 · 막대 차트의 범례는 차트 위의 지표 타일이다(사용자 결정 — SEED 그림). 타일 하나가 계열 하나 — 점 8(계열 색) + 이름 13 · fg-neutral-subtle(덧붙인 정보 — 글자 역할 D5), 아래 합계 16 / 22 · 700 · fg-neutral. 켠 계열은 바탕이 그 색의 옅은 바탕(chart-{색}-subtle, v111), 끈 계열은 흰 면 + 1px stroke-neutral-weak 이다. 타일을 누르면 그 계열을 켜고 끈다 — 키보드로도(Enter · Space). 마우스를 올리면 끈 타일만 바탕이 bg-layer-default-pressed 가 되고, 누르면 색 없이 2px 거리 축소만 한다 — 바탕이 이미 켬 · 끔을 말하므로 누름에 색을 쓰지 않는다(SEED Feedback Color, Q-012-2). 마지막 하나는 끌 수 없다 — 그 타일은 켠 색 그대로 두고(회색으로 바꾸지 않는다) aria-disabled 로 막는다. 마우스를 올리면 커서가 금지 표시(not-allowed — v106 비활성 커서)이고 눌러도 축소하지 않는다(2026-10-15 사용자 결정 — 구현 세션 질문 Q-012-3, 안 C). 타일 사이 8, 타일과 차트 사이 8. 차트 아래 점 범례는 두지 않는다.

10월 수입 · 지출

둘 다 켬켠 타일 — chart-{색}-subtle 바탕, 점 8 + 이름 13 · 합계 16 / 22 · 700

10월 수입 · 지출

지출 끔끈 타일 — 흰 면 + 안쪽 1px stroke-neutral-weak, 그 계열의 선이 사라진다(마지막 하나는 끌 수 없다)
타일 사이 8 · 타일 ↔ 차트 8 · 높이 62 — 누르면 aria-pressed 가 바뀐다. 차트 아래 점 범례는 두지 않는다
지표 타일 — 수입 켬 · 지출 끔, 누르면 선이 사라진다

계열 켬 · 끔

legend지표 타일 배경지표 타일 테두리지표 타일 테두리 두께설명
shown (기본)chart-{색}-subtle — 그 계열 색의 넓은 면 옅은 바탕(v111) — 테두리 없음. aria-pressed="true". 호버 바탕 없음——계열을 그린다 — 타일 바탕 chart-{색}-subtle(기본)
hiddencolor-bg-layer-default #FFFFFF · 다크 #242938 — 흰 면 + 안쪽 1px stroke-neutral-weak — 계열이 숨었다. aria-pressed="false"color-stroke-neutral-weak #E5E8EF · 다크 #4047571px숨긴 계열 — 흰 면 + 1px 테두리

지표 타일

속성값비고
지표 타일 모서리radius-r3 12px
지표 타일 상하 여백spacing-x2_5 10px
지표 타일 좌우 여백spacing-x3 12px
타일 사이spacing-x2 8px타일 사이 8 — 차트 위 한 줄, 넘치면 줄바꿈. 타일 ↔ 차트 8
타일 이름 글자text-t3 13px / 400 / 18px이름 13 — fg-neutral-subtle, 앞 점 8(계열 색) · 점 ↔ 이름 6. 아래 2 에 합계 16 / 22 · 700 · fg-neutral · 고정폭 숫자, 돈은 원까지
타일 이름 글자색color-fg-neutral-subtle #62697A · 다크 #A2A8B7이름 — 덧붙인 정보라 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일이 가장 낮다)
지표 타일 커서pointer
지표 타일 누르는 영역타일 전체높이 62(10 + 이름 18 + 2 + 합계 22 + 10) · 폭 100 이상 — AA ✓ · AAA ✓
지표 타일 전환 대상background-color, scale
지표 타일 전환 시간motion-duration-color-transition 150ms
지표 타일 전환 곡선motion-ease-easing cubic-bezier(0.35, 0, 0.35, 1)
라이트

10월 수입 · 지출

다크

10월 수입 · 지출

수입 타일은 켠 색(chart-{색}-subtle) 그대로다 — 회색으로 바꾸지 않는다. 마우스를 올리면 커서가 not-allowed(v106 비활성 커서), 누르면 아무 일 없음 · 축소 없음(aria-disabled). 지출 타일을 다시 켜면 둘 다 누를 수 있다
끌 수 없는 마지막 타일 — 수입만 켜져 있다, 커서 금지 표시 · 누름 없음

도넛 — 목록 범례 · 가운데 합계

도넛의 범례는 카테고리 목록이다 — 줄마다 색 네모 10 + 이름 14 + % 14 · fg-neutral-subtle + 금액 14 · 700 + "원". 하위 카테고리가 있는 줄은 누르는 줄이다(통계의 카테고리 → 하위로). 가운데는 합계 — 조각의 합(16 / 22 · 700) + 위 라벨(12) — 돈은 가운데서도 줄이지 않는다("73.3만" 이 아니라 "733,000원"). 가운데에 들어가지 않으면 가운데 글을 빼고 목록 위에 합계를 둔다. 조각 사이는 0 이다. 두께는 지름에서 나온다 — 지름 ÷ 10 + 6 을 정수로 반올림한다(2026-10-15 사용자 결정 — 구현 세션 질문 Q-012-5, 안 C). 데스크톱 대시보드 160 은 22, 폰 120 은 18, 자산 180 은 24 다. 문턱이 없어 지름이 바뀌어도 고리가 고르게 굵어지고(160 에서 4 가 튀지 않는다), 화면이 새 지름을 쓰면 두께를 따로 정하지 않는다. 레시피 chartDonutRadii(지름) 이 그 두께로 innerRadius · outerRadius 를 준다.

10월 카테고리별 지출

10월 지출1,240,000원
  • 교통14%173,600원
  • 경조사10%124,000원
  • 주거9%111,600원
  • 구독6%74,400원
  • 의료4%49,600원
  • 미용2.8%34,500원
  • 기타3.2%39,900원
지름 160 · 두께 22(폰 120 · 18 — 두께 = 지름 ÷ 10 + 6) · 조각 사이 0. 가운데 합계 16 / 22 · 700 — 돈은 원까지. 범례는 줄마다 색 네모 10 · 이름 · % · 금액 "원", 상위 9 + 회색 "기타". 하위가 있는 줄은 누르는 줄(화살표)
카테고리 도넛 — 가운데 1,240,000원 · 목록 범례 9 + 기타

도넛 범례

속성값비고
범례 줄 최소 높이44px카테고리 목록 줄 — 색 네모 10 · 이름 14 · % 14 fg-neutral-subtle · 금액 14 · 700 · "원". 누르면 하위 카테고리가 있는 줄만 누르는 줄(List)
범례 줄 글자text-t4 14px / 400 / 19px
범례 줄 간격spacing-x2 8px

도넛 가운데

속성값비고
도넛 가운데 글자text-t5 16px / 22px합계 16 / 22 · 700 — 돈은 줄이지 않는다. 가운데에 들어가지 않으면 가운데 글을 빼고 범례 위 합계로. 위 라벨 12 · fg-neutral-subtle
도넛 가운데 굵기700
도넛 가운데 글자색color-fg-neutral #1A1F2E · 다크 #F5F6FA
도넛 가운데 숫자 폭tabular-nums
라이트
지름 112 · 두께 17 · 구멍 78가운데 글 뺌 → 목록 위 합계
지름 120 · 두께 18 · 구멍 84가운데 글 뺌 → 목록 위 합계
지름 140 · 두께 20 · 구멍 100가운데 글 뺌 → 목록 위 합계
10월 지출12,345,678원
지름 160 · 두께 22 · 구멍 116가운데 합계
10월 지출12,345,678원
지름 176 · 두께 24 · 구멍 128가운데 합계
10월 지출12,345,678원
지름 180 · 두께 24 · 구멍 132가운데 합계
다크
지름 112 · 두께 17 · 구멍 78가운데 글 뺌 → 목록 위 합계
지름 120 · 두께 18 · 구멍 84가운데 글 뺌 → 목록 위 합계
지름 140 · 두께 20 · 구멍 100가운데 글 뺌 → 목록 위 합계
10월 지출12,345,678원
지름 160 · 두께 22 · 구멍 116가운데 합계
10월 지출12,345,678원
지름 176 · 두께 24 · 구멍 128가운데 합계
10월 지출12,345,678원
지름 180 · 두께 24 · 구멍 132가운데 합계
두께 = 지름 ÷ 10 + 6 을 정수로 — 문턱이 없어 지름을 따라 고르게 굵어진다(160 에서 튀지 않는다). 데스크톱 160 → 22 · 폰 120 → 18. 가운데 합계는 가장 나쁜 값 12,345,678원(16 / 22 · 700)이 구멍에 들어갈 때만 — 아니면 목록 위 합계로
도넛 두께 = 지름 ÷ 10 + 6 — 지름 112 · 120 · 140 · 160 · 176 · 180, 가운데 합계가 구멍에 드는지

종류

속성line (기본)bardonutheatmap
도넛 두께——지름 ÷ 10 + 6 — 정수로 반올림 — 지름 112 → 17 · 120 → 18 · 140 → 20 · 160 → 22 · 176 → 24 · 180 → 24. 문턱 없이 지름을 따라 고르게 굵어진다(2026-10-15 사용자 결정 — 구현 세션 질문 Q-012-5, 안 C). 조각 사이 0—
series diameter——160px — 데스크톱 대시보드 — 지름은 쓰는 자리가 정한다. 두께는 지름에서 식으로 나온다—
series diameterPhone——120px — 폰 대시보드 — 구멍 84 에 가운데 합계가 들어가지 않아 목록 위로 옮긴다—
series thicknessPerDiameter——0.1 — 두께 식의 기울기 — 지름 ÷ 10—
series thicknessOffset——6px — 두께 식의 더하는 값 — + 6—
선 굵기2px — 곡선 monotone · 영역은 같은 색 25% → 0% 세로 그라디언트(겹쳐도 아래 선이 보인다)———
막대 최대 너비—28px——
막대 사이—spacing-x1 4px — 한 묶음 안 막대 사이——
막대 모서리—radius-r1 4px — 위 두 모서리만 4 — 음수 막대는 아래 두 모서리——
tooltip 트리거와 거리———8px — 칸 ↔ 툴팁 — 위 · 아래 같다
tooltip 흐리는 쪽———칸 위 — 화면에 자리가 모자랄 때만 칸 아래로 뒤집는다 — 떠 있는 층(z-floating)이라 카드 · 열지도 상자에 갇히지 않고, 첫 줄 칸도 카드 머리 위로 뜬다(Q-012-6). 가운데는 칸 가운데
tooltip viewportMargin———8px — 화면 가장자리와 최소 8 — 좌우로 밀어 넣고, 위에 8 이 남지 않으면 아래로
열지도 칸 사이———spacing-x1_5 6px — 칸 사이 6 — 가로 · 세로 같다. 왼쪽 시간대 라벨 열 56(이름 13 · 700 + 시간 11 · fg-neutral-subtle), 위 요일 머리 12 · fg-neutral-subtle

열지도

요일 × 시간처럼 두 축의 세기는 열지도다 — 왼쪽 시간대 라벨 열 56 + 요일 일곱 칸이고, 칸은 정사각형 · 모서리 4 · 사이 6 이다. 세기는 다섯 단계 — 브랜드 채움을 카드 면에 18 · 35 · 55 · 76 · 100% 섞은 지금 제품 단계다(가장 큰 칸 값의 8 · 22 · 45 · 75% 에서 끊는다). 값이 없는 칸은 bg-neutral-weak 다. 가장 큰 칸에 고리를 두르지 않는다(사용자 결정) — 가장 짙은 단계가 큰 값을 말하고, 같은 단계 칸이 여럿이면 툴팁 · 표로 보기에서 값을 읽는다. 고리는 키보드 포커스 링(stroke-focus-ring — 같은 브랜드 파랑)과 헷갈린다.

칸에 금액을 적는 것은 칸 폭이 112 이상일 때뿐이다 — 원까지, 11 / 15 · 700 · 고정폭 숫자로 쓴다("123,456,789원" 이 84, "99,999,999,999원" 이 107 이라 999억까지 들어간다). 2026-10-08 칸 폭은 1440 에서 140 · 1280 에서 117 이라 글이 보이고, 1024(81) · 768(44) · 폰 390(35)에서는 글 없이 세기 색만 칠한다. 좁다고 돈을 줄여 쓰거나("3.5만") 글자를 줄여 맞추지 않는다(사용자 결정) — 값은 칸을 가리키거나(웹) 누르면(터치) 뜨는 툴팁과 표로 보기에서 읽는다. 툴팁은 머리 "수요일 저녁 18~22시" · 줄 "■ 지출 35,000원"(네모는 그 칸의 세기 색)이고, 넓은 칸에서도 뜬다. 툴팁은 칸 위 8 에 칸 가운데로 뜨고, 화면에 자리가 모자랄 때만 칸 아래 8 로 뒤집는다 — 떠 있는 층이라 카드 · 열지도 상자에 갇히지 않으므로 첫 줄 칸도 카드 머리 위로 뜬다. 좌우는 화면 끝에서 8 안으로 밀어 넣는다(Q-012-6).

칸 글자색은 단계마다 칸 바탕 위 4.5 를 넘는 쪽으로 정해 둔다 — Desk 라이트 18 ~ 55% 는 fg-neutral(5.69 이상) · 76 · 100% 는 흰 글자(4.74 · 8.38), HR(v121 그루 초록) 라이트는 18 ~ 55% 가 fg-neutral(5.94 이상) · 76 · 100% 가 흰 글자(4.52 · 8.17), 다크는 둘 다 모두 fg-neutral(7.74 이상)이다. 넷째 단계는 75% 였다 — 그루 초록에서 흰 글자 4.40 · fg-neutral 3.73 으로 어느 쪽도 4.5 에 못 미쳐, 두 브랜드 함께 76% 로 올렸다(2026-10-22 사용자 결정 B — 열지도 넷째 칸. 이음만 76% · 이음만 67% + 검정 글자 · 4.40 받아들이기는 고르지 않았다). 값이 없는 칸의 "—" 는 fg-neutral-subtle(5.09 · 다크 4.68)이다.

요일 · 시간대별 지출

1280 — 칸 117(112 이상) · 원까지11 / 15 · 700 · 고정폭 숫자, 글자색은 단계마다(라이트 18% fg-neutral · 35% fg-neutral · 55% fg-neutral · 76% 흰 · 100% 흰 · 다크는 모두 fg-neutral). 넓은 칸에서도 가리키면 툴팁

요일 · 시간대별 지출

1024 — 칸 81 · 세기 색만칸이 112 보다 좁으면 글 없이 세기 다섯(18 · 35 · 55 · 76 · 100%)만 — 값은 칸을 가리키거나 누르면 뜨는 툴팁 · 표로 보기. 글자를 줄이거나 돈을 줄여 쓰지 않는다
칸 정사각형 · 모서리 4 · 사이 6라벨 열 56 — 이름 13 · 700 + 시간 11세기 bg-brand-solid 18 · 35 · 55 · 76 · 100%(가장 큰 값의 8 · 22 · 45 · 75% 에서 끊음) · 빈 칸 bg-neutral-weak
열지도 — 1280 칸 117 원까지(11 · 700 · 단계마다 글자색) · 1024 칸 81 색만 + 누른 칸 툴팁

열지도 칸

속성값비고
열지도 칸 비율1 / 1정사각형 — 폭은 격자가 정한다(시간대 라벨 열 56 + 요일 일곱 칸, 사이 6). 2026-10-08 칸 폭은 1440 → 140 · 1280 → 117 · 1024 → 81 · 768 → 44 · 폰 390 → 35
열지도 칸 모서리radius-r1 4px
열지도 칸 배경bg-brand-solid 18 · 35 · 55 · 76 · 100%세기 다섯 — 브랜드 채움을 카드 면에 섞은 지금 제품 단계(가장 큰 칸 값의 8 · 22 · 45 · 75% 에서 끊는다). 값이 없는 칸은 bg-neutral-weak

열지도 금액

속성값비고
글을 두는 칸 폭112px칸 폭 — 이보다 좁으면 칸에 글을 두지 않고 세기 색만 칠한다. 값은 툴팁 · 표로 보기에서 읽는다. 글자를 줄여 맞추지 않는다(지금은 1280 이상만 글이 보인다)
칸 금액 글자text-t1 11px / 15px11 / 15 — 금액은 원까지("123,456,789원" 84 · "99,999,999,999원" 107 — 999억까지 칸 112 에 들어간다). 값이 없는 칸은 "—"(fg-neutral-subtle — 5.09 · 다크 4.68)
칸 금액 굵기700
칸 금액 숫자 폭tabular-nums
칸 금액 글자색단계마다칸 바탕 위 4.5 를 넘는 쪽 — Desk 라이트 18 · 35 · 55% 는 fg-neutral(5.69 이상) · 76 · 100% 는 static-white(4.74 · 8.38), HR(v121 그루 초록) 라이트는 18 · 35 · 55% 가 fg-neutral(5.94 이상) · 76 · 100% 가 static-white(4.52 · 8.17), 다크는 둘 다 모두 fg-neutral(7.74 이상). 넷째 단계는 75% 였다 — 그루 초록에서 어느 글자도 4.5 에 못 미쳐(흰 4.40) 두 브랜드 함께 76% 로 올렸다(2026-10-22 사용자 결정 B, https://claude.ai/artifact/JftMz8DQo6yKaGJ5kS9N53). 칸마다 재지 않고 단계마다 정해 둔다

State

상태모습
enabled계열 · 타일 · 범례 줄 그대로
hovered가리킴 — 세로 점선 · 점 · 툴팁. 끈 타일 · 범례 줄은 bg-layer-default-pressed(켠 타일은 바탕 그대로)
pressed타일 — 색 없이 2px 거리 축소(마우스면 끈 타일의 호버 바탕이 남는다). 범례 줄 — 누름 바탕
focused웹 — 키보드 포커스에만 링(타일 바깥 · 범례 줄 안쪽 · 차트 상자 바깥)
disabled끌 수 없는 마지막 타일 — 켠 색 그대로 · 커서 not-allowed · 누름 없음(aria-disabled)
가리킴세로 점선 · 점 · 툴팁
끈 타일 — 기본
끈 타일 — 호버
끈 타일 — 누름
끈 타일 — 포커스(웹)
범례 줄 — 기본
범례 줄 — 호버
범례 줄 — 포커스(웹)
상태 — 가리킴 · 끈 타일 호버 · 누름 · 포커스

상태 — 지표 타일

상태지표 타일 배경타일 이름 글자색지표 타일 배율지표 타일 커서지표 타일 축소 시간지표 타일 축소 곡선
enabled 기본chart-{색}-subtle — 그 계열 색의 넓은 면 옅은 바탕(v111) — 테두리 없음. aria-pressed="true". 호버 바탕 없음color-fg-neutral-subtle #62697A · 다크 #A2A8B7 — 이름 — 덧붙인 정보라 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일이 가장 낮다)—pointer——
pressed 지표 타일 — 2px 거리 축소만(색은 켬 · 끔이 말한다) · 범례 줄 — 누름 바탕chart-{색}-subtle — 그 계열 색의 넓은 면 옅은 바탕(v111) — 테두리 없음. aria-pressed="true". 호버 바탕 없음color-fg-neutral-subtle #62697A · 다크 #A2A8B7 — 이름 — 덧붙인 정보라 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일이 가장 낮다)2px 거리 축소 — 색 없이 축소만 — 바탕이 이미 켬 · 끔을 말해 누름에 색을 쓰지 않는다(SEED Feedback Color). 마우스로 누르면 끈 타일의 호버 바탕은 그대로 남는다(Q-012-2). 모션 줄이기면 하지 않는다pointermotion-duration-pressed-scale 150msmotion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1)
disabled 지표 타일 — 켠 계열이 하나만 남아 끌 수 없다(aria-disabled). 색은 켠 타일 그대로, 커서 not-allowed · 누름 없음chart-{색}-subtle — 그 계열 색의 넓은 면 옅은 바탕(v111) — 테두리 없음. aria-pressed="true". 호버 바탕 없음color-fg-neutral-subtle #62697A · 다크 #A2A8B7 — 이름 — 덧붙인 정보라 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일이 가장 낮다)없음 — 눌러도 아무 일이 없다 — 축소도 하지 않는다. 바탕 · 글자색은 켠 타일 그대로(회색으로 바꾸지 않는다), aria-disabled="true"not-allowed — 켠 계열이 하나만 남은 타일 — 끌 수 없다를 커서가 알린다. v106 비활성 커서와 같다(2026-10-15 사용자 결정 — 구현 세션 질문 Q-012-3, 안 C). 포인터 이벤트는 끄지 않는다(끄면 커서가 안 보인다)——

상태 — 끈 타일

상태지표 타일 배경타일 이름 글자색지표 타일 테두리지표 타일 테두리 두께지표 타일 배율지표 타일 축소 시간지표 타일 축소 곡선
enabled 기본color-bg-layer-default #FFFFFF · 다크 #242938 — 흰 면 + 안쪽 1px stroke-neutral-weak — 계열이 숨었다. aria-pressed="false"color-fg-neutral-subtle #62697A · 다크 #A2A8B7 — 이름 — 덧붙인 정보라 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일이 가장 낮다)color-stroke-neutral-weak #E5E8EF · 다크 #4047571px———
hovered 가리킴 — 마우스 · 터치로 짚은 자리(툴팁 · 점 · 세로선). 끈 타일 · 범례 줄은 누름과 같은 바탕color-bg-layer-default-pressed #F7F8FD · 다크 #353B4D — 끈 타일만 — 켠 타일은 바탕이 계열 색이라 호버 바탕을 두지 않는다(Q-012-2)color-fg-neutral-subtle #62697A · 다크 #A2A8B7 — 이름 — 덧붙인 정보라 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일이 가장 낮다)color-stroke-neutral-weak #E5E8EF · 다크 #4047571px———
pressed 지표 타일 — 2px 거리 축소만(색은 켬 · 끔이 말한다) · 범례 줄 — 누름 바탕color-bg-layer-default #FFFFFF · 다크 #242938 — 흰 면 + 안쪽 1px stroke-neutral-weak — 계열이 숨었다. aria-pressed="false"color-fg-neutral-subtle #62697A · 다크 #A2A8B7 — 이름 — 덧붙인 정보라 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일이 가장 낮다)color-stroke-neutral-weak #E5E8EF · 다크 #4047571px2px 거리 축소 — 색 없이 축소만 — 바탕이 이미 켬 · 끔을 말해 누름에 색을 쓰지 않는다(SEED Feedback Color). 마우스로 누르면 끈 타일의 호버 바탕은 그대로 남는다(Q-012-2). 모션 줄이기면 하지 않는다motion-duration-pressed-scale 150msmotion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1)

상태 — 도넛 범례 줄

상태범례 줄 배경
enabled 기본—
hovered 가리킴 — 마우스 · 터치로 짚은 자리(툴팁 · 점 · 세로선). 끈 타일 · 범례 줄은 누름과 같은 바탕color-bg-layer-default-pressed #F7F8FD · 다크 #353B4D
pressed 지표 타일 — 2px 거리 축소만(색은 켬 · 끔이 말한다) · 범례 줄 — 누름 바탕color-bg-layer-default-pressed #F7F8FD · 다크 #353B4D

모션

전환시간곡선대상비고
타일 · 범례 줄motion-duration-color-transition 150msmotion-ease-easing cubic-bezier(0.35, 0, 0.35, 1)background-color
타일 누름motion-duration-pressed-scale 150msmotion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1)scale모션 줄이기면 하지 않는다
그려짐motion-duration-d6 300msmotion-ease-enter cubic-bezier(0, 0, 0.15, 1)막대 높이, 선 길이, 조각 각도처음 그릴 때 한 번 — 모션 줄이기면 바로 그린다(라이브러리 기본 "auto" — 강제로 켜지 않는다)

Guidelines

어느 차트를 쓰나

"무엇을 보이려나" 로 고른다 — 차트가 아닌 Card 의 지표 카드 · Table 도 같은 자리에서 고른다. SEED 에는 차트 고르기 가이드가 없어 groo 가 처음 쓰는 표다 — 그래서 금지가 아니라 권장이다. 이미 정한 것(이중 축 · 지표 타일 · 열지도 칸 112 · 넷째 단계 76%)은 표 칸에 그대로 들어간다(2026-10-22 사용자 결정 5B — https://claude.ai/artifact/KPp9Lpd3v5KMgNrDn7pZmt).

① 상황 → 고를 것

보이려는 것고를 것Desk 예이럴 때는 다른 것
날짜를 따라 오르내리는 흐름선(영역)10월 수입 · 지출 추이 · 순자산 추이점이 셋 이하 → 지표 카드 · 막대 · 점이 적은 추이는 채움 없이 선 + 점으로 그려도 된다(달마다 순자산 — 2026-10-23 I-05 Q2)
기간마다의 합을 견준다 · 음수가 섞인다막대월별 순저축 · 예산 이행률날짜가 30칸을 넘는 흐름 → 선
한 기간 전체를 나눈 몫(2 ~ 10 + 기타)도넛 + 목록 범례10월 카테고리별 지출음수 · 다른 단위가 섞임 · 자산과 빚 → 막대 · 목록(아래 "도넛은 한 전체의 몫")
두 축(요일 × 시간대)의 세기열지도요일 · 시간대별 지출축이 하나 → 막대
숫자 하나 · 둘과 그 변화지표 카드 + 증감(Card)이번 달 지출 ▲ 12% 지난달보다흐름을 봐야 → 선
값을 정확히 읽고 견준다 · 열이 셋 이상표(Table)날짜별 수입 · 지출 — 차트의 "표로 보기"—

② 비슷한 것끼리

선막대도넛열지도지표 카드
묻는 말어떻게 변했나어느 기간이 많나전체 중 얼마나언제 많나지금 얼마 · 얼마나 변했나
가로축날짜 — 오늘에서 끝난다기간없다요일 × 시간대없다
계열셋까지 권장(아래 "계열은 셋까지")셋까지 권장 · 쌓기 포함한 계열(조각 2 ~ 10 + 기타)한 값숫자 하나
범례위 지표 타일(켜고 끔)위 지표 타일목록 범례(색 · % · 금액)없음 — 세기 다섯라벨
음수된다된다(아래 모서리)안 된다안 된다된다(−)
폰 360높이만 낮게막대 수를 줄인다지름 120 — 합계가 안 들면 목록 위칸 30 — 색만한 줄에 하나
값 읽기툴팁 · 표로 보기툴팁 · 표로 보기목록 범례 금액툴팁 · 표로 보기숫자 그대로

지표 카드와 지표 타일은 다르다 — 지표 카드(Card)는 숫자 하나를 보이는 카드이고, 지표 타일(위 "선 · 막대 범례")은 선 · 막대 차트 위의 범례다(합계 + 누르면 계열을 켜고 끈다).

10월 수입 · 지출

선 — 흐름날짜를 따라 오르내리는 흐름 · 가로축은 오늘에서 끝난다

월별 수입 · 지출

막대 — 기간마다의 합기간끼리 견준다 · 음수가 섞여도 된다

10월 카테고리별 지출

10월 지출1,240,000원
  • 교통14%173,600원
  • 경조사10%124,000원
  • 주거9%111,600원
도넛 — 한 전체의 몫2 ~ 10 + 기타 · 목록 범례 · 가운데는 조각의 합

요일 · 시간대별 지출

열지도 — 두 축의 세기요일 × 시간대 · 칸 21 은 112 보다 좁아 세기 색만
이번 달 지출1,240,000원지난달보다 12% 더 썼어요
지표 카드 — 숫자 하나숫자 하나 · 둘과 그 변화 — 차트가 아니라 Card 의 지표 카드
무엇을 보이려나 — 선 흐름 · 막대 기간 합 · 도넛 몫 · 열지도 세기 · 지표 카드 숫자 하나

계열은 셋까지

선 · 막대 한 차트의 계열은 셋까지를 권한다 — 넷이 넘으면 선이 엉켜 어느 선이 무엇인지 범례를 오간다. 넷 이상이 필요하면 한 기간의 몫(도넛) · 표로 바꿀 수 있는지 먼저 본다. 꼭 필요하면 까닭을 적고 둘 수 있다. 같은 기간을 위아래 두 차트로 나누지는 않는다 — 크기가 열 배 다른 두 계열은 이중 축이다(위 "이중 축", 사용자 결정 10A). 지금 차트는 모두 계열 둘 이하다(2026-10-22 사용자 결정 6B — https://claude.ai/artifact/KPp9Lpd3v5KMgNrDn7pZmt).

10월 카테고리 지출

이렇게 — 셋까지 — 선마다 따라 읽힌다

10월 카테고리 지출

이렇게 하지 않는다 — 다섯 — 선이 엉켜 어느 선이 무엇인지 범례를 오간다. 넷 이상이면 도넛 · 표를 먼저 본다
한 차트의 계열 — 셋 · 다섯

도넛은 한 전체의 몫

도넛은 한 전체를 나눈 몫이다 — 0 보다 큰 같은 단위 값만 조각이 된다. 자산과 빚을 한 도넛에 넣지 않는다 — 큰 조각(대출)과 가운데 숫자가 맞지 않고, "전체 중 얼마나" 가 무엇의 전체인지 흐려진다. 가운데는 조각의 합이다 — 순자산처럼 조각의 합이 아닌 숫자는 순자산 카드 · 지표 카드로 둔다. 0 이하 값은 조각이 못 된다 — 빠지면 % 가 틀리므로, 음수가 섞이면 막대 · 목록이다. 자산 화면의 모양(지금 웹 자산 도넛은 자산 + 빚 조각 · 가운데 순자산)은 이관 때 화면 비교로 고른다(2026-10-22 사용자 결정 8B — https://claude.ai/artifact/KPp9Lpd3v5KMgNrDn7pZmt).

자산 구성

자산8,450,000원
  • 예금56.8%4,800,000원
  • 투자37.9%3,200,000원
  • 현금5.3%450,000원
이렇게 — 한 전체(자산)의 몫 — 가운데는 조각의 합, 빚은 따로(순자산 카드 · 막대)

자산 구성

순자산−2,240,000원
  • 예금26.3%4,800,000원
  • 투자17.5%3,200,000원
  • 카드값3.5%640,000원
  • 대출52.6%9,600,000원
이렇게 하지 않는다 — 자산 + 빚 조각 · 가운데 순자산 — 가장 큰 조각(대출)과 가운데 숫자가 맞지 않는다
도넛에 넣는 것 — 한 전체(자산)의 몫 · 자산 + 빚 조각에 가운데 순자산

색 없는 항목은 쓰지 않은 색부터

색을 저장하지 않은 항목에 순번 색을 그대로 주지 않는다 — 7번째 조각이 빨강을 받으면 저장된 빨강(경조사)과 같은 색이 둘이 된다. 저장된 색을 먼저 칠하고, 남은 항목은 그 차트에서 쓰지 않은 색부터 배정 순서로 준다. 회색은 "기타" 에만 — 색이 없다는 이유로 회색을 주지 않는다. 같은 카테고리의 색은 다른 카테고리가 생기면 바뀔 수 있다 — 늘 같은 색이어야 하면 카테고리에 색을 저장한다.

  • 식비33%
  • 교통15%
  • 쇼핑13%
  • 경조사11%
  • 주거10%
  • 생활9%
  • 구독6%
  • 의료4%
이렇게 — 저장된 색 먼저, 남은 항목은 쓰지 않은 색부터 — 구독 남색 · 의료 노랑
  • 식비33%
  • 교통15%
  • 쇼핑13%
  • 경조사11%
  • 주거10%
  • 생활9%
  • 구독6%
  • 의료4%
이렇게 하지 않는다 — 순번 그대로 — 7번째(빨강)가 저장된 빨강(경조사)과 겹친다
  • 식비33%
  • 교통15%
  • 쇼핑13%
  • 경조사11%
  • 주거10%
  • 생활9%
  • 구독6%
  • 의료4%
이렇게 하지 않는다 — 색 없는 항목에 회색 — "기타" 와 구분되지 않는다
쓰지 않은 색부터 · 순번 그대로(빨강 둘) · 회색

오늘 뒤는 그리지 않는다

기간이 이번 달이면 가로축은 오늘에서 끝난다 — 오늘 뒤 날짜를 0 으로 그리면 선이 바닥으로 떨어져 "이번 달 지출이 줄었다" 로 읽힌다. 남은 날의 자리는 비워 둔다(축 눈금은 그 달 끝까지 둘 수 있다).

이렇게 — 오늘(8일)에서 끝난 선 — 남은 날의 자리는 비워 둔다(눈금은 달 끝까지 둘 수 있다)
이렇게 하지 않는다 — 31일까지 0 으로 — 선이 바닥으로 떨어져 "지출이 줄었다" 로 읽힌다
오늘(8일)에서 끝난 선 · 31일까지 0 으로 떨어진 선

돈은 줄이지 않는다 — 축만 "만"

축 눈금은 "400만" 처럼 줄인다. 툴팁 · 지표 타일 · 도넛 가운데 · 열지도 칸 · 범례 · 대체 표의 돈은 원까지 쓴다("1,240,000원"). 좁은 자리에 원까지 들어가지 않으면 줄이지 않고 글을 뺀다 — 열지도 칸은 세기 색만 남기고(값은 툴팁 · 표로 보기), 도넛 가운데는 목록 위 합계로 옮긴다(2026-10-08). 빼기는 U+2212 하나다 — 같은 차트 안에서 "-" 와 "−" 를 섞지 않는다.

이렇게 — 축 눈금만 "400만" — 툴팁 · 가운데 · 범례는 원까지
10월 지출124만
이렇게 하지 않는다 — 도넛 가운데 돈을 "124만" 으로 — 원까지 들어가지 않으면 가운데 글을 빼고 목록 위 합계로
축 "400만" · 툴팁 원까지 · 도넛 가운데 "73.3만" 으로 줄인 것

색만으로 알리지 않는다

계열은 늘 이름과 함께다 — 지표 타일 · 목록 범례 · 툴팁이 이름을 보인다. 선이 둘이면 범례 순서와 선의 위아래가 같게 둔다. 다크의 빨강 · 주황은 둘 다 산호색이라 가장 가깝다(v110) — 한 차트에 둘이 이웃하면 이름이 가른다.

가까운 색 짝 — 차트 10색(v110) 가운데 서로 가장 가까운 짝을 잰 값이다(ΔE00 — 작을수록 가깝다).

짝라이트다크
주황 · 빨강11.39.7가장 가깝다 — 다크는 둘 다 산호색
파랑 · 남색11.611.5
보라 · 남색11.712.8
주황 · 갈색12.514.0
배정 순서의 이웃(노랑 · 갈색)16.018.2순서에서 가장 가까운 이웃 — 나머지 이웃은 17.5 ~ 60.2

배정 순서(파랑 → 초록 → 주황 → 보라 → 분홍 → 남색 → 빨강 → 노랑 → 갈색)는 이웃끼리 떨어져 있어, 색 없는 항목만 있는 도넛에서는 가까운 짝이 붙지 않는다. 붙는 것은 저장된 색끼리이거나 색을 정해 두는 두 계열을 고를 때다. 색을 정해 두는 두 계열(수입 · 지출처럼)은 위 짝을 고르지 않는다. 저장된 색끼리 이웃하면 이름 · 범례 순서가 가른다. 값 · 배정 순서는 그대로다(2026-10-22 사용자 결정 7B — https://claude.ai/artifact/KPp9Lpd3v5KMgNrDn7pZmt).

라이트

10월 수입 · 지출

이렇게 — 수입 파랑 · 지출 빨강 — 먼 짝

10월 수입 · 지출

이렇게 하지 않는다 — 주황 · 빨강 — 가까운 짝(라이트 11.3 · 다크 9.7), 다크에서는 이름 없이 못 가른다
다크

10월 수입 · 지출

이렇게 — 수입 파랑 · 지출 빨강 — 먼 짝

10월 수입 · 지출

이렇게 하지 않는다 — 주황 · 빨강 — 가까운 짝(라이트 11.3 · 다크 9.7), 다크에서는 이름 없이 못 가른다
두 계열의 색 — 수입 파랑 · 지출 빨강(먼 짝) · 주황 · 빨강(가까운 짝)

한 계열을 둘로 쪼갠 쌓은 막대(통계의 고정 · 변동 — 한 색을 짙게 + 22% 옅게, 2026-10-21)는 지금 이 스펙의 계열 색(차트 10색 하나씩)에 없는 표현이다 — 이관 때 따로 정한다.

기다리는 동안 · 비었을 때 · 실패

카드 머리 · 지표 타일 이름 · 범례 틀은 그리고, 차트 자리만 Skeleton(모서리 16)이다. 비었으면 차트 자리에 Result Section medium("이번 달 지출이 없어요"), 못 불러왔으면 failure + "다시 시도" — 빈 축 · 회색 고리 · 0 으로 그린 막대로 대신하지 않는다. 시간표는 Skeleton 의 "기다리는 동안" 이다.

10월 수입 · 지출

수입
지출
불러오는 동안머리 · 타일 이름은 그리고 차트 자리만 Skeleton(모서리 16)

10월 지출

이번 달 지출이 없어요
비었음빈 축 · 회색 고리 · 0 막대로 대신하지 않는다

10월 수입 · 지출

추이를 불러오지 못했어요

잠시 뒤 다시 시도해주세요.

실패Result Section failure + 다시 시도
차트 자리 스켈레톤 · 비었음 · 실패 + 다시 시도

모션

처음 그릴 때 막대가 자라고 선이 그어지는 모션(300ms)은 한 번만이다. 모션 줄이기를 켠 사람에게는 바로 그린다 — 차트 라이브러리의 기본("auto")을 두고, 모션을 강제로 켜지 않는다. 계열을 켜고 끌 때 · 기간을 바꿀 때도 같다.

보조 기술 — 요약 이름 · 목록 범례 · 표로 보기

차트 상자는 role="img" 와 요약 이름이다 — "10월 수입 · 지출 추이, 수입 4,200,000원 · 지출 1,240,000원". 지표 타일 · 목록 범례는 글로 읽히는 대체다(차트 그림은 장식처럼 건너뛴다). 날짜마다 값을 읽어야 하는 차트(추이 · 열지도)는 "표로 보기" 를 둔다 — 같은 값을 Table 로(숨긴 표 또는 펼치는 표). 키보드로 차트에 들어가면 ← → 로 날짜를 옮기며 툴팁을 띄운다(열지도는 ← → 로 요일 · ↑ ↓ 로 시간대, 포커스 링이 차트 상자에 보인다).

10월 수입 · 지출

보조 기술이 읽는 글: 그림, 10월 수입 · 지출 추이, 수입 4,200,000원 · 지출 1,240,000원보조 기술이 읽는 글: 계열, 수입 4,200,000원 눌림 · 지출 1,240,000원 눌림
요약 이름 · 목록 범례

10월 날짜별 수입 · 지출

10월 날짜별 수입 · 지출
날짜
수입
지출
10월 1일 (목)
3,800,000원
152,300원
10월 2일 (금)
0원
98,400원
10월 3일 (토)
0원
286,000원
10월 4일 (일)
0원
131,500원
표로 보기날짜마다 값을 읽어야 하는 차트(추이 · 열지도)는 같은 값을 Table 로 — 숨긴 표 또는 펼치는 표
차트 상자는 role="img" + 요약 이름("{기간} {무엇} — {핵심 값}"), 라이브러리가 붙이는 이름 없는 role="application" 은 걷는다. 키보드로 들어가면 ← → 로 날짜를 옮기며 툴팁
요약 이름 · 목록 범례가 대체 · 표로 보기

글

요약 이름은 "{기간} {무엇} — {핵심 값}" 문장이다. 계열 이름은 짧은 명사("수입" · "지출"), 빈 결과는 해요체("이번 달 지출이 없어요"). 툴팁 머리의 날짜는 International Design 의 표기("10월 8일 (목)" · "오후 4시").

코드

레시피 recipes/shadcn/components/ui/chart.tsx 를 쓴다(recharts 위). 아래 미리보기는 스펙 값으로 그린 모습이다.

  • Chart — 차트 상자. label(필수 — 요약 이름, role="img" 의 이름) · height(px) · legendId(대체가 되는 범례의 id — aria-describedby). 자식은 recharts 차트(ResponsiveContainer 를 안에서 감싼다).
  • chartAxisProps · chartGridProps — recharts XAxis · YAxis · CartesianGrid 에 펼쳐 넣는 값(눈금 11 · fg-neutral-subtle · 축 선 · 눈금 선 없음 · 가로 점선 격자 3 3 · stroke-neutral-subtle). 이중 축은 chartAxisProps({ color: "red" }) 처럼 계열 색을 준다.
  • ChartLegendTiles — 지표 타일 묶음(role="group"). items({ key, label, color, total }[] — color 는 차트 색 이름, total 은 원까지 만든 글) · hidden(숨긴 key 의 집합) · onHiddenChange. 타일은 <button aria-pressed> 이고 마지막 하나는 막는다(aria-disabled · 커서 not-allowed).
  • ChartTooltip · ChartTooltipContent — 툴팁. headFormatter(label) · valueFormatter(value, key) · 줄은 "■ 라벨 값".
  • ChartDonutLegend — 도넛 목록 범례(List). items({ key, label, color, percent, amount, onClick? }[] — onClick 이 있는 줄만 누르는 줄).
  • chartDonutRadii(diameter) — 도넛 지름에서 { innerRadius, outerRadius }(두께 = 지름 ÷ 10 + 6, 정수로). <Pie {...chartDonutRadii(160)}> 처럼 펼쳐 넣는다. chartDonutThickness(diameter) 는 두께만.
  • ChartDonutCenter — 가운데 합계. label · amount · onFitChange(fits)(구멍에 들어가지 않으면 그리지 않고 false 를 알린다 — 쓰는 쪽이 목록 위에 합계를 둔다).
  • ChartHeatmap — 열지도. label(필수 — 요약 이름, role="img" 의 이름) · rows({ key, label, sub }[] — 시간대, "저녁" · "1822시") · columns({ key, label }[] — 요일) · values(number[][], 줄 × 칸) · formatValue(기본 원까지 — "35,000원") · textMinCellWidth(기본 112 — 칸 폭이 이보다 좁으면 칸에 글을 두지 않는다) · tooltipLabel(row, column)(툴팁 머리 — "수요일 저녁 1822시") · valueLabel(툴팁 줄 이름 — 기본 "지출"). 세기 다섯 단계와 단계마다 글자색은 안에서 정한다. 칸 폭은 ResizeObserver 로 재고, 가리키면 · 누르면 · 키보드(← → ↑ ↓)로 툴팁을 띄운다.
  • ChartDataTable — 표로 보기. columns · rows, visuallyHidden(기본 true — 숨긴 표, false 면 차트 아래 펼친 표).
  • assignChartColors(items, { colorOf, groupOthers }) — 저장된 색 먼저, 나머지는 쓰지 않은 색부터 배정 순서, 10개를 넘으면 상위 9 + 회색 "기타"(groupOthers(rest) 가 "기타" 항목을 만든다). 돌려준 항목에 color 와 fill 이 붙어 <Pie data> 에 바로 넣는다.
  • formatAxisWon(value) — 눈금 글자("400만" · "1.2만" · "−3,000만").

수입 · 지출 추이 — 이중 축

10월 수입 · 지출

10월 수입 · 지출 — 지표 타일 둘 · 이중 축 · 오늘에서 끝남
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"
import {
  Chart, ChartLegendTiles, ChartTooltip, ChartTooltipContent, chartAxisProps, chartGridProps, formatAxisWon,
} from "@/components/ui/chart"

<ChartLegendTiles
  id="trend-legend"
  items={[
    { key: "income", label: "수입", color: "blue", total: "4,200,000원" },
    { key: "expense", label: "지출", color: "red", total: "1,240,000원" },
  ]}
  hidden={hidden}
  onHiddenChange={setHidden}
/>
<Chart label="10월 수입 · 지출 추이, 수입 4,200,000원 · 지출 1,240,000원" legendId="trend-legend" height={200}>
  {/* 오늘까지만 — 남은 날을 0 으로 채우지 않는다 */}
  <AreaChart data={daysUntilToday}>
    {/* 이중 축이면 격자도 축 하나에 건다 — 없으면 recharts 가 격자를 두 줄만 긋는다 */}
    <CartesianGrid {...chartGridProps} yAxisId="income" />
    <XAxis dataKey="day" {...chartAxisProps()} />
    <YAxis yAxisId="income" tickFormatter={formatAxisWon} {...chartAxisProps({ color: "blue" })} />
    <YAxis yAxisId="expense" orientation="right" tickFormatter={formatAxisWon} {...chartAxisProps({ color: "red" })} />
    <ChartTooltip content={<ChartTooltipContent headFormatter={formatDay} valueFormatter={formatWon} />} />
    {!hidden.has("income") && <Area yAxisId="income" dataKey="income" name="수입" stroke="var(--color-chart-blue)" />}
    {!hidden.has("expense") && <Area yAxisId="expense" dataKey="expense" name="지출" stroke="var(--color-chart-red)" />}
  </AreaChart>
</Chart>

카테고리 도넛 — 목록 범례

10월 카테고리별 지출

10월 지출1,240,000원
  • 교통14%173,600원
  • 경조사10%124,000원
  • 주거9%111,600원
  • 구독6%74,400원
  • 의료4%49,600원
  • 미용2.8%34,500원
  • 기타3.2%39,900원
읽는 글—
카테고리 — 가운데 합계 · 목록 범례(누르면 하위로)
import { Pie, PieChart } from "recharts"
import { Chart, ChartDonutCenter, ChartDonutLegend, assignChartColors, chartDonutRadii } from "@/components/ui/chart"

const slices = assignChartColors(categories, { colorOf: (c) => c.savedColor })

<Chart label="10월 카테고리별 지출, 합계 1,240,000원" legendId="cat-legend" height={160}>
  <PieChart>
    <Pie data={slices} dataKey="amount" {...chartDonutRadii(160)} paddingAngle={0} />
  </PieChart>
  <ChartDonutCenter label="10월 지출" amount="1,240,000원" />
</Chart>
<ChartDonutLegend
  id="cat-legend"
  items={slices.map((s) => ({ key: s.id, label: s.name, color: s.color, percent: s.percentText, amount: s.amountText, onClick: s.hasChildren ? () => openChildren(s.id) : undefined }))}
/>

표로 보기 · 비었음 · 실패

10월 수입 · 지출

10월 날짜별 수입 · 지출
날짜
수입
지출
10월 1일 (목)
3,800,000원
152,300원
10월 2일 (금)
0원
98,400원
10월 3일 (토)
0원
286,000원
10월 4일 (일)
0원
131,500원
10월 5일 (월)
280,000원
74,200원
10월 6일 (화)
0원
352,000원
10월 7일 (수)
0원
59,200원
10월 8일 (목)
120,000원
86,400원
읽는 글—
표로 보기 · 비었음 · 실패 + 다시 시도
import { ReceiptText } from "lucide-react"
import { ResultSection } from "@/components/ui/result-section"
import { ChartDataTable } from "@/components/ui/chart"

{query.isError ? (
  <ResultSection kind="failure" size="medium" title="추이를 불러오지 못했어요" description="잠시 뒤 다시 시도해주세요."
    primaryAction={{ label: "다시 시도", onClick: () => query.refetch() }} />
) : rows.length === 0 ? (
  <ResultSection kind="empty" size="medium" icon={<ReceiptText />} title="이번 달 기록이 없어요" />
) : (
  <>
    <TrendChart rows={rows} />
    <ChartDataTable caption="10월 날짜별 수입 · 지출" columns={["날짜", "수입", "지출"]} rows={rows.map(toWonRow)} />
  </>
)}

Behavior

인터랙션동작
마우스를 올림 · 터치로 짚음그 날짜 · 막대에 세로 점선 · 점 · 툴팁. 터치는 손을 떼도 남고, 다른 곳을 짚으면 옮긴다
열지도 칸을 가리킴 · 누름그 칸의 툴팁 — 머리 "수요일 저녁 18~22시", 줄 "■ 지출 35,000원". 칸 위 8(화면에 모자랄 때만 아래). 칸 폭 112 미만이라 칸에 글이 없을 때 값을 읽는 자리다
지표 타일 누르기그 계열을 켜고 끈다(aria-pressed) — 마지막 하나는 끌 수 없다(aria-disabled · 커서 not-allowed · 축소 없음, 눌러도 아무 일 없음)
도넛 범례 줄 누르기하위 카테고리가 있는 줄만 — 그 카테고리의 하위 도넛으로
Tab지표 타일 → 차트 상자 → 범례 줄 차례
차트 상자에서 ← · →날짜 · 막대를 옮기며 툴팁을 띄운다 · Esc 로 툴팁을 닫는다. 열지도는 ← · → 요일, ↑ · ↓ 시간대
칸 폭이 바뀜(창 크기 · 회전)열지도 칸이 112 를 넘나들면 칸 글을 보이고 감춘다 — 글자 크기는 그대로
처음 그림막대가 자라고 선이 그어진다(300ms 한 번) — 모션 줄이기면 바로
기간을 바꿈머리 · 타일 이름은 바로, 차트 자리만 기다린다(옛 기간의 값은 남기지 않는다)

Accessibility

기준검증
WCAG 1.4.3 Color contrast(글자 ≥ 4.5:1)눈금 fg-neutral-subtle 5.50 · 다크 6.09 ✓. 이중 축 눈금 blue 5.09 · red 5.06 · 다크 6.12 · 6.08 ✓. 툴팁 머리 · 줄 이름 fg-neutral-subtle 5.50 · 다크(떠 있는 면 위) 5.27 ✓. 지표 타일 이름 fg-neutral-subtle chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일) · 합계 10.32 이상 ✓. 열지도 글자 Desk 5.69 · 4.74 · 8.38 · 다크 7.74 이상, HR 5.94 · 4.52 · 8.17 · 다크 7.74 이상, 빈 칸 "—" 5.09 · 4.68 ✓
WCAG 1.4.11 Non-text contrast(≥ 3:1)계열 색 카드 면 위 4.55(노랑) ~ 5.50 · 다크 6.07 ~ 7.70 ✓. 지표 타일의 점 옅은 바탕 위 4.06 이상 ✓. 격자는 장식(1.15). 키보드 포커스 링 Desk 8.38 · 6.10 · HR 8.17 · 6.07 ✓
WCAG 1.4.1 Use of color계열은 이름(타일 · 목록 범례 · 툴팁)과 함께 — 색만으로 가르지 않는다. 열지도의 좁은 칸은 세기 색만이지만 같은 값을 툴팁 · 표로 보기가 글로 준다 ✓
WCAG 1.1.1 Non-text content차트 상자 role="img" + 요약 이름, 범례 목록 · "표로 보기" 가 대체 ✓
WCAG 2.1.1 Keyboard타일 · 범례 줄은 버튼, 차트는 ← · → 로 날짜를 옮긴다(열지도는 ↑ · ↓ 도) ✓
WCAG 2.3.3 Animation from interactions모션 줄이기면 바로 그린다 ✓
WCAG 2.5.8 Target Size — Minimum(AA ≥ 24×24)지표 타일 높이 62 · 범례 줄 44 ✓
WCAG 2.5.5 Target Size — Enhanced(AAA ≥ 44×44)타일 · 범례 줄 44 이상 ✓
ARIA차트 상자 role="img" · aria-label(요약) · aria-describedby(범례). 라이브러리가 붙이는 role="application" · 이름 없는 tabindex 를 걷는다. 지표 타일 묶음 role="group" + 이름, 타일 aria-pressed. 툴팁은 보조 기술에 숨기고 같은 값을 표 · 범례로

Do / Don't

✅ Do

  • 차트 10색(v110) — 저장된 색 먼저, 나머지는 쓰지 않은 색부터, 회색은 "기타".
  • 눈금 11 · fg-neutral-subtle, 이중 축이면 계열 색, 가로 점선 격자만.
  • 선 · 막대 범례는 위 지표 타일(켜고 끄기), 도넛 범례는 목록(금액 "원").
  • 툴팁은 떠 있는 표면 + "■ 라벨 값", 돈은 원까지.
  • 열지도 칸은 폭 112 이상에서만 원까지(11 · 700), 좁으면 세기 색만 — 값은 툴팁 · 표로 보기.
  • 오늘에서 끝나는 가로축, 음수 축 글자가 잘리지 않게.
  • role="img" + 요약 이름, 범례 목록이 대체, 모션 줄이기면 바로.
  • "무엇을 보이려나" 로 고른다 — 숫자 하나 · 둘은 지표 카드, 정확히 견줄 값은 표.
  • 선 · 막대의 계열은 셋까지 — 넷 이상이면 도넛 · 표를 먼저 본다.
  • 도넛은 한 전체의 몫 — 가운데는 조각의 합.
  • 색을 정해 두는 두 계열은 먼 짝(수입 파랑 · 지출 빨강).

❌ Don't

  • 순번 색을 그대로 — 저장된 색과 같은 색 둘 · 색 없는 항목에 회색.
  • 축 하나에 크기가 열 배 다른 두 계열 · 차트를 둘로 나눠 같은 기간을 위아래로.
  • 차트 아래 점 범례 · 테두리 툴팁.
  • 오늘 뒤 날짜를 0 으로, 도넛 가운데 돈을 "73.3만" 으로.
  • 열지도 칸 돈을 "3.5만" 으로 줄이거나, 칸에 맞춰 글자를 줄이기.
  • 실패를 빈 축 · 회색 고리로, 모션을 강제로 켜기.
  • 이름 없는 role="application" 차트.
  • 숫자 둘을 막대 둘로 — 높이를 견주려 눈금을 읽어야 한다.
  • 자산과 빚을 한 도넛에 · 가운데에 조각의 합이 아닌 숫자(순자산).
  • 두 계열에 가까운 짝(주황 · 빨강 — 다크 9.7).

Specification

chart.yaml 의 규칙을 하나도 빼지 않고 조건마다 그린다 — 웹 · 앱이 Chart 를 만들 때 이 값을 그대로 쓴다. 조건이 없는 Base 가 모든 조합에 걸리고, 뒤의 규칙이 앞의 같은 값을 덮는다. 상태는 enabled 에서 바뀌는 값만 적었다.

Base

부위상태속성값
rootenabled높이height쓰는 자리가 정한다고정 비율(16:9)을 두지 않는다 — 폰은 낮게, 데스크톱은 높게. 오늘 뒤 날짜는 그리지 않는다(가로축이 오늘에서 끝난다)
너비width100%
배경backgroundtransparent카드 면이 바탕 — 차트는 카드(card.md) 본문 안에 둔다
tickLabelenabled눈금 글자색foregroundfg-neutral-subtle#62697A다크 #A2A8B7
눈금 글자typographytext-t111px / 15px / 40011 / 15 — 돈 축은 "만" 단위로 줄인다(400만 · 1.2만, 빼기 U+2212). 축의 폭은 가장 긴 글자("−3,000만")가 잘리지 않게
눈금 숫자 폭numeralstabular-nums
gridLineenabled격자 색borderColorstroke-neutral-subtle#EDEFF3다크 #353B4D
격자 두께borderWidth1px
격자 모양borderStyledashed점선 3 · 3 — 가로 격자만. 세로 격자 · 가로축 · 세로축 선은 긋지 않는다
seriesenabled계열 색colorchart-{색}palette 축 — 저장된 색이 있는 항목은 그 색, 없으면 아직 쓰지 않은 색부터 배정 순서대로. 회색은 "기타" 전용
pointenabled가리킨 점 크기size10px보통은 가리킨 자리에만 — 계열 색 원 + 카드 면 색 테두리 2. 점이 적은 추이는 채움 없이 값마다 찍어도 된다(chart.md "어느 차트를 쓰나"). 값마다 늘 찍는 점은 선 차트의 선택 dots(기본 꺼짐 — 웹 · 앱 같은 이름) — 이 원에서 테두리를 뺀 계열 색 원(지름 6 · 테두리 없음)이고, 가리키면 그 위에 이 점이 선다(2026-10-25 05-3 앱 PLineChart.dots)
crosshairenabled가리킴 선 색borderColorstroke-neutral-weak#E5E8EF다크 #404757
가리킴 선 두께borderWidth1px
가리킴 선 모양borderStyledashed세로 점선 — 가리킨 날짜 · 기간 위
tooltipenabled툴팁 최소 너비minWidth128px
툴팁 상하 여백paddingYspacing-x2_510px
툴팁 좌우 여백paddingXspacing-x312px
툴팁 줄 사이gapspacing-x14px머리 ↔ 줄 · 줄 사이
툴팁 모서리radiusradius-r312px
툴팁 배경backgroundbg-layer-floating#FFFFFF다크 #2D3346떠 있는 표면 — 테두리 없음
툴팁 그림자shadowshadow-s30 8px 24px -4px rgba(15, 18, 28, 0.10), 0 2px 6px -2px rgba(15, 18, 28, 0.05) · 다크 0 8px 24px -4px rgba(0, 0, 0, 0.50), 0 2px 6px -2px rgba(0, 0, 0, 0.25), inset 0 1px 0 0 rgba(255, 255, 255, 0.08)
툴팁 z-indexzIndex200z-floating — specs/z-index.md L3. 차트 상자 안에 그리면 상자 안 겹침(1)
tooltipHeadenabled툴팁 머리 글자색foregroundfg-neutral-subtle#62697A다크 #A2A8B7
툴팁 머리 글자typographytext-t212px / 16px / 400
tooltipRowenabled네모 ↔ 라벨 ↔ 값gapspacing-x1_56px네모 ↔ 라벨 · 라벨 ↔ 값은 12 이상
툴팁 라벨 글자색foregroundfg-neutral-subtle#62697A다크 #A2A8B7라벨(계열 이름) — 덧붙인 정보라 축 · 툴팁 머리와 같은 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). 떠 있는 면 위 5.50 · 다크 5.27. 값은 fg-neutral · 700 · 고정폭 숫자, 오른쪽 맞춤. 돈은 줄이지 않고 원까지
툴팁 줄 글자typographytext-t313px / 18px / 400
swatchenabled색 네모 크기size8px툴팁 — 도넛 범례는 10
색 네모 모서리radius2px모서리 2 — 네모(■)
legendTileenabled지표 타일 상하 여백paddingYspacing-x2_510px
지표 타일 좌우 여백paddingXspacing-x312px
타일 사이gapspacing-x28px타일 사이 8 — 차트 위 한 줄, 넘치면 줄바꿈. 타일 ↔ 차트 8
지표 타일 모서리radiusradius-r312px
타일 이름 글자색foregroundfg-neutral-subtle#62697A다크 #A2A8B7이름 — 덧붙인 정보라 subtle(2026-10-16 사용자 결정 글자 역할 D5, 전 muted). chart-{색}-subtle 위 4.77 이상 · 다크 4.68 이상(회색 타일이 가장 낮다)
타일 이름 글자typographytext-t313px / 18px / 400이름 13 — fg-neutral-subtle, 앞 점 8(계열 색) · 점 ↔ 이름 6. 아래 2 에 합계 16 / 22 · 700 · fg-neutral · 고정폭 숫자, 돈은 원까지
지표 타일 커서cursorpointer
지표 타일 누르는 영역touchTarget타일 전체높이 62(10 + 이름 18 + 2 + 합계 22 + 10) · 폭 100 이상 — AA ✓ · AAA ✓
지표 타일 전환 대상transitionPropertybackground-color, scale
지표 타일 전환 시간transitionDurationmotion-duration-color-transition150ms
지표 타일 전환 곡선transitionEasingmotion-ease-easingcubic-bezier(0.35, 0, 0.35, 1)
legendListenabled범례 줄 최소 높이minHeight44px카테고리 목록 줄 — 색 네모 10 · 이름 14 · % 14 fg-neutral-subtle · 금액 14 · 700 · "원". 누르면 하위 카테고리가 있는 줄만 누르는 줄(List)
범례 줄 간격gapspacing-x28px
범례 줄 글자typographytext-t414px / 19px / 400
donutCenterenabled도넛 가운데 글자색foregroundfg-neutral#1A1F2E다크 #F5F6FA
도넛 가운데 글자typographytext-t516px / 22px합계 16 / 22 · 700 — 돈은 줄이지 않는다. 가운데에 들어가지 않으면 가운데 글을 빼고 범례 위 합계로. 위 라벨 12 · fg-neutral-subtle
도넛 가운데 굵기fontWeight700
도넛 가운데 숫자 폭numeralstabular-nums
heatmapCellenabled열지도 칸 모서리radiusradius-r14px
열지도 칸 배경backgroundbg-brand-solid 18 · 35 · 55 · 76 · 100%세기 다섯 — 브랜드 채움을 카드 면에 섞은 지금 제품 단계(가장 큰 칸 값의 8 · 22 · 45 · 75% 에서 끊는다). 값이 없는 칸은 bg-neutral-weak
열지도 칸 비율aspectRatio1 / 1정사각형 — 폭은 격자가 정한다(시간대 라벨 열 56 + 요일 일곱 칸, 사이 6). 2026-10-08 칸 폭은 1440 → 140 · 1280 → 117 · 1024 → 81 · 768 → 44 · 폰 390 → 35
heatmapValueenabled칸 금액 글자색foreground단계마다칸 바탕 위 4.5 를 넘는 쪽 — Desk 라이트 18 · 35 · 55% 는 fg-neutral(5.69 이상) · 76 · 100% 는 static-white(4.74 · 8.38), HR(v121 그루 초록) 라이트는 18 · 35 · 55% 가 fg-neutral(5.94 이상) · 76 · 100% 가 static-white(4.52 · 8.17), 다크는 둘 다 모두 fg-neutral(7.74 이상). 넷째 단계는 75% 였다 — 그루 초록에서 어느 글자도 4.5 에 못 미쳐(흰 4.40) 두 브랜드 함께 76% 로 올렸다(2026-10-22 사용자 결정 B, https://claude.ai/artifact/JftMz8DQo6yKaGJ5kS9N53). 칸마다 재지 않고 단계마다 정해 둔다
칸 금액 글자typographytext-t111px / 15px11 / 15 — 금액은 원까지("123,456,789원" 84 · "99,999,999,999원" 107 — 999억까지 칸 112 에 들어간다). 값이 없는 칸은 "—"(fg-neutral-subtle — 5.09 · 다크 4.68)
칸 금액 굵기fontWeight700
칸 금액 숫자 폭numeralstabular-nums
글을 두는 칸 폭threshold112px칸 폭 — 이보다 좁으면 칸에 글을 두지 않고 세기 색만 칠한다. 값은 툴팁 · 표로 보기에서 읽는다. 글자를 줄여 맞추지 않는다(지금은 1280 이상만 글이 보인다)
legendListhovered범례 줄 배경backgroundbg-layer-default-pressed#F7F8FD다크 #353B4D
legendTilepressed지표 타일 배율scale2px 거리 축소색 없이 축소만 — 바탕이 이미 켬 · 끔을 말해 누름에 색을 쓰지 않는다(SEED Feedback Color). 마우스로 누르면 끈 타일의 호버 바탕은 그대로 남는다(Q-012-2). 모션 줄이기면 하지 않는다
지표 타일 축소 시간scaleDurationmotion-duration-pressed-scale150ms
지표 타일 축소 곡선scaleEasingmotion-ease-pressed-scalecubic-bezier(0, 0, 0.15, 1)
legendListpressed범례 줄 배경backgroundbg-layer-default-pressed#F7F8FD다크 #353B4D
focusRingfocused링 두께width2px
링 색colorstroke-focus-ringDesk#0147AD다크 #7AA9F6HR#075B3C다크 #2ABE84
링 간격offset2px타일 바깥 · 범례 줄은 안쪽(−2) · 차트 상자는 바깥

kind=line

부위상태속성값
lineenabled선 굵기strokeWidth2px곡선 monotone · 영역은 같은 색 25% → 0% 세로 그라디언트(겹쳐도 아래 선이 보인다)

kind=bar

부위상태속성값
barenabled막대 최대 너비maxWidth28px
막대 사이gapspacing-x14px한 묶음 안 막대 사이
막대 모서리radiusradius-r14px위 두 모서리만 4 — 음수 막대는 아래 두 모서리

kind=donut

부위상태속성값
seriesenabled도넛 두께thickness지름 ÷ 10 + 6정수로 반올림 — 지름 112 → 17 · 120 → 18 · 140 → 20 · 160 → 22 · 176 → 24 · 180 → 24. 문턱 없이 지름을 따라 고르게 굵어진다(2026-10-15 사용자 결정 — 구현 세션 질문 Q-012-5, 안 C). 조각 사이 0
diameterdiameter160px데스크톱 대시보드 — 지름은 쓰는 자리가 정한다. 두께는 지름에서 식으로 나온다
diameterPhonediameterPhone120px폰 대시보드 — 구멍 84 에 가운데 합계가 들어가지 않아 목록 위로 옮긴다
thicknessPerDiameterthicknessPerDiameter0.1두께 식의 기울기 — 지름 ÷ 10
thicknessOffsetthicknessOffset6px두께 식의 더하는 값 — + 6

kind=heatmap

부위상태속성값
tooltipenabled트리거와 거리offset8px칸 ↔ 툴팁 — 위 · 아래 같다
흐리는 쪽placement칸 위화면에 자리가 모자랄 때만 칸 아래로 뒤집는다 — 떠 있는 층(z-floating)이라 카드 · 열지도 상자에 갇히지 않고, 첫 줄 칸도 카드 머리 위로 뜬다(Q-012-6). 가운데는 칸 가운데
viewportMarginviewportMargin8px화면 가장자리와 최소 8 — 좌우로 밀어 넣고, 위에 8 이 남지 않으면 아래로
heatmapCellenabled열지도 칸 사이gapspacing-x1_56px칸 사이 6 — 가로 · 세로 같다. 왼쪽 시간대 라벨 열 56(이름 13 · 700 + 시간 11 · fg-neutral-subtle), 위 요일 머리 12 · fg-neutral-subtle

axis=dual

부위상태속성값
tickLabelenabled눈금 글자색foregroundchart-{계열 색}왼쪽 축은 왼쪽 계열(수입 blue), 오른쪽 축은 오른쪽 계열(지출 red)의 색 — 700 · 800-dark 라 글자 기준 4.5 를 넘는다. 가로축은 fg-neutral-subtle 그대로

legend=shown

부위상태속성값
legendTileenabled지표 타일 배경backgroundchart-{색}-subtle그 계열 색의 넓은 면 옅은 바탕(v111) — 테두리 없음. aria-pressed="true". 호버 바탕 없음
legendTiledisabled지표 타일 배율scale없음눌러도 아무 일이 없다 — 축소도 하지 않는다. 바탕 · 글자색은 켠 타일 그대로(회색으로 바꾸지 않는다), aria-disabled="true"
지표 타일 커서cursornot-allowed켠 계열이 하나만 남은 타일 — 끌 수 없다를 커서가 알린다. v106 비활성 커서와 같다(2026-10-15 사용자 결정 — 구현 세션 질문 Q-012-3, 안 C). 포인터 이벤트는 끄지 않는다(끄면 커서가 안 보인다)

legend=hidden

부위상태속성값
legendTileenabled지표 타일 배경backgroundbg-layer-default#FFFFFF다크 #242938흰 면 + 안쪽 1px stroke-neutral-weak — 계열이 숨었다. aria-pressed="false"
지표 타일 테두리borderColorstroke-neutral-weak#E5E8EF다크 #404757
지표 타일 테두리 두께borderWidth1px
legendTilehovered지표 타일 배경backgroundbg-layer-default-pressed#F7F8FD다크 #353B4D끈 타일만 — 켠 타일은 바탕이 계열 색이라 호버 바탕을 두지 않는다(Q-012-2)

palette=blue

부위상태속성값
seriesenabled계열 색colorchart-blue#1D6EC9다크 #69ABFF

palette=green

부위상태속성값
seriesenabled계열 색colorchart-green#167F3F다크 #25C062

palette=orange

부위상태속성값
seriesenabled계열 색colorchart-orange#BE490D다크 #FF8758

palette=violet

부위상태속성값
seriesenabled계열 색colorchart-violet#8B4DBA다크 #C793F3

palette=pink

부위상태속성값
seriesenabled계열 색colorchart-pink#B83B7A다크 #F485B6

palette=indigo

부위상태속성값
seriesenabled계열 색colorchart-indigo#5E60C8다크 #99A1FE

palette=red

부위상태속성값
seriesenabled계열 색colorchart-red#D72323다크 #FF8477

palette=yellow

부위상태속성값
seriesenabled계열 색colorchart-yellow#8C7400다크 #C5A721

palette=brown

부위상태속성값
seriesenabled계열 색colorchart-brown#9A6536다크 #CF9F77

palette=gray

부위상태속성값
seriesenabled계열 색colorchart-gray#62697A다크 #B7BDCC"기타" 전용 — 색이 없는 항목에 주지 않는다

SEED 와 다른 점

  • groo 가 정한 자리가 대부분이다 — SEED 에는 차트 컴포넌트 · 색 · 규칙이 없다. 이중 축 · 계열 색 눈금 · 가로 격자 · 세로 점선 가리킴 · "■ 라벨 값" 툴팁 · 위 지표 타일은 SEED 대시보드 그림을 따랐다.
  • 계열 색은 groo 차트 10색(700 · 800-dark) — SEED 그림의 blue-600 · green-500 은 흰 바탕 2.84 · 2.18 로 3:1 에 못 미친다. SEED 팔레트에는 남색 · 분홍 · 갈색 가족이 없다(v110).
  • 이중 축의 눈금 글자는 계열 색 그대로 — SEED 그림은 계열 색을 옅게 썼다. groo 는 글자 기준 4.5 를 넘는 700 · 800-dark 다.
  • 지표 타일의 바탕은 chart-{색}-subtle — SEED 그림의 팔레트 100 과 같은 자리(v111).
  • 도넛 범례 · 열지도 · 빈 · 실패 · 표로 보기 — SEED 에 없다.
  • 숫자 줄임은 축만, 소수 한 자리("1.2만") — SEED 는 유효 숫자 셋("1.23만")이다(International Design).

Migration notes

2026-10-30 — 늘 찍는 점은 dots 한 이름

2026-10-23 결정(아래)은 "변형은 만들지 않는다, 화면이 덮는다" 였다. 앱은 차트 안을 화면이 덮을 길이 없어 PLineChart 에 dots(기본 꺼짐 · 지름 6 · 계열 색 · 테두리 없음 — desk-app b02a31b3)를 두었고, 이 이름을 웹 · 앱이 함께 쓰는 선택으로 적었다(Properties "툴팁" 아래 "늘 찍는 점", chart.yaml point.size 비고). 값 · 토큰 변경 없음. 레시피 Chart 는 아직 늘 찍는 점을 숨긴다([&_.recharts-line-dots]:hidden) — 레시피 · 웹 ds 에 dots 를 옮기는 일은 따로 남았다. 옛 스펙은 chart.history/v-pre-cleanup-1030.*.

2026-10-23 — 점이 적은 추이는 선 + 점도 된다

"어느 차트를 쓰나" 의 선 줄에 "점이 적은 추이는 채움 없이 선 + 점으로 그려도 된다" 를 더하고, 툴팁의 "점은 가리킨 자리에만" 을 "보통은" 으로 누그러뜨렸다(chart.yaml point.size 비고도). 자산 순자산 추이(달마다 몇 점)를 실제 차트로 그리되 채움을 빼고 선과 점이 보이게 하자는 사용자 결정(I-05 https://claude.ai/artifact/WRqqZhbQYdBCcnyEKhzeVW Q2)에서 나왔다 — 변형 · 값은 만들지 않았다(한 화면의 모양은 그 화면 지시서에). 레시피는 늘 찍는 점을 숨기므로([&_.recharts-line-dots]:hidden) 그 화면은 className 으로 덮는다.

2026-10-22 — 어느 차트를 쓰나 · 계열 셋까지 · 가까운 색 짝 · 도넛은 한 전체의 몫

머리 한 줄("추이(선) · 기간별 합(막대) · 비율(도넛) · 세기(열지도)")뿐이던 차트 고르기를 Guidelines 맨 앞 "어느 차트를 쓰나" 로 넓혔다 — 상황 표 · 견주기 표에 지표 카드 · 표까지(5B). 6ca9937(2026-10-08)에서 걷힌 두 가이드를 권장 말투로 되살렸다 — 선 · 막대 한 차트의 계열은 셋까지 권장 · 넷 이상이면 도넛 · 표를 먼저(6B — 옛 "1 ~ 3 · Don't 5개 이상" 금지는 되살리지 않았다), 가까운 색 짝은 잰 ΔE00 표 + "색을 정해 두는 두 계열은 가까운 짝을 고르지 않는다"(7B — 값 · 배정 순서는 그대로, 옛 "분배 권장" 순서는 다시 두지 않는다). 도넛은 한 전체의 몫 — 자산과 빚을 섞지 않고 가운데는 조각의 합(8B). 사용자 결정 — https://claude.ai/artifact/KPp9Lpd3v5KMgNrDn7pZmt. 고르지 않은 안: 머리 한 줄 그대로(5A) · 계열 상한 없음(6A) · 옛 금지 되살림(6C) · 한 줄 그대로(7A) · 도넛 그대로(8A) · 자산 화면 모양을 지금 정함(8C). 값 · 토큰 변경 없음.

제품이 이관 때 볼 것

  • 웹 자산 도넛 — 현금 · 투자 · 카드 빚 · 대출 빚(절댓값)을 한 도넛에 넣고 가운데에 순자산(자산 − 빚)을 쓴다. 0 이하 항목은 조각에서 빠진다(pages/asset/ui/AssetPage.tsx:307-355 — filter(amt > 0)). 이 절에 걸린다 — 자산 화면의 모양은 이관 때 화면 비교 페이지로 고른다. 앱 자산 화면에는 도넛이 없다.
  • 통계 고정 · 변동 쌓은 막대 — 한 색을 짙게 + 22% 옅게로 두 계열을 가른다(pages/stats/ui/FixedVariableTab.tsx:43-48 · 474-481, 2026-10-21). 계열 색(차트 10색 하나씩)에 없는 표현이라 이관 때 따로 묻는다.

2026-10-16 — 범례 이름 · 툴팁 줄 이름을 subtle 로(글자 역할 D5)

사용자가 글자 역할 비교 페이지에서 보조 글의 규칙을 정했다(D5 A) — fg-neutral-subtle 은 덧붙인 정보(축 · 시각 · 단위 · 이름표), fg-neutral-muted 는 문장으로 된 보조 글. 지표 타일 이름 · 툴팁 줄 이름이 muted 에서 subtle 로 바뀌어 차트 안 글자(축 · 툴팁 머리 · 이름)가 한 색이 된다. 모두 subtle(D5 B) · 지금대로(D5 C)는 고르지 않았다. 옛 스펙은 chart.history/v-pre-text-roles.*.

2026-10-15 — 구현 세션 질문(Q-012-2 · 3 · 5 · 6)

사용자가 비교 페이지에서 정했다(2026-10-15 사용자 결정 — 구현 세션 질문 Q-012-3 · Q-012-5, 정리 Q-012-2 · Q-012-6 은 "추천대로").

  • Q-012-3 끌 수 없는 마지막 타일 → 안 C(not-allowed) — 켠 색은 그대로 두고 커서만 금지 표시, 누름 축소 없음. v106 비활성 커서와 같은 표시다. YAML 에 disabled 상태(legend: shown 규칙)를 더했다. 커서 화살표(A — 지금 웹 · 옛 레시피 aria-disabled:cursor-default) · 손 모양 그대로(B)는 고르지 않았다.
  • Q-012-5 도넛 두께 → 안 C(지름 ÷ 10 + 6, 정수로) — 120 → 18 · 160 → 22 · 180 → 24 가 그대로 맞는다. YAML series 에 thickness(식) · thicknessPerDiameter 0.1 · thicknessOffset 6 · diameter 160 · diameterPhone 120 을 적고 레시피에 chartDonutRadii · chartDonutThickness 를 더했다. 160 에서 뚝 바뀌는 계단(A — 지금 앱) · 지름 비율(B)은 고르지 않았다.
  • Q-012-2 끈 타일 호버 · 누름 — 호버 바탕은 legend: hidden 규칙으로 옮겼다(켠 타일은 바탕 그대로). 누름은 색 없이 축소만이다 — 옛 레시피만 끈 타일에 누름 바탕(active:bg-…)을 주던 것을 걷었다. 웹 · 앱은 이미 그렇다.
  • Q-012-6 열지도 툴팁 자리 — kind: heatmap 규칙에 툴팁 placement(칸 위) · offset 8 · viewportMargin 8 을 적었다. 화면에 모자랄 때만 아래로 — 떠 있는 층이라 첫 줄 칸도 위로 뜬다. 레시피 · 웹은 이미 그렇다.

제품이 바꿀 것

  • 웹 — 마지막 타일 aria-disabled:cursor-default → cursor-not-allowed(chart-variants.ts). 도넛은 화면마다 손으로 적은 두께 대신 지름에서 식으로(대시보드 160 · 120 · 자산 180 은 값이 그대로). 카탈로그 견본 chart.demo.tsx 가 120 에서도 22 를 쓰는 것을 18 로.
  • 앱 — 도넛 두께 diameter >= 160 ? 22 : 18(p_chart_values.dart) → (diameter / 10 + 6).round(). 대시보드 112 는 18 → 17, 통계 176 은 28 → 24 로 바뀐다. 열지도 툴팁을 떠 있는 층(Overlay)으로 띄워 화면 기준으로 뒤집는다 — 지금은 열지도 상자 기준이라 첫 줄이 늘 아래로 뒤집힌다(p_chart_parts.dart). 마지막 타일의 커서는 폰이라 해당 없다(누름 없음은 이미 그렇다).

2026-10-08 — 축 · 툴팁 · 범례 · 접근성을 정한다

사용자가 데이터 표시 비교 페이지에서 정했다 — 색 없는 항목은 쓰지 않은 색부터(9A — 회색은 "기타" 전용), 추이 차트는 이중 축 유지(10A — 눈금 글자는 계열 색), 선 · 막대 범례는 차트 위 지표 타일(11A — 점 + 이름 + 합계, 바탕 chart-*-subtle, 누르면 계열 켜고 끔). 그리고 "따라오는 것" — 축 글자 11 fg-neutral-subtle · 가로 점선 격자 stroke-neutral-subtle · 툴팁 bg-layer-floating · s3 · 모서리 12 · "■ 라벨 값" · 도넛 범례는 카테고리 목록 + 금액 "원" · 오늘 뒤 날짜 안 그림 · 음수 축 글자 안 잘림 · role="img" + 요약 이름 · 범례 목록이 대체 · 모션 줄이기면 바로 · 빈 · 실패는 작은 Result Section · 열지도 글자 4.5. 회색(9B) · 색 필수(9C) · 축 하나(10B) · 차트 둘(10C) · 아래 점 범례(11B)는 고르지 않았다. 스펙을 쓰다 나온 것(같은 비교 페이지 19) — 열지도 칸의 돈은 칸 폭 112 이상에서만 원까지, 좁으면 세기 색만(19B — 값은 툴팁 · 표로 보기, 글자를 줄여 맞추지 않는다). 늘 색만(19A) · 축처럼 줄여 쓰기(19C)는 고르지 않았다. 구현을 앞두고 나온 것(같은 비교 페이지 22) — 가장 큰 칸에 고리를 두르지 않는다(22A — 지금 웹의 고리는 칸 색에 묻히고 포커스 링과 겹친다). 고리 있음(22B)은 고르지 않았다. 따라오는 것으로 — 세기 다섯(초안의 넷을 지금 제품대로 바로잡음) · 툴팁은 넓은 칸에서도 · 화살표 키로 칸을 옮긴다. 옛 스펙은 chart.history/v-pre-seed-data.* 에 남겼다.

옛 스펙 안의 어긋남을 걷었다 — 배정 순서가 규칙(v110 순서)과 "분배 권장"(옛 red → green → blue …) 두 벌이었다. "모든 차트 색은 흰 글자와 4.5:1" 은 다크에서 틀렸다 — 800-dark 위 흰 글자는 2.4 안팎이다(v110). 차트 색 위에 글자를 얹으면 fg-neutral-inverted(Avatar 이니셜과 같다)다. Layout 예시(HR 부서별 인원 · 직급 도넛 · 연간 출근율 · RadialBar KPI)는 제품에 없었다. 툴팁 모서리 4 · 테두리 · 아래 점 범례 · 16:9 · 툴팁 표시 세 가지(점 · 선 · 점선)를 걷었다.

제품은 앱 적용 단계에서 옮긴다(2026-10-08 조사 — Desk 웹 · HR 은 크로미움에 띄워 쟀고, Desk 앱은 위젯 테스트 · 코드로 봤다).

  • 차트 색이 세 제품 세 벌 — 웹은 10-06 토큰 가져오기로 v110 이 들어왔다(shared/styles/groo-tokens.css:263-282 · 1002-1011). 앱은 옛 v21 상수(app/theme/colors.dart:69-89 · core/format/chart_palette.dart — 빨강 #C73838 · 다크 #ECA0A0)라 "식비" 가 웹 #BE490D / #FF8758 · 앱 #B36418 / #E8B266 이다(D3). HR 은 recharts 데모 색(#0088FE · #00C49F · #FFBB28 · #FF8042 · #8884D8 — features/vacation-history/ui/VacationTypeStatsContent.tsx:8-23) 고정이라 흰 바탕 1.69 ~ 3.53, 다크에서도 격자 #CCCCCC · 축 #888888(3.54)이다(MonthVacationStatsContent.tsx:56-87, D7). 앱 · HR 을 v110 으로 — HR 휴가 유형은 차트 색 이름에 잇는다.
  • 순번 색이 저장된 색과 부딪친다 — 색 없는 카테고리(구독)에 7번째 순번 색(빨강)을 줘 저장된 빨강(경조사)과 겹친다 — 홈 · 통계 도넛에 #D72323 조각이 둘(pages/dashboard/ui/DashboardPage.tsx:339-346 · pages/stats/ui/StatsPage.tsx:265-272 · 앱 features/dashboard/presentation/dashboard_screen.dart:961-971, D4). 10개를 넘으면 순번이 한 바퀴 돌아 회색이 일반 조각에 간다. assignChartColors 로.
  • 이름 없는 차트 — recharts 3.8 기본값으로 모든 차트 SVG 가 role="application" · tabindex=0 인데 이름 · <title> · 대체 글 · 초점 링이 0 이다(웹 · HR). 앱 차트 파일 5개는 Semantics( 0(D8). role="img" + 요약 이름으로.
  • 모션 줄이기 무시 — 공용 Donut 과 예산 막대가 isAnimationActive 를 참으로 박았다(shared/ui/groo/charts.tsx:671 · pages/budget/ui/BudgetPage.tsx:1191, D11). 렌더로 확인 — 줄이기 상태에서도 조각이 120ms 사이에 바뀐다. 기본 "auto" 로.
  • 오늘 뒤 날짜를 0 으로 — 일별 추이가 10/9 ~ 10/31 을 0 으로 채운다(StatsPage.tsx:2085-2121, D12). 오늘까지만.
  • 이중 축 — 수입 0 ~ 400만 · 지출 0 ~ 40만, 눈금 글자가 계열 색이다(웹 StatsPage.tsx:2268-2295 · 앱 stats_screen.dart useDualAxis, D13). 그대로 두고, 툴팁 · 지표 타일이 두 값을 숫자로 보이게 한다.
  • 음수 축 글자가 잘린다 — 자산 순자산 차트 세로축 "−3,000만" · "−2,000만" 이 SVG 밖으로 7px(−1,000만 4px) 나가 빼기가 안 보인다(pages/asset/ui/AssetPage.tsx:151-235 — YAxis 폭, D6).
  • 돈을 줄여 쓴다 · 빼기 두 벌 — 통계 도넛 가운데 "73.3만" · 자산 도넛 가운데 "−2,637.2만"(formatChartAxis — StatsPage.tsx:1366 · AssetPage.tsx:366, 앱은 홈 · 통계 도넛 가운데 — dashboard_screen.dart:1103 · stats_screen.dart:1318), 순자산 툴팁 "-26,140,000원" 은 ASCII 빼기(축은 "−")다(D22). 가운데 · 툴팁은 원까지, U+2212 하나로.
  • 범례 · 툴팁 — 세 제품 모두 HTML 손 범례다. 웹 도넛 범례 금액에 "원" 이 없다(.cat-legend), HR 은 점 범례다. 툴팁은 웹 모서리 12 · 테두리 1px · shadow-md, HR 8 · 테두리, 앱은 터치 자리 옆 12(shared/widgets/p_chart_tooltip.dart)다(D30). 선 · 막대는 지표 타일, 도넛은 목록 범례, 툴팁은 떠 있는 표면으로.
  • 열지도 흰 글자 2.88 · 줄인 돈 · 줄어드는 글자 — 라이트 55% 칸 위 흰 글자 2.88 · 다크 3.54 다(StatsPage.tsx:202-221). 칸 값은 축 줄임 함수로 "3.5만" 이고(heatCellLabel → formatChartAxis — StatsPage.tsx:1770 · 앱 stats_screen.dart:1792), 글자 수에 따라 데스크톱 11.5 → 10 · 폰 10 → 9 → 8 로 줄인다(StatsPage.tsx:1772-1780, 앱은 FittedBox 로 줄인다 — stats_screen.dart:1720). 칸 이름 · 원까지의 값은 title 에만 있어 터치로는 못 본다(StatsPage.tsx:1784-1788, D17). 웹만 가장 큰 칸에 2px 고리를 두르고 앱에는 없다(StatsPage.tsx:1801-1803) — 고리 색(--fg-brand-strong)과 칸 색(--border-brand)이 둘 다 --color-primary 라 고리는 칸에 묻히고 바깥 25% 띠만 보인다. 고리는 걷는다. 단계마다 글자색을 정하고, 칸 폭 112 이상에서만 원까지(11 · 700 — 오늘 1280 이상), 좁은 칸은 세기 색만 + 툴팁 · 표로 보기로 옮긴다.
  • 다크 브랜드 채움 1.73 — 예산 이번 달 막대 · 자산 구성의 투자 조각이 다크 bg-brand-solid(#1049A4)라 카드 면 대비 1.73 이다(BudgetPage.tsx:1195-1200 · AssetPage.tsx:423, D19). 계열은 차트 10색에서 고른다.
  • 같은 화면의 다른 파랑 — 홈 수입 숫자는 브랜드 #0147AD, 수입 막대는 #1D6EC9 다(DashboardPage.tsx:237-240 · 1278-1290, D31). 수입은 chart-blue 하나로.
  • 빈 · 실패 — 홈 막대 차트가 비면 축 0 ~ 1 만 남고, 도넛은 회색 고리 + "카테고리 데이터가 없습니다"(데스크톱) / "…없어요"(폰) 두 문체, 통계 · 예산은 실패도 빈 상태로 보인다(D2 · D28). HR 은 합쇼체 빈 상태. Result Section 으로.
  • HR 차트 두 개 — 유형 도넛 가운데 두 줄이 붙고(위 글 아래 끝 · 아래 글 위 끝 거의 0), 월 막대 축(시간)과 툴팁(일)의 단위가 다르며 "월" 이 코드에 박혔다(VacationTypeStatsContent.tsx:150-185 · MonthVacationStatsContent.tsx:56-87, D24).
  • 쓰지 않는 것 — 웹 손 SVG LineChart · BarChart(shared/ui/groo/charts.tsx:89-569)는 쓰는 곳이 0 이다(D29). chart-palette.ts 머리 주석의 "base hex" 가 옛 값이다(shared/lib/groo/chart-palette.ts:1-13, D32).

이 페이지