# Panel

회색 바탕(`canvas`) 위에 놓는 흰 패널이다. 제목 줄(제목, 설명 아이콘, 오른쪽 링크)과 내용을 담는다. 리포트와 시험 계획 화면의 기본 면이다.

- 분류: 면과 목록
- 가져오기: `import { Panel, PanelHead, PanelLink } from '@/ui/surface'`
- 코드 위치: `apps/mobile/src/ui/surface.tsx:21` (Mordy 저장소 60df633)
- 웹 페이지: https://developers.moring.co/tds/components/panel

## 미리보기

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

## 언제 쓰는가

### 쓴다
- 리포트, 시험 계획 같은 대시보드 화면에서 내용을 묶는 흰 면으로 쓴다.
- 제목 줄 오른쪽에는 `PanelLink`("전체보기 ›")나 토글을 둔다.
- 제목 옆 설명(ⓘ)이 필요하면 `info`에 `[제목, 설명]`을 넘긴다. 누르면 대화상자가 뜬다.

### 쓰지 않는다
- 흰 배경 화면(`bg`) 위에서 구분 없이 쓰지 않는다. 패널은 `canvas` 위에서 보인다.
- 패널 안에 패널을 넣지 않는다. 안의 묶음은 `WellRow`로 나눈다.
- 제목 줄 오른쪽에 요소를 둘 넘게 두지 않는다.

## 종류

| 이름 | 설명 |
| --- | --- |
| Panel | 흰 패널. 제목(`title`)을 주면 제목 줄이 생긴다. |
| PanelHead | 제목 줄만 따로 쓴다. 패널 밖에서 같은 모양의 제목이 필요할 때. |
| PanelLink | "전체보기 ›" 모양의 작은 링크. |

## 크기

| 이름 | 값 | 설명 |
| --- | --- | --- |
| 기본 | 안쪽 여백 18, 모서리 22 | 제목 줄 아래 간격 14. 좁은 화면(글자 배율 반영 폭 370 미만)에서는 `link`가 패널 맨 아래로 옮겨 간다. |

## 상태

| 상태 | 모습과 동작 |
| --- | --- |
| 기본 | `surface` 바탕, 그림자 `shadow(1)`. 다크 모드에서는 그림자 대신 1px `cardBorder` 테두리. |
| 누르는 패널 | `onPress`가 있으면 버튼이 되고 눌렀을 때 투명도 0.88. |

## 사용 방법

### 기본

```tsx
import { Panel, PanelLink, WellRow } from '@/ui/surface';

<Screen background={color.canvas}>
  <Panel title="이번 주 학습" info={['이번 주 학습', '월요일부터 오늘까지 문제를 푼 시간이에요.']} link={<PanelLink label="전체보기" onPress={openReport} />}>
    <WellRow title="수학" meta="3시간 20분" />
  </Panel>
</Screen>
```

### 속성(props)

#### Panel

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `children` | `ReactNode` | — | 선택 | 패널 안의 내용. |
| `style` | `StyleProp<ViewStyle>` | — | 선택 | 바깥 여백이나 배치만 바꾸는 React Native 스타일이다. |
| `title` | `string` | — | 선택 | 제목. 있으면 제목 줄이 생긴다. |
| `info` | `[string, string]` | — | 선택 | 제목 옆 ⓘ 설명. `[제목, 설명]`. 누르면 대화상자가 뜬다. |
| `right` | `ReactNode` | — | 선택 | 제목 줄 오른쪽 요소. `link`보다 우선한다. |
| `link` | `ReactNode` | — | 선택 | 제목 줄 오른쪽 링크. 좁은 화면에서는 패널 아래로 옮겨 간다. |
| `onPress` | `() => void` | — | 선택 | 있으면 패널 전체가 버튼이 된다. |
| `accessibilityLabel` | `string` | — | 선택 | 누르는 패널의 이름. |

#### PanelHead

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `title` | `string` | — | 필수 | 제목(`headline` 18, 한 줄). |
| `info` | `[string, string]` | — | 선택 | 제목 옆 ⓘ 설명 `[제목, 설명]`. |
| `right` | `ReactNode` | — | 선택 | 오른쪽 요소. |
| `below` | `boolean` | — | 선택 | `true`이면 오른쪽 요소를 제목 아래로 내린다(좁은 화면). |
| `style` | `StyleProp<ViewStyle>` | — | 선택 | 바깥 여백이나 배치만 바꾸는 React Native 스타일이다. |

#### PanelLink

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `label` | `string` | — | 필수 | 링크 글자. |
| `onPress` | `() => void` | — | 필수 | 눌렀을 때 실행할 함수. |

## 치수와 토큰

| 항목 | 값 |
| --- | --- |
| 패널 | `surface` 바탕, 모서리 22, 안쪽 여백 18, `shadow(1)`(다크는 1px `cardBorder`) |
| 제목 줄 | 제목 `headline` 18 Bold, 아래 간격 14, ⓘ 17px(`textTertiary`) |
| PanelLink | `small` `textSecondary`, ChevronRight 15 선 2.3 |
| 좁은 화면 | 글자 배율을 반영한 화면 폭이 370 미만이면 링크를 패널 아래(위 구분선)로 옮긴다 |

## 접근성

- 제목은 `header` 역할이다. ⓘ 버튼의 이름은 "{제목} 설명"이다.
- `onPress`가 있으면 패널 전체가 `button` 역할이다.
- PanelLink는 `button`이고 눌리는 영역이 사방 8 넓다.

### 글자 색 대비

| 쓰임 | 글자색 | 바탕 | Mordy 라이트 | Mordy 다크 | Morit 라이트 | Morit 다크 | 기준 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 패널 위 본문 | `text` | `surface` | 17.15:1 통과 | 15.25:1 통과 | 16.13:1 통과 | 10.92:1 통과 | 4.5:1 |
| PanelLink 글자 (13px) | `textSecondary` | `surface` | 4.23:1 미달 | 6.95:1 통과 | 4.88:1 통과 | 7.11:1 통과 | 4.5:1 |

## 잘한 예와 잘못한 예

- 잘한 예: `canvas` 위에 패널을 놓고, 안의 묶음은 홈(`WellRow`)으로 나눈다.
- 잘못한 예: 패널 안에 패널을 넣지 않는다.

## 함께 보는 컴포넌트

- [Card](https://developers.moring.co/tds/components/card.md): 옅은 주색 틴트(`card`)를 깐 둥근 상자다. 안내, 요약, 눌러서 이동하는 카드에 쓴다.
- [WellRow](https://developers.moring.co/tds/components/well-row.md): 패널 안의 목록 한 줄이다. 옅은 홈(`well`)에 앞 아이콘 타일, 제목, 보조 줄, 뒤 요소가 놓인다.
- [SectionTitle](https://developers.moring.co/tds/components/section-title.md): 화면 안의 한 묶음(섹션)을 시작하는 제목 줄이다. 위에 24, 아래에 12의 간격을 포함한다.
- [Screen](https://developers.moring.co/tds/components/screen.md): 모든 화면의 바탕이다. 안전 영역, 키보드, 스크롤, 좌우 여백, 아래 고정 영역을 한 번에 처리한다.
