# PillTabs

알약 모양의 탭 모음이다. 하나를 고르면 그 칸이 짙은 색(네이비, 다크 모드는 주색)으로 채워진다.

- 분류: 입력과 선택
- 가져오기: `import { PillTabs } from '@/ui/controls'`
- 코드 위치: `apps/mobile/src/ui/controls.tsx:13` (Mordy 저장소 60df633)
- 웹 페이지: https://developers.moring.co/tds/components/pill-tabs

## 미리보기

실제 컴포넌트를 그린 화면은 https://developers.moring.co/tds/components/pill-tabs 에서 볼 수 있다. 서비스 색 선택기로 Mordy, Morit 색을 바꿔 볼 수 있다.

## 언제 쓰는가

### 쓴다
- 한 화면 안에서 같은 종류의 내용을 2~4개로 나눠 보여 줄 때 쓴다. 예: 리포트의 "하루 · 주 · 월".
- 카드나 시트 안의 작은 선택에는 `size="sm"`을 쓴다.
- 탭이 5개 이상이면 `scroll`을 켜서 옆으로 밀어 보게 한다.

### 쓰지 않는다
- 페이지를 이동하는 데 쓰지 않는다. 화면 간 이동은 `TabBar`다.
- 설정 값을 켜고 끄는 데 쓰지 않는다. `SettingsSwitch`를 쓴다.
- 탭 이름을 6글자 넘게 쓰지 않는다. 칸이 좁아진다.

## 종류

| 이름 | 설명 |
| --- | --- |
| md (기본) | 페이지의 탭. 칸 높이 42, 글자 `bodyStrong`. |
| sm | 카드, 시트, 설정 안의 탭. 칸 높이 36, 글자 `smallStrong`. |
| scroll | 탭이 많을 때. 칸 폭이 글자에 맞춰지고(좌우 16) 바탕 띠를 옆으로 민다. |

## 크기

| 이름 | 값 | 설명 |
| --- | --- | --- |
| md | 칸 42, 띠 안쪽 여백 4, 모서리 26 |  |
| sm | 칸 36, 띠 안쪽 여백 3, 모서리 21 |  |

## 상태

| 상태 | 모습과 동작 |
| --- | --- |
| 선택됨 | 칸이 `navy`(다크 모드는 `primary`)로 채워지고 글자는 흰색이다. 접근성 상태 `selected`. |
| 선택 안 됨 | 바탕은 `tabTrack`, 글자는 `textSecondary`. |
| 누름 | 선택이 바뀌는 순간 가벼운 선택 진동(`haptic.select`). 이미 선택된 칸을 눌러도 아무 일도 없다. |

## 사용 방법

### 기본

```tsx
import { PillTabs } from '@/ui/controls';

const [range, setRange] = useState<'day' | 'week' | 'month'>('day');

<PillTabs
  options={[
    { value: 'day', label: '하루' },
    { value: 'week', label: '주' },
    { value: 'month', label: '월' },
  ]}
  value={range}
  onChange={setRange}
/>
```

### 작은 크기와 옆으로 밀기

```tsx
<PillTabs size="sm" options={filters} value={filter} onChange={setFilter} />
<PillTabs scroll options={manyTabs} value={tab} onChange={setTab} />
```

### 속성(props)

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `options` | `{ value: T; label: string }[]` | — | 필수 | 탭 목록. 각 항목은 `{ value, label }`. `value`는 문자열이다. |
| `value` | `T` | — | 필수 | 지금 선택된 `value`. |
| `onChange` | `(v: T) => void` | — | 필수 | 다른 칸을 눌렀을 때 새 `value`와 함께 호출된다. |
| `size` | `'md' \| 'sm'` | `'md'` | 선택 | `"md"`(기본) 또는 `"sm"`. |
| `scroll` | `boolean` | — | 선택 | `true`이면 칸 폭이 글자에 맞춰지고 띠를 옆으로 밀 수 있다. |

## 치수와 토큰

| 항목 | 값 |
| --- | --- |
| 띠(바탕) | `tabTrack` 배경, md는 안쪽 여백 4·모서리 26, sm은 3·21 |
| 칸 | md 높이 42·모서리 21, sm 높이 36·모서리 18, 좌우 6 (scroll은 16) |
| 선택된 칸 | `navy` 배경(다크는 `primary`), 글자 white |
| 글자 | md `bodyStrong`(15/22 SemiBold), sm `smallStrong`(13/19 SemiBold). 선택 안 된 글자 `textSecondary` |

## 접근성

- 띠의 역할은 `tablist`, 각 칸은 `tab`이고 상태 `selected`가 전달된다.
- 칸 높이가 42 또는 36이라 눌리는 영역이 48 미만이다. 위아래 여백을 6 이상 두어 눌림을 돕는다.
- 선택은 색(채움)과 글자 색 변화로 나타낸다. 다크 모드에서도 글자(흰색)와 채움이 함께 바뀐다.
- 앱은 터치 화면이라 마우스 올림(hover)이 없다. 웹에서는 포커스 링(2.5px 실선, 바깥 3px)을 직접 그린다. 이 문서의 미리보기에는 포커스 링이 그려져 있다.

### 글자 색 대비

| 쓰임 | 글자색 | 바탕 | Mordy 라이트 | Mordy 다크 | Morit 라이트 | Morit 다크 | 기준 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 선택된 칸 글자 (15px 굵게) | `white` | `navy` | 15.61:1 통과 | 1.24:1 미달 | 11.97:1 통과 | 1.35:1 미달 | 4.5:1 |
| 선택 안 된 글자 (15px 굵게) | `textSecondary` | `tabTrack` | 3.60:1 미달 | 6.42:1 통과 | 4.13:1 미달 | 6.26:1 통과 | 4.5:1 |

## 잘한 예와 잘못한 예

- 잘한 예: 탭 이름을 짧게 쓰고 2~4개로 둔다.
- 잘못한 예: 이름이 길고 개수가 많으면 칸이 좁아져 글자가 잘린다. 이럴 때는 `scroll`을 켠다.

## 함께 보는 컴포넌트

- [TabBar](https://developers.moring.co/tds/components/tab-bar.md): Mordy 앱 맨 아래의 탭 줄이다. 홈 · 과목 · (+) · 커뮤니티 · 더보기. 가운데 +는 탭이 아니라 자료 추가 행동이다.
- [SettingsSwitch](https://developers.moring.co/tds/components/settings-switch.md): 켜고 끄는 스위치다. 설정 행의 오른쪽에 놓는다.
- [Chip](https://developers.moring.co/tds/components/chip.md): 짧은 글자를 담는 작은 알약 표지다. 상태, 분류, D-Day를 알린다. 눌리지 않는다.
