Stat
아이콘·수치·라벨로 이루어진 요약 타일 컴포넌트
개요
Stat 컴포넌트는 아이콘과 수치, 라벨을 한 타일로 보여 줍니다. 값은 prop으로 주고, 세부 설정이 필요하면 부품(Stat.Icon, Stat.Value, Stat.Label)을 요소로 넘깁니다.
주요 특징
- ✅ 값 또는 요소:
icon·value·label에 문자열·숫자를 주면 부품으로 감싸고, 요소를 주면 그대로 배치 - ✅ 아이콘 위치:
top·bottom·left·right(기본right) - ✅ 내용 정렬:
contentAlign으로start·center·end - ✅ 부품:
Stat.Icon(변형·크기),Stat.Value(천 단위 구분),Stat.Label - ✅ 클릭 가능:
onClick을 주면role="button"과 Enter·Space 동작을 제공 - ✅ 접근성: 포커스 링, 아이콘
aria-hidden/aria-label, DOM 순서 아이콘 → 라벨 → 수치
기본 사용
아이콘·수치·라벨을 prop으로 주어 타일을 렌더링합니다.
Preview
icon에 요소를 주면 그대로 배치되므로 배경(원)이 없습니다. 아이콘 요소에 배경이 필요하면 Stat.Icon으로 감쌉니다.
문자열 아이콘
문자열·숫자 icon은 자동으로 Stat.Icon으로 감쌉니다.
Preview
아이콘 위치
iconPosition으로 아이콘을 내용의 위·아래·왼쪽·오른쪽에 둡니다. top·bottom은 세로 배치, left·right는 가로 배치입니다.
Preview
부품으로 세부 설정
Stat.Icon의 variant·size, Stat.Value의 thousandSeparator처럼 세부 설정은 부품을 요소로 넘겨 정합니다. 부품은 Stat 안에서만 사용합니다. 토큰이 Stat 루트에 걸려 있기 때문입니다.
Preview
크기 단계(sm md lg xl) 밖의 아이콘 크기가 필요하면 루트 또는 Stat.Icon의 className에서 --icon-size를 덮습니다. 가로 배치(left·right)에서 아이콘 영역이 차지하는 비율(기본 37.5%)은 루트 className에서 --ratio로 덮습니다. top·bottom에서는 --ratio를 쓰지 않습니다.
긴 수치
수치는 내용 영역 폭을 넘으면 줄임표로 잘리고, 접미어는 항상 보입니다. 자동 툴팁은 없으므로 전체 값을 보여 주려면 Stat.Value에 title을 직접 넘깁니다.
Preview
줄바꿈으로 전체 값을 보여 주려면 Stat.Value의 className에 whitespace-normal break-all을 줍니다.
내용 정렬
contentAlign을 주지 않으면 아이콘 위치에서 정합니다. left는 start, right는 end, top·bottom은 center입니다.
Preview
클릭
onClick을 주면 role="button", Enter·Space 동작, 포인터 커서가 붙습니다. 클릭하면 MouseEvent, Enter·Space로 활성화하면 KeyboardEvent가 전달됩니다.
Preview
API Reference
Stat Props
| Prop | Type | Default | Description |
|---|---|---|---|
icon | string | number | ReactElement | - | 문자열·숫자는 Stat.Icon으로 감싸고, 요소는 그대로 배치 |
iconPosition | "top" | "bottom" | "left" | "right" | "right" | 아이콘 배치 위치 |
value | string | number | ReactElement | - | 문자열·숫자는 Stat.Value로 감싸고, 요소는 그대로 배치 |
label | string | ReactElement | - | 문자열은 Stat.Label로 감싸고, 요소는 그대로 배치 |
suffix | string | - | 수치 뒤 접미어 (문자열·숫자 value에만 적용) |
contentAlign | "start" | "center" | "end" | 아이콘 위치에서 결정 | 내용 영역 가로 정렬 |
children | ReactNode | - | label·value 아래에 이어서 배치할 추가 내용 |
onClick | (e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>) => void | - | 지정 시 role="button"·Enter·Space 동작·포인터 커서 부여. 키보드 활성화는 KeyboardEvent 전달 |
className | string | - | 컨테이너 CSS 클래스 (--ratio, --icon-size 덮어쓰기 가능) |
style | React.CSSProperties | - | 인라인 스타일 |
그 밖의 HTML 속성과 ref를 그대로 받습니다.
Stat.Icon Props
| Prop | Type | Default | Description |
|---|---|---|---|
icon | ReactNode | - | 표시할 아이콘 |
variant | "default" | "ghost" | "default" | 배경 변형 (default 배경 있는 원, ghost 배경 없음) |
size | "sm" | "md" | "lg" | "xl" | "md" | 컨테이너 크기 단계 (3rem · 4.5rem · 6rem · 8rem) |
aria-label | string | - | 접근성 이름. 지정 시 role="img" 부여와 장식 숨김 해제 |
그 밖의 HTML 속성과 ref를 그대로 받습니다.
Stat.Value Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | number | - | 표시할 수치 |
suffix | string | - | 수치 뒤 접미어 (예: “건”, “원”) |
thousandSeparator | boolean | false | 정수부 천 단위 콤마 여부 (소수부·부호·뒤따르는 글자는 유지) |
title | string | - | HTML 속성 그대로 전달. 자동 툴팁 없음, 잘린 수치의 전체 값 표시용 |
그 밖의 HTML 속성과 ref를 그대로 받습니다.
Stat.Label Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | - | 표시할 라벨 |
title | string | - | HTML 속성 그대로 전달. 라벨 문구 자동 복제 없음 |
그 밖의 HTML 속성과 ref를 그대로 받습니다.
토큰
루트 data-token="stat" 한 블록입니다. 부품에는 data-token이 없고 루트 값을 상속합니다.
| Token | 설명 |
|---|---|
--stat-icon-background | 아이콘 원 배경색 |
--stat-value-font-size | 수치 글자 크기 |
--stat-value-font-weight | 수치 글자 굵기 |
--stat-value-suffix-font-size | 수치 접미어 글자 크기 |
--stat-label-font-size | 라벨 글자 크기 |
--stat-label-font-weight | 라벨 글자 굵기 |
--stat-label-foreground | 라벨 글자색 |
수치 글자색 토큰은 없습니다. 수치는 부모의 글자색을 상속합니다.
--ratio와 --icon-size는 토큰이 아니라 className으로 덮는 변수입니다. 토큰 시트에 두지 않습니다.
접근성
권장 사항
- ✅
onClick이 있으면role="button",tabIndex, Enter·Space 키 동작을 제공 - ✅ 소비자가 넘긴
role·tabIndex·onKeyDown은 유지 - ✅ 키보드 포커스 시
focus-visible링 표시 - ✅ 장식용 아이콘은
aria-hidden, 의미가 있으면Stat.Icon의aria-label로 접근성 이름 제공 - ✅ DOM 순서는 아이콘 → 라벨 → 수치
- ✅ 잘린 수치의 전체 값은 소비자가 넘긴
title로만 표시 (마우스 보조, 스크린리더는 DOM 전체 텍스트를 읽음). 잘리면 안 되는 곳은 줄바꿈(whitespace-normal break-all) 사용 - ❌ 클릭 가능한
Stat안에 버튼·링크 같은 상호작용 요소를 넣지 않기