# UI Design System — Samsung One UI

> 어떤 스택에서든 동일한 톤을 이식하기 위한 단일 소스. Samsung One UI 공개 디자인 가이드의 톤을 웹 이식용으로 재해석한 문서다.
>
> **한 줄 정의**: **한 손이 닿는 곳에 인터랙션을, 시선이 머무는 곳에 정보를.** 화면 상단 절반은 큰 제목과 여백(Viewing area), 하단 절반은 조작 영역(Interaction area)으로 나누고, 큰 라운드(16px+)의 화이트 카드와 블루(`#0381fe`) 액센트로 구성하는 대화면 모바일 시스템.

---

## 목차

1. [디자인 원칙](#1-디자인-원칙)
2. [색상 토큰](#2-색상-토큰)
3. [타이포그래피](#3-타이포그래피)
4. [레이아웃 & 라운드](#4-레이아웃--라운드)
5. [핵심 컴포넌트](#5-핵심-컴포넌트)
6. [인터랙션](#6-인터랙션)
7. [다크 모드](#7-다크-모드)
8. [접근성](#8-접근성)
9. [안티패턴](#9-안티패턴)
10. [프레임워크 어댑터](#10-프레임워크-어댑터)
11. [이식 가이드](#11-이식-가이드)

---

## 1. 디자인 원칙

| 원칙 | 정의 |
|---|---|
| **Viewing / Interaction 분리** | 대화면에서 정보는 위, 조작은 엄지가 닿는 아래에. 헤더 제목은 크고 아래로 내려온다. |
| **큰 라운드 카드** | 콘텐츠는 16~26px 라운드의 카드 단위로 묶는다. 카드 사이는 보더가 아닌 배경 대비로 구분. |
| **하나의 액센트** | 블루(`#0381fe`)가 유일한 액센트. 스위치·체크·링크·주 버튼에만 사용. |
| **차분한 뉴트럴** | 배경은 옅은 그레이(`#f6f6f6`), 카드가 흰색으로 떠오른다. 채도 있는 배경 금지. |
| **One Seamless Experience** | 폰·태블릿·워치·TV에서 같은 구조가 스케일만 바뀌어 이어진다. |
| **부드러운 피드백** | 전환·탭 피드백은 짧고 자연스럽게. 급격한 모션 금지. |

---

## 2. 색상 토큰

### 2-1. 기본 팔레트

```css
:root {
  --accent:        #0381fe;  /* One UI 블루 */
  --accent-press:  #026ee0;
  --accent-surface:#e8f2ff;  /* 선택·활성 옅은 면 */

  --bg:            #f6f6f6;  /* 페이지 배경 */
  --card:          #ffffff;  /* 카드 표면 */
  --text:          #252525;  /* 기본 텍스트 */
  --text-sub:      #8c8c8c;  /* 보조 텍스트 */
  --text-disabled: #c4c4c4;
  --divider:       #e6e6e6;  /* 카드 내부 구분선 */

  --danger:        #db332a;
  --success:       #1a9349;
  --warning:       #f5a623;
}
```

### 2-2. 사용 규칙

| 역할 | 토큰 |
|---|---|
| 본문·제목 | `var(--text)` |
| 보조 설명·설정값 | `var(--text-sub)` |
| 페이지 배경 | `var(--bg)` |
| 카드·리스트 그룹 | `var(--card)` |
| 카드 내부 구분선 | `var(--divider)` 1px |
| 스위치 ON·주 버튼·링크 | `var(--accent)` |
| 선택된 항목 배경 | `var(--accent-surface)` |
| 파괴적 액션 | `var(--danger)` |

> **핵심 규칙**: 카드 밖(페이지 배경 위)에는 구분선을 긋지 않는다. 구분은 카드 단위, 선은 카드 안에서만.

---

## 3. 타이포그래피

### 3-1. 폰트

원 시스템 서체는 SamsungOne(다국어 최적화)·Samsung Sharp Sans. 공개 환경에서는 Noto Sans KR로 대체한다.

```css
:root {
  --font-sans: 'SamsungOne', 'Samsung Sharp Sans',
               'Noto Sans KR', 'Malgun Gothic', system-ui, sans-serif;
}

body {
  font-family: var(--font-sans);
  color: var(--text);
  background: var(--bg);
  word-break: keep-all;
}
```

```html
<link rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700&display=swap" />
```

### 3-2. 타입 스케일

| 역할 | `font-size` | `font-weight` | 용도 |
|---|---|---|---|
| Expanded Title | 32px | 400 | 펼쳐진 헤더 대제목 |
| Title | 20px | 500 | 접힌 헤더·다이얼로그 제목 |
| List Title | 17px | 400 | 리스트 항목 제목 |
| Body | 15px | 400 | 본문·설명 |
| Sub Text | 13px | 400 | 항목 하단 보조 |
| Button | 15px | 600 | 버튼 라벨 |
| Section Header | 13px | 500 | 카드 그룹 상단 라벨 (액센트색) |

- **Expanded Title이 Regular(400)** 인 것이 특징 — 크기로만 위계를 만들고 무게는 절제.
- 섹션 헤더는 작게 + 액센트색으로 — One UI 설정 화면의 시그니처.

---

## 4. 레이아웃 & 라운드

```css
:root {
  --radius-card:   1.625rem;  /* 26px — 카드 그룹 */
  --radius-button: 1.25rem;   /* 풀 라운드 지향 버튼 */
  --radius-inner:  1rem;      /* 카드 내부 요소 */
  --spacing:       0.25rem;
}

.container { max-width: 45rem; margin-inline: auto; padding-inline: 1rem; }

/* Viewing / Interaction 분리 헤더 */
.expanded-header {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-height: 12rem;            /* 상단 절반은 보는 영역 */
  padding-bottom: 2rem;
  font-size: 2rem;
  color: var(--text);
}
```

- 대화면 세로 레이아웃: 상단 1/3~1/2는 제목·상태 표시, 인터랙티브 요소는 그 아래부터.
- 카드 그룹 사이 간격 12px, 카드 좌우 마진 16px.

---

## 5. 핵심 컴포넌트

### 5-1. 설정형 리스트 카드 — 시그니처

```html
<p class="section-label">디스플레이</p>
<div class="list-card">
  <button class="item">
    <span class="item__texts">
      <span class="item__title">화면 밝기</span>
      <span class="item__sub">자동 조절 켜짐</span>
    </span>
    <span class="switch" aria-checked="true"></span>
  </button>
  <button class="item">…</button>
</div>
```

```css
.section-label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--accent);
  padding: 1.25rem 1.5rem 0.5rem;
}
.list-card {
  background: var(--card);
  border-radius: var(--radius-card);
  overflow: hidden;
  margin-inline: 1rem;
}
.item {
  display: flex;
  align-items: center;
  width: 100%;
  gap: 0.75rem;
  padding: 1rem 1.5rem;
  min-height: 3.5rem;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
}
.item:active { background: var(--bg); }
.item + .item { border-top: 1px solid var(--divider); }
.item__title { font-size: 1.0625rem; color: var(--text); }
.item__sub   { font-size: 0.8125rem; color: var(--text-sub); }
```

### 5-2. 스위치

```css
.switch {
  width: 2.5rem; height: 1.5rem;
  border-radius: 62.4375rem;
  background: var(--text-disabled);
  position: relative;
  transition: background-color 0.2s ease;
}
.switch::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 1.25rem; height: 1.25rem;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
  transition: transform 0.2s ease;
}
.switch[aria-checked="true"] { background: var(--accent); }
.switch[aria-checked="true"]::after { transform: translateX(1rem); }
```

### 5-3. 버튼

```css
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: 0.625rem 1.75rem;
  border: none;
  border-radius: var(--radius-button);
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.2s ease;
}
.btn--primary { background: var(--accent); color: #ffffff; }
.btn--primary:active { background: var(--accent-press); }
.btn--secondary { background: var(--card); color: var(--accent); }
.btn:disabled { background: var(--divider); color: var(--text-disabled); }
```

### 5-4. 하단 시트·다이얼로그

```css
.dialog {
  background: var(--card);
  border-radius: var(--radius-card);
  padding: 1.5rem;
  max-width: 22rem;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
}
.dialog__title { font-size: 1.25rem; font-weight: 500; margin-bottom: 0.75rem; }
.dialog__actions { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1.25rem; }
```

---

## 6. 인터랙션

- 탭 피드백: 배경을 `--bg`로 살짝 가라앉힘, 즉시 적용.
- 전환 0.2s ease. 리스트 진입은 아래에서 가볍게 떠오르는 슬라이드.
- 당겨서 새로고침·스크롤 바운스 등 물리 기반 모션 감각 유지.
- `prefers-reduced-motion` 시 슬라이드를 페이드로 대체.

---

## 7. 다크 모드

```css
.dark {
  color-scheme: dark;

  --bg:            #010101;   /* AMOLED 순검정 배경 */
  --card:          #1c1c1e;
  --text:          #e8e8e8;
  --text-sub:      #8c8c8c;
  --text-disabled: #4d4d4f;
  --divider:       #2c2c2e;

  --accent:         #3e91ff;  /* 블루 한 단계 밝게 */
  --accent-press:   #5da2ff;
  --accent-surface: #10305c;

  --danger:  #ff6b61;
  --success: #4ccf7c;
}
```

- 배경은 AMOLED 절전을 위한 **순검정(#010101)**, 카드가 `#1c1c1e`로 떠오른다 — HIG류 다크와 구분되는 One UI 특징.
- 액센트는 한 단계 밝게 조정해 검정 배경 대비 확보.

---

## 8. 접근성

- `--text`(#252525) 대비 15.1:1 — AAA. `--text-sub`(#8c8c8c)는 보조 텍스트 전용 (대비 3.5:1, 큰 텍스트만).
- 터치 타깃 최소 48×48px (리스트 항목 `min-height: 3.5rem`).
- 한 손 조작: 주 액션(확인·저장)은 항상 화면 하단에 배치.
- 스위치·체크 상태는 색 + 위치(노브 이동)로 이중 전달, `aria-checked` 필수.
- 글자 크기 시스템 설정 연동 — 전 크기 `rem`.

---

## 9. 안티패턴

| 금지 | 이유 |
|---|---|
| 페이지 배경 위 구분선 | 구분은 카드 단위, 선은 카드 안에서만 |
| 작은 라운드(8px 미만) 카드 | 큰 라운드가 One UI 정체성 |
| 화면 상단에 주 액션 배치 | 한 손 조작 원칙 위반 |
| 블루 외 액센트 도입 | 단일 액센트 원칙 |
| 채도 있는 페이지 배경 | 차분한 뉴트럴 원칙 |
| 다크 모드 카드에 순검정 사용 | 배경만 순검정, 카드는 #1c1c1e |
| Expanded Title에 Bold | 대제목은 Regular — 크기로만 위계 |
| 섹션 라벨 생략 | 액센트 섹션 라벨이 그룹 인지의 핵심 |

---

## 10. 프레임워크 어댑터

### 10-1. Tailwind CSS v4

```css
@import "tailwindcss";

@theme {
  --color-bg:       #f6f6f6;
  --color-card:     #ffffff;
  --color-text:     #252525;
  --color-text-sub: #8c8c8c;
  --color-divider:  #e6e6e6;
  --color-accent:   #0381fe;
  --radius-card:    1.625rem;
  --radius-button:  1.25rem;
}

@custom-variant dark (&:where(.dark, .dark *));
```

### 10-2. Tailwind CSS v3

```js
module.exports = {
  darkMode: 'class',
  theme: {
    extend: {
      colors: {
        bg:        'var(--bg)',
        card:      'var(--card)',
        text:      'var(--text)',
        'text-sub':'var(--text-sub)',
        divider:   'var(--divider)',
        accent:    'var(--accent)',
      },
      borderRadius: { card: '1.625rem', button: '1.25rem' },
    },
  },
};
```

### 10-3. React / Vue / Svelte

CSS 변수가 원천. 다크 전환은 `.dark` 토글. AMOLED 순검정과 카드색 차이를 토큰이 보존한다.

---

## 11. 이식 가이드

### Step 1 — 토큰 복사

§2 라이트 + §7 다크 블록을 전역 CSS에 붙인다.

### Step 2 — 폰트 연결

Noto Sans KR 링크 추가 (SamsungOne 보유 시 우선 연결).

### Step 3 — 시그니처 3종 적용

| 패턴 | 핵심 CSS |
|---|---|
| **리스트 카드** | `border-radius: 26px; background: var(--card)` + 내부 divider |
| **액센트 섹션 라벨** | 13px, 500, `color: var(--accent)` — 카드 그룹 위 |
| **Expanded Header** | 화면 상단 1/3 여백 + 하단 정렬 32px Regular 제목 |

### Step 4 — 한 손 조작 검증

주 액션이 화면 하단 절반에 있는지, 터치 타깃 48px 이상인지 확인한다.

### 신규 컴포넌트 결정 트리

```
새 컴포넌트가 필요하다
  → 카드 안에 들어가는가?
    yes → 리스트 항목 변형으로 구현 (제목/보조/우측 컨트롤 구조)
    no  → 독립 카드로 — 26px 라운드·배경 대비 상속
  → 인터랙션이 있는가?
    yes → 화면 하단 배치 가능성부터 검토
```
