# OptionRow

퀴즈 보기 한 줄이다. 고르기 전, 고른 뒤, 채점 뒤(정답, 오답)의 모습이 정해져 있다.

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

## 미리보기

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

## 언제 쓰는가

### 쓴다
- 객관식 문제의 보기를 보여 줄 때 쓴다. 한 문제의 보기를 모두 `OptionRow`로 통일한다.
- 시험지처럼 번호(① ② …)를 붙이려면 `index`에 1부터 번호를 넘긴다.
- 채점 뒤에는 `state`를 `correct`(내가 고른 정답), `wrong`(내가 고른 오답), `answer`(내가 안 골랐지만 정답)로 바꾼다.

### 쓰지 않는다
- 여러 개를 동시에 고르는 선택에 쓰지 않는다. 이 컴포넌트의 접근성 역할은 하나만 고르는 `radio`다. 여러 개 선택은 `ChoiceCard`를 쓴다.
- 설정 목록에 쓰지 않는다. `SettingsRow`를 쓴다.

## 종류

| 이름 | 설명 |
| --- | --- |
| 기본 | 앞에 빈 동그라미 아이콘이 붙는다. |
| 번호(`index`) | 선택 전(`idle`)과 오답(`wrong`)일 때 동그라미 안에 번호가 들어간다. |

## 크기

| 이름 | 값 | 설명 |
| --- | --- | --- |
| 기본 | 최소 높이 48 | 글자가 길어지면 줄이 늘어나고 칸도 커진다. 좌우 14, 위아래 10. |

## 상태

| 상태 | 모습과 동작 |
| --- | --- |
| idle (기본) | `surface` 배경, 1px `line` 테두리. |
| selected | `primarySoft` 배경, 1.5px `primary` 테두리, 체크된 파란 원. |
| correct | `successSoft` 배경, 1.5px `success` 테두리, 체크된 초록 원. |
| wrong | `dangerSoft` 배경, 1.5px `danger` 테두리, `danger` 색 원. |
| answer | 내가 고르지 않은 정답. `correct`와 같은 모습. |
| 비활성 | `disabled`이면 눌러도 반응하지 않는다. 채점 뒤에 쓴다. |

## 사용 방법

### 기본

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

{choices.map((c, i) => (
  <OptionRow key={c.id} label={c.text} state={picked === c.id ? 'selected' : 'idle'} onPress={() => setPicked(c.id)} />
))}
```

### 채점 뒤

```tsx
const state = c.id === answer ? (picked === c.id ? 'correct' : 'answer') : picked === c.id ? 'wrong' : 'idle';

<OptionRow label={c.text} state={state} disabled index={i + 1} />
```

### 속성(props)

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `label` | `ReactNode` | — | 필수 | 보기의 내용. 글자(문자열)면 `body`로 그리고, 수식이나 그림을 넣으려면 요소를 넘긴다. |
| `state` | `OptionState` | — | 필수 | `"idle"`, `"selected"`, `"correct"`, `"wrong"`, `"answer"` 중 하나. |
| `onPress` | `() => void` | — | 선택 | 눌렀을 때 호출된다. |
| `disabled` | `boolean` | — | 선택 | `true`이면 눌러도 반응하지 않는다. |
| `index` | `number` | — | 선택 | 번호(1부터). 있으면 `idle`과 `wrong`일 때 동그라미 안에 번호를 그린다. |

## 치수와 토큰

| 항목 | 값 |
| --- | --- |
| 모양 | 최소 높이 48, 모서리 14, 좌우 14, 위아래 10, 아이콘과 글자 사이 12 |
| 테두리 | `idle` 1px, 그 밖에는 1.5px |
| 아이콘 | 20px. 선택·정답은 채운 원에 `surface` 색 체크, 번호 원은 22px에 선 1.4 |
| 글자 | `body` (15/22 Medium) |
| 누름 | 투명도 0.9 |

## 접근성

- 역할은 `radio`이고 상태 `selected`가 전달된다.
- 정답과 오답은 색(초록, 빨강)과 아이콘(체크 원, 빈 원), 번호 색으로 함께 나타낸다. 채점 결과 글자는 `FeedbackCard`가 따로 알린다.
- 앱은 터치 화면이라 마우스 올림(hover)이 없다. 웹에서는 포커스 링(2.5px 실선, 바깥 3px)을 직접 그린다. 이 문서의 미리보기에는 포커스 링이 그려져 있다.

### 글자 색 대비

| 쓰임 | 글자색 | 바탕 | Mordy 라이트 | Mordy 다크 | Morit 라이트 | Morit 다크 | 기준 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 보기 글자 | `text` | `surface` | 17.15:1 통과 | 15.25:1 통과 | 16.13:1 통과 | 10.92:1 통과 | 4.5:1 |
| 선택된 보기 글자 | `text` | `primarySoft` | 15.05:1 통과 | 12.52:1 통과 | 15.09:1 통과 | 7.13:1 통과 | 4.5:1 |
| 정답 보기 글자 | `text` | `successSoft` | 15.74:1 통과 | 13.64:1 통과 | 15.09:1 통과 | 7.13:1 통과 | 4.5:1 |
| 오답 보기 글자 | `text` | `dangerSoft` | 15.42:1 통과 | 14.27:1 통과 | 14.99:1 통과 | 8.34:1 통과 | 4.5:1 |

## 잘한 예와 잘못한 예

- 잘한 예: 선택한 보기는 주색으로, 채점 뒤의 정답은 초록으로 나눠 칠한다.
- 잘못한 예: 채점 전에 선택한 보기를 정답처럼 초록으로 칠하면 맞았다고 오해한다.

## 함께 보는 컴포넌트

- [ChoiceCard](https://developers.moring.co/tds/components/choice-card.md): 카드 모양의 선택지다. 고르면 테두리가 굵어지고 체크 표시가 붙는다. 온보딩의 과목·알림 선택에 쓴다.
- [ChoiceNumber](https://developers.moring.co/tds/components/choice-number.md): 숫자가 들어간 얇은 동그라미다. 시험지 보기 번호(① ② ③ ④ ⑤)를 그린다.
- [FeedbackCard](https://developers.moring.co/tds/components/feedback-card.md): 문제를 채점한 뒤 결과("정답!", "오답")와 해설을 보여 주는 카드다.
