# Calendar

한 달 달력에서 여러 날짜를 고르는 컴포넌트다. 시험 날짜를 고를 때 쓴다.

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

## 미리보기

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

## 언제 쓰는가

### 쓴다
- 시험일처럼 날짜를 여러 개 고를 때 쓴다. 이어진 날짜는 띠로 이어 보인다.
- 지난 날짜를 막으려면 `minDate`를 넘긴다.

### 쓰지 않는다
- 날짜 하나를 고르는 데 쓰지 않는다(Calendar 앱에서는 `pickDate` 시트를 쓴다).
- 날짜 사이의 범위를 끌어서 고르는 데 쓰지 않는다. 날짜를 하나씩 누른다.
- 주간 일정 표시에 쓰지 않는다. `WeekStrip`이나 Calendar 앱의 `MonthView`를 쓴다.

## 종류

종류가 없다.

## 크기

| 이름 | 값 | 설명 |
| --- | --- | --- |
| 기본 | 날짜 칸 높이 44, 날짜 원 36 | 폭은 부모를 채우고 7칸으로 나눈다. |

## 상태

| 상태 | 모습과 동작 |
| --- | --- |
| 선택 안 됨 | 글자 `text`. |
| 선택됨 | `primarySoft` 원, `primary` 굵은 글자. 이어진 날짜는 `primarySoft` 띠로 연결. |
| 첫 선택일 | 가장 이른 선택 날짜는 `primary` 채운 원에 흰 글자. |
| 오늘 | `primary` 굵은 글자. |
| 비활성 | `minDate`보다 이르거나 이번 달이 아닌 칸. `textTertiary`, 누를 수 없다. |

## 사용 방법

### 기본

```tsx
import { Calendar } from '@/ui/Calendar';

const [days, setDays] = useState<string[]>([]);

<Calendar
  selected={days}
  onToggle={(d) => setDays((cur) => (cur.includes(d) ? cur.filter((x) => x !== d) : [...cur, d]))}
  minDate={today}
/>
```

### 속성(props)

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `selected` | `string[]` | — | 필수 | 선택된 날짜 목록. `"YYYY-MM-DD"` 문자열. |
| `onToggle` | `(date: string) => void` | — | 필수 | 날짜를 눌렀을 때 그 날짜와 함께 호출된다. 선택과 해제를 부모가 정한다. |
| `minDate` | `string` | — | 선택 | 이 날짜보다 이른 날짜와 그 이전 달 이동을 막는다. |
| `initialMonth` | `string` | — | 선택 | 처음 보여 줄 달의 아무 날짜. 없으면 가장 이른 선택 날짜, 그것도 없으면 오늘의 달. |

## 치수와 토큰

| 항목 | 값 |
| --- | --- |
| 머리 | 이전 달·다음 달 버튼 36 × 36, 가운데 "YYYY년 M월"(`headline`) |
| 요일 줄 | 높이 34, `small`, `textTertiary`. 일요일부터 시작 |
| 날짜 칸 | 높이 44, 날짜 원 36, 글자 15/20 Medium(선택·오늘은 Bold) |
| 띠 | 위아래 4씩 안쪽, `primarySoft` |
| 줄 수 | 5줄 또는 6줄(달에 따라) |

## 접근성

- 각 날짜는 `button`이고 선택 상태가 전달된다. 비활성 날짜는 `disabled`.
- 이전·다음 달 버튼의 이름은 "이전 달", "다음 달"이다.
- 선택은 채움 색과 굵은 글자로 나타낸다.
- 앱은 터치 화면이라 마우스 올림(hover)이 없다. 웹에서는 포커스 링(2.5px 실선, 바깥 3px)을 직접 그린다. 이 문서의 미리보기에는 포커스 링이 그려져 있다.

### 글자 색 대비

| 쓰임 | 글자색 | 바탕 | Mordy 라이트 | Mordy 다크 | Morit 라이트 | Morit 다크 | 기준 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 선택된 날짜 글자 | `primary` | `primarySoft` | 3.45:1 미달 | 4.32:1 미달 | 4.21:1 미달 | 4.68:1 통과 | 4.5:1 |
| 첫 선택일 글자 | `onPrimary` | `primary` | 3.93:1 미달 | 3.31:1 미달 | 4.60:1 통과 | 7.25:1 통과 | 4.5:1 |
| 비활성 날짜 | `textTertiary` | `surface` | 2.53:1 미달 | 3.50:1 미달 | 2.97:1 미달 | 4.45:1 미달 | 4.5:1 |

## 잘한 예와 잘못한 예

- 잘한 예: `minDate`로 지난 날짜를 막는다.
- 잘못한 예: 선택한 날짜를 알 수 없게 아무 표시도 없으면 안 된다.

## 함께 보는 컴포넌트

- [TimeSheet](https://developers.moring.co/tds/components/time-sheet.md): 아래에서 올라오는 시트에서 시각을 고른다. 오전/오후, 시, 분(5분 단위) 세 줄 바퀴를 돌려서 고른다.
- [WeekStrip](https://developers.moring.co/tds/components/week-strip.md): 월요일부터 일요일까지 7일을 한 줄로 보여 주는 주간 표시다. 공부한 날에는 점이 찍힌다.
- [RangeSlider](https://developers.moring.co/tds/components/range-slider.md): 손잡이 두 개로 정수 범위(시작~끝)를 고르는 슬라이더다. PDF 페이지 범위를 고를 때 쓴다.
