# Chart 누적 막대 · 가로 막대 · 선 · 원형 네 형태를 같은 틀에 담은 차트입니다. > 원본: `03_ASSET_GUIDE/catalog/chart.js` · CSS: `03_ASSET_GUIDE/styles/elements/chart.css` > kind `component` · category `display` · status `stable` · specSource `measured` > 함께 쓰는 CSS: `chip.css` (차트/표 전환 칩) --- ## 1. 구성 네 형태 모두 **Header · Legend · Plot** 으로 구성됩니다. 형태마다 다른 것은 Plot 안의 마크입니다. ``` ┌─────────────────────────────────────────────┐ │ 월별 처리 건수 [차트][표] │ ① ② ③ │ 최근 7개월 · 단위 건 │ │ ■ 처리 완료 ■ 처리 중 ■ 반려 │ ④ │ 100 ┼──────────────────────────── 95 │ ⑤ ⑧ │ 50 ┼──────────█───█────────────── │ ⑥ ⑦ │ 0 ┴──█───█───█───█───█───█───█── │ │ 1월 2월 3월 4월 5월 6월 7월 │ └─────────────────────────────────────────────┘ ``` | # | 요소 | 필수 | 클래스 | 설명 | |---|---|---|---|---| | ① | Header | 필수 | `atom-chart__header` | 제목 블록과 전환 칩을 한 줄에 둡니다. | | ② | Title · Subtitle | 제목 필수 | `atom-chart__title` · `atom-chart__subtitle` | 제목과 부제입니다. 제목은 15px 이며 제목 단계를 쓰지 않습니다. 차트는 보통 [Section Title](./section-title.md) 아래에 놓이기 때문입니다. | | ③ | Toggle | 선택 | `atom-chart__toggle` | 표 뷰를 쓸 때 차트/표 전환 칩([Chip](./chip.md))을 담습니다. | | ④ | Legend | 시리즈 2개 이상 | `atom-chart__legend` · `__legend-item` · `__legend-swatch` · `__legend-label` | 시리즈가 둘 이상이면 **항상** 있습니다. 색은 스와치에만 쓰고 라벨은 텍스트 색으로 둡니다. | | ⑤ | Plot | 필수 | `atom-chart__plot` | 마크가 그려지는 SVG 상자입니다. 축 라벨 띠까지 포함해 높이를 잡습니다. | | ⑥ | Grid line · Axis · Axis label | 필수 | `atom-chart__grid-line` · `__axis` · `__axis-label` | 보조 요소입니다. 헤어라인 실선으로 약하게 표시합니다. | | ⑦ | Bar · Line · Marker · Slice | 필수 | `atom-chart__bar` · `__line` · `__area` · `__marker` · `__slice` | 데이터입니다. 화면에서 가장 강하게 표시됩니다. | | ⑧ | Value | 선택 | `atom-chart__value` (`--on-fill`) | 직접 라벨입니다. **선택적으로만** 답니다. | | — | Tooltip | 선택 | `atom-chart__tooltip` · `__tooltip-title` · `__tooltip-row` · `__tooltip-swatch` · `__tooltip-label` · `__tooltip-value` · `__crosshair` | 보조 수단입니다. 툴팁으로만 값을 확인할 수 있게 하지 않습니다. | | — | Table | 선택 | `atom-chart__table` | 같은 숫자를 표로. `data-view="table"` 일 때 Plot·Legend 대신 보입니다. | | — | Empty | 데이터 없을 때 | `atom-chart__empty` | 빈 상태 문구입니다. | --- ## 2. 종류 / 크기 ### Type 형태는 데이터의 용도에 따라 정하며, 색보다 먼저 정합니다. | type | 데이터의 일 | 참고한 샘플 | |---|---|---| | `bar` | 부분과 전체를 함께 — 합계와 구성 | [stacked](https://www.chartjs.org/docs/latest/samples/bar/stacked.html) | | `bar-horizontal` | 크기 비교. 항목 이름이 길 때 | [horizontal](https://www.chartjs.org/docs/latest/samples/bar/horizontal.html) | | `line` | 시간에 따른 추이 | [line](https://www.chartjs.org/docs/latest/samples/line/line.html) | | `pie` | 전체 대비 비율을 한눈에 | [pie](https://www.chartjs.org/docs/latest/samples/other-charts/pie.html) | #### 누적 막대 막대는 **22px** 입니다(상한 24px). 슬롯을 다 채우지 않고 남는 폭은 여백으로 둡니다. 데이터가 끝나는 쪽 모서리만 **4px** 로 둥글고 기준선 쪽은 각을 유지합니다. 기준선 쪽이 둥글면 막대의 시작점이 흐려지기 때문입니다. 세그먼트 사이는 **2px 서피스 갭**입니다. 세그먼트를 테두리로 나누지 않습니다. > [!NOTE] > **원본 샘플과 다른 점 — 음수를 쓰지 않았습니다** > chart.js 의 stacked 샘플은 -100~100 의 난수를 씁니다. 누적 막대는 **부분과 전체**를 > 보여주는데, 음수가 섞이면 전체 합계의 의미가 없어집니다. 기준선 위아래로 갈리는 > 데이터에는 발산(diverging) 막대를 씁니다. #### 가로 막대 항목 이름이 길면 눕힙니다. 세로로 두면 라벨이 기울어지거나 잘립니다. 두 시리즈가 나란히 놓일 때도 사이는 같은 **2px 갭**입니다. 값은 **첫 시리즈의 팁 바깥**에만 답니다. 막대 안에 넣으려면 글자가 좌우 여백을 두고 들어가야 하고, 짧은 막대에서는 그럴 자리가 없습니다. #### 선 선은 **2px**, 조인·캡은 라운드입니다. 마커는 **r=4**(지름 8px 하한)이고 **2px 서피스 링**을 두릅니다. 링은 선이 겹치는 자리에서도 점을 구분되게 하며, hover 히트 영역에 포함됩니다. 직접 라벨은 **끝점 두 개**에만 답니다. 점마다 숫자를 달지 않습니다. #### 원형 조각 사이도 2px 갭입니다. ### 시리즈 색 색은 `data-series` 하나로 결정됩니다. 슬롯 1–6 이고, [Color](../foundation/color.md) 의 `--atom-chart-series-1` … `-6` 을 읽습니다. > [!NOTE] > **임시 값입니다** > 시리즈 색 여섯 개는 확정되지 않은 임의의 값입니다. 디자인이 확정되면 바뀔 수 있습니다. | 시리즈 수 | 다루는 방법 | |---|---| | 1 | 범례 없음. 제목으로 내용을 나타냅니다 | | 2–6 | 슬롯 1 부터 순서대로 씁니다. 범례를 함께 둡니다 | | 7 이상 | 꼬리를 "기타" 로 묶거나 작은 배수(small multiples)로 나눕니다 | **색은 개체에 고정하며, 순위에 따라 바꾸지 않습니다.** 필터로 시리즈 하나가 빠져도 남은 시리즈의 색은 그대로 둡니다. ### 범례와 직접 라벨 범례는 **둘 이상이면 항상**, **하나면 없습니다.** 시리즈가 하나면 범례가 제목과 같은 내용이 되기 때문입니다. 직접 라벨은 범례를 **보조**하며, 대체하지 않습니다. 끝점, 극값, 강조할 시리즈 하나에만 답니다. ### 툴팁 선·영역에는 세로 크로스헤어 + 툴팁, 막대·조각에는 마크별 툴팁입니다. 막대는 마크 자체가 히트 영역이므로 크로스헤어를 두지 않습니다. 툴팁 안에서도 색은 스와치에만 쓰고 라벨은 텍스트 색으로 둡니다. ### 표 뷰 같은 숫자를 표로도 보여줘야 하는 화면에서 씁니다. **선택 사항이며, 필수나 권고가 아닙니다.** `view` 를 `"table"` 로 두면 Plot·Legend 대신 `atom-chart__table` 이 보입니다. 헤더에 전환 칩을 두면 사용자가 직접 오갈 수 있습니다. 숫자를 정확히 읽는 것이 화면의 주목적이라면 이 뷰 대신 [Grid](./grid.md) 를 씁니다. ### 빈 상태 데이터가 없으면 축과 격자만 남긴 빈 판을 그리지 않습니다. ### 클래스 계약 `styles/elements/chart.css` 헤더와 원본 `registry.json` `css.blocks` 기준입니다. Chart 는 modifier 클래스가 없고, 형태와 뷰를 **데이터 속성**으로 받습니다. (CSS 헤더: "for three of the four it changes nothing visually — the SVG inside is what differs — and a modifier that draws nothing is a promise the stylesheet does not keep") | Prop | 값 | 클래스 / 속성 | |---|---|---| | `type` | `bar` · `bar-horizontal` · `line` · `pie` | `[data-type="bar"]` · `[data-type="bar-horizontal"]` · `[data-type="line"]` · `[data-type="pie"]` (pie 만 Plot 을 가운데 정렬) | | `view` | `chart` · `table` | `[data-view="chart"]` · `[data-view="table"]` | | 시리즈 슬롯 | `1` – `6` | 마크·스와치·툴팁 행의 `[data-series="1…6"]` | | 채움 위 라벨 | — | `atom-chart__value--on-fill` (+ `[data-series]`) | 상태 선택자: `[data-type]` · `[data-view]` · `[data-series]` · `atom-chart__tooltip[data-state="closed"]` 로컬 커스텀 프로퍼티: `--atom-chart-ink` (내부 배관 — `[data-series]` 가 슬롯 색을 넣고 마크 규칙이 읽습니다. 토큰 아님) > [!WARNING] > **`--on-fill` 은 CSS 헤더 계약에 없습니다** > `.atom-chart__value--on-fill` 은 stylesheet 에 정의되어 있고 데모(원형 조각 안 비율)가 쓰지만, > 헤더 주석의 클래스 목록에는 빠져 있습니다 (registry `problems`: `css-defined-not-declared` — "on-fill — defined in the stylesheet, absent from the header comment"). --- ## 3. 상태 | 상태 | 표현 | 선택자 | |---|---|---| | chart 뷰 | Plot · Legend 표시, Table 숨김 | `[data-view="chart"]` | | table 뷰 | Table 표시, Plot · Legend 숨김 | `[data-view="table"]` | | 툴팁 열림 / 닫힘 | 닫히면 `display: none` | `atom-chart__tooltip[data-state="open"]` · `[data-state="closed"]` | | 빈 상태 | 축·격자 없이 `atom-chart__empty` 문구 | — | | 강제 색상 모드 | 막대·조각에 `CanvasText` 1px 외곽선, 선은 `CanvasText` | `@media (forced-colors: active)` | --- ## 4. Props | Prop | Type | Default | 필수 | 설명 | |---|---|---|---|---| | `type` | `"bar" \| "bar-horizontal" \| "line" \| "pie"` | `"bar"` | | 마크의 형태입니다. | | `series` | `Array<{ key, label, data: number[], slot? }>` | | ● | 시리즈입니다. `slot` 을 주면 그 색을 고정합니다. | | `categories` | `string[]` | | ● | x축(또는 가로 막대의 y축) 라벨입니다. | | `stacked` | `boolean` | `true` | | `bar` 계열에서 누적할지 나란히 놓을지입니다. | | `title` | `string` | | ● | 무엇을 그린 차트인지입니다. 시리즈가 하나면 이것이 유일한 이름입니다. | | `subtitle` | `string` | | | 기간·단위 같은 보충입니다. | | `valueLabels` | `"none" \| "end" \| "total" \| "all"` | `"end"` | | 직접 라벨의 범위입니다. `"all"` 은 안티패턴이라 문서화만 해 둡니다. | | `view` | `"chart" \| "table"` | `"chart"` | | 표 뷰를 쓸 때만 씁니다. 선택 사항입니다 — [표 뷰](#표-뷰). | | `yTicks` | `number[]` | 자동 | | y축 눈금입니다. 깔끔한 수로 떨어지게 잡습니다. | | `emptyText` | `string` | `"조회된 데이터가 없습니다"` | | 데이터가 없을 때 문구입니다. | | `onPointHover` | `(point) => void` | | | 툴팁을 밖에서 제어할 때 씁니다. | ### Parts (compound) | Part | 요소 | 설명 | |---|---|---| | `Chart` | `