# Screen

모든 화면의 바탕이다. 안전 영역, 키보드, 스크롤, 좌우 여백, 아래 고정 영역을 한 번에 처리한다.

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

## 미리보기

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

## 언제 쓰는가

### 쓴다
- 모든 화면의 가장 바깥에 하나 쓴다.
- 아래에 고정할 주 행동은 `footer`에 넣는다. 키보드가 올라와도 가려지지 않는다.
- 목록을 끌어내려 새로고침하려면 `onRefresh`를 넘긴다.

### 쓰지 않는다
- `Screen`을 중첩하지 않는다.
- 안쪽에 또 `ScrollView`를 두지 않는다(스크롤이 겹친다). 자체 스크롤이 필요하면 `scroll={false}`.
- 화면 안에서 직접 좌우 여백을 또 넣지 않는다. `padded`가 20을 넣는다.

## 종류

| 이름 | 설명 |
| --- | --- |
| 스크롤 (기본) | `scroll`이 `true`다. 내용이 길면 스크롤된다. |
| 고정 | `scroll={false}`. 내용이 화면에 딱 맞는 화면(퀴즈, 촬영). |
| 회색 바탕 | `background={color.canvas}`. 대시보드형 화면(시험 계획, 리포트). |

## 크기

| 이름 | 값 | 설명 |
| --- | --- | --- |
| 전체 | 화면 전체 | 위쪽 안전 영역은 기본으로 적용(`edges=["top"]`). 아래는 `footer`가 처리한다. |

## 상태

| 상태 | 모습과 동작 |
| --- | --- |
| 새로고침 중 | `onRefresh`가 있고 아래로 끌었을 때만 스피너가 보인다. 백그라운드 갱신에서는 보이지 않는다. |
| 키보드 열림 | 아래쪽이 키보드 높이만큼 밀려 올라간다. |

## 사용 방법

### 기본

```tsx
import { Screen, TitleHeader } from '@/ui/layout';

<Screen>
  <TitleHeader title="내 과목" />
  {/* 내용 */}
</Screen>
```

### 아래 고정 버튼과 새로고침

```tsx
<Screen
  onRefresh={() => refetch()}
  footer={<PrimaryButton label="완료" arrow={false} height={56} onPress={done} />}
>
  {/* 내용 */}
</Screen>
```

### 회색 바탕

```tsx
<Screen background={color.canvas}>
  <Panel title="이번 주">{/* … */}</Panel>
</Screen>
```

### 속성(props)

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `children` | `ReactNode` | — | 필수 | 화면 내용. |
| `scroll` | `boolean` | `true` | 선택 | `true`(기본)면 세로로 스크롤된다. |
| `edges` | `Edge[]` | `['top']` | 선택 | 안전 영역을 적용할 가장자리. 기본 `["top"]`. |
| `padded` | `boolean` | `true` | 선택 | `true`(기본)면 좌우에 `space.gutter`(20)를 둔다. |
| `footer` | `ReactNode` | — | 선택 | 아래에 고정할 요소. 위 12, 아래 16, 좌우 20의 여백과 화면 배경색이 깔린다. |
| `background` | `string` | `color.bg` | 선택 | 바탕색. 기본 `color.bg`. |
| `onRefresh` | `() => Promise<unknown> \| void` | — | 선택 | 아래로 끌어 새로고침할 때 호출. 끝나면 스피너가 사라진다. |
| `contentStyle` | `StyleProp<ViewStyle>` | — | 선택 | 스크롤 내용(또는 고정 내용)에 적용할 스타일. |

## 치수와 토큰

| 항목 | 값 |
| --- | --- |
| 좌우 여백 | `space.gutter`(20) |
| 스크롤 아래 여백 | `space.xxl`(32) |
| 아래 고정 영역 | 위 `md`(12), 아래 `lg`(16), 좌우 `gutter`(20), 배경 `bg` |
| 바탕 | `bg` (회색 바탕이 필요하면 `canvas`) |
| 키보드 | `KeyboardAvoidingView` padding 방식 |

## 접근성

- 스크롤 막대는 숨기지만 스크롤은 된다.
- 입력 중 바깥을 눌러도 키보드가 먼저 닫히지 않고 눌림이 전달된다(`keyboardShouldPersistTaps="handled"`).

## 잘한 예와 잘못한 예

- 잘한 예: 주 행동을 `footer`에 두면 스크롤해도 항상 보인다.
- 잘못한 예: 내용 맨 아래에 주 버튼을 두면 긴 화면에서는 스크롤해야 보인다.

## 함께 보는 컴포넌트

- [TitleHeader](https://developers.moring.co/tds/components/title-header.md): 탭의 첫 화면 위쪽에 놓는 큰 제목 줄이다. 왼쪽에 제목, 오른쪽에 행동 자리가 있다.
- [BackHeader](https://developers.moring.co/tds/components/back-header.md): 화면 위쪽의 뒤로 가기 줄이다. 왼쪽에 뒤로 화살표, 가운데에 제목(선택), 오른쪽에 행동 자리가 있다.
- [Panel](https://developers.moring.co/tds/components/panel.md): 회색 바탕(`canvas`) 위에 놓는 흰 패널이다. 제목 줄(제목, 설명 아이콘, 오른쪽 링크)과 내용을 담는다. 리포트와 시험 계획 화면의 기본 면이다.
- [PrimaryButton](https://developers.moring.co/tds/components/primary-button.md): 서비스 주색 그라데이션으로 채운 알약 모양 버튼이다. 한 화면에서 가장 중요한 행동 하나에 쓴다.
