# TimeGrid

주·일 보기의 24시간 시간표다. 일정 블록을 길게 눌러 끌면 시간(15분 단위)과 날짜가 바뀌고, 빈 칸을 누르면 그 시각에 추가한다.

- 분류: Calendar 앱
- 가져오기: `import { TimeGrid } from '@/cal/TimeGrid'`
- 코드 위치: `apps/calendar/src/cal/TimeGrid.tsx:25` (Mordy 저장소 60df633)
- 웹 페이지: https://developers.moring.co/tds/components/time-grid

## 미리보기

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

## 언제 쓰는가

### 쓴다
- 이 컴포넌트는 Mordy Calendar 앱(`apps/calendar/src/cal`)에만 있다.
- 캘린더 탭의 주 보기와 일 보기에 쓴다. 날짜 목록(`days`)이 1개면 일 보기, 7개면 주 보기다.
- 시간이 없는 할 일은 위쪽 띠에 칩으로 놓인다. 끌어서 그 띠에 놓으면 시간 없음으로 바뀐다.

### 쓰지 않는다
- 한 달을 보는 데 쓰지 않는다. `MonthView`를 쓴다.
- 끌기만으로 옮길 수 있게 두지 않는다. 일정 편집 화면에서도 시간을 바꿀 수 있어야 한다.

## 종류

| 이름 | 설명 |
| --- | --- |
| 일 보기 | `days`가 1개. |
| 주 보기 | `days`가 7개. 옆으로 날짜를 바꿀 수 있다. |

## 크기

| 이름 | 값 | 설명 |
| --- | --- | --- |
| 기본 | 시각 줄 높이 44, 왼쪽 시각 영역 50 | 끌기 단위 15분. 일정 길이를 모르면 할 일 30분, 일정 60분으로 그린다. |

## 상태

| 상태 | 모습과 동작 |
| --- | --- |
| 끌기 시작 | 길게 누르면 중간 세기 진동(`haptic.firm`)과 함께 블록이 떠오르고 `shadow(3)`가 붙는다. 원래 자리는 투명도 0.3. |
| 놓음 | 새 시각이 `onMove`로 전달된다. 위 띠에 놓으면 `time`이 `null`이다. |
| 빈 칸 누름 | `onAdd(날짜, 시각)`이 호출된다. |

## 사용 방법

### 기본

```tsx
import { TimeGrid } from '@/cal/TimeGrid';

<TimeGrid days={week} today={today} data={range.data} showPlan={prefs.showPlan}
  onOpen={(e) => openItem(e)}
  onAdd={(day, time) => openQuickAdd({ date: day, time })}
  onMove={(e, day, time) => move(e, day, time)} />
```

### 속성(props)

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `days` | `string[]` | — | 필수 | 보여 줄 날짜 목록(`"YYYY-MM-DD"`). 1개(일) 또는 7개(주). |
| `today` | `string` | — | 필수 | 오늘 날짜. |
| `data` | `Range \| undefined` | — | 필수 | 해당 기간의 항목. 불러오는 중이면 `undefined`. |
| `showPlan` | `boolean` | — | 필수 | Mordy 계획 블록을 보일지. |
| `onOpen` | `(e: { item?: CalItem; plan?: PlanItem }) => void` | — | 필수 | 블록이나 칩을 눌렀을 때 호출된다. |
| `onAdd` | `(day: string, time: string) => void` | — | 필수 | 빈 칸을 눌렀을 때 날짜와 시각(15분 단위)과 함께 호출된다. |
| `onMove` | `(e: { item?: CalItem; plan?: PlanItem }, day: string, time: string \| null) => void` | — | 필수 | 끌어서 놓았을 때 새 날짜와 시각(`null`이면 시간 없음)과 함께 호출된다. |

## 치수와 토큰

| 항목 | 값 |
| --- | --- |
| 시각 줄 | 높이 44, 위쪽 1px `line` |
| 블록 | 모서리 6, 왼쪽 3px 과목 색 테두리, 바탕 과목 색 15%, 글자 11.5/15 SemiBold |
| 끌기 | 15분 단위(`SNAP`), 좌우로는 날짜 이동 |
| 시각 영역 | 폭 50 |

## 접근성

- 끌기는 제스처다. 대체 방법으로 블록을 눌러 일정 편집 화면에서 시간을 바꿀 수 있다.
- 시각 글자는 `caption`, 블록 글자는 11.5px로 작다. 일정 상세는 눌러서 편집 화면에서 읽는다.

### 글자 색 대비

| 쓰임 | 글자색 | 바탕 | Mordy 라이트 | Mordy 다크 | Morit 라이트 | Morit 다크 | 기준 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 블록 글자 (11.5px 굵게) | `text` | `surface` | 17.15:1 통과 | 15.25:1 통과 | 16.13:1 통과 | 10.92:1 통과 | 4.5:1 |

## 잘한 예와 잘못한 예

- 잘한 예: 끌어서 옮기는 일은 일정 편집 화면에서도 할 수 있게 한다.
- 잘못한 예: 끌기만 시간을 바꾸는 유일한 방법으로 두지 않는다.

## 함께 보는 컴포넌트

- [MonthView](https://developers.moring.co/tds/components/month-view.md): 한 달을 화면 가득 보여 주는 달력이다. 날마다 칩(시험 먼저, 시간 있는 일정, 나머지)을 줄에 들어가는 만큼 보이고 넘치면 "+n"으로 줄인다.
- [DayStrip](https://developers.moring.co/tds/components/day-strip.md): 한 주 7일을 한 줄로 보여 주고 날짜를 골라 이동하는 주간 줄이다. 좌우로 밀면 앞뒤 주로 이동한다. 일정이 있는 날에는 점이 찍힌다.
- [ItemRow](https://developers.moring.co/tds/components/item-row.md): 오늘과 할 일 목록의 한 줄이다. 할 일은 앞에 체크 원, 일정은 앞에 시간과 색 막대가 있다.
