@x-plat/design-system 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/guidelines/Guidelines.md +57 -0
- package/guidelines/components/accordion.md +72 -0
- package/guidelines/components/avatar.md +35 -0
- package/guidelines/components/button.md +58 -0
- package/guidelines/components/card.md +28 -0
- package/guidelines/components/chart.md +58 -0
- package/guidelines/components/chip-tag.md +49 -0
- package/guidelines/components/data-display.md +96 -0
- package/guidelines/components/datepicker.md +60 -0
- package/guidelines/components/dropdown.md +49 -0
- package/guidelines/components/feedback.md +64 -0
- package/guidelines/components/file-media.md +95 -0
- package/guidelines/components/form.md +60 -0
- package/guidelines/components/html-typewriter.md +38 -0
- package/guidelines/components/input.md +55 -0
- package/guidelines/components/navigation.md +80 -0
- package/guidelines/components/overlay.md +72 -0
- package/guidelines/components/select.md +44 -0
- package/guidelines/components/swiper.md +84 -0
- package/guidelines/components/table.md +62 -0
- package/guidelines/composition/grid.md +95 -0
- package/guidelines/composition/layout.md +30 -0
- package/guidelines/foundations/color.md +81 -0
- package/guidelines/foundations/icons.md +55 -0
- package/guidelines/foundations/spacing.md +51 -0
- package/guidelines/foundations/typography.md +63 -0
- package/guidelines/setup.md +42 -0
- package/package.json +4 -2
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# @x-plat/design-system Guidelines
|
|
2
|
+
|
|
3
|
+
React 기반 디자인 시스템 라이브러리이다. Figma Make Kit과 1:1 대응한다.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 핵심 규칙
|
|
8
|
+
|
|
9
|
+
1. **컴포넌트에 `color`, `className`, `style` prop이 없다.** 색상과 스타일은 내부 semantic 토큰으로 고정한다.
|
|
10
|
+
2. **레이아웃 조절은 래퍼 `<div>`로 감싸서 래퍼에만 스타일을 적용한다.**
|
|
11
|
+
3. **CSS로 DS 컴포넌트 스타일을 오버라이드하지 않는다.**
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
// 올바른 방법
|
|
15
|
+
<div className="button-wrapper">
|
|
16
|
+
<Button type="primary">저장</Button>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
// 금지
|
|
20
|
+
<Button style={{ marginBottom: "1rem" }}>저장</Button>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 읽기 순서
|
|
26
|
+
|
|
27
|
+
아래 순서로 읽는다.
|
|
28
|
+
|
|
29
|
+
1. **[설치 및 설정](./setup.md)** - CSS/컴포넌트 import, ToastProvider 설정
|
|
30
|
+
2. **파운데이션**
|
|
31
|
+
- [컬러](./foundations/color.md) - 4레이어 semantic 토큰
|
|
32
|
+
- [스페이싱](./foundations/spacing.md) - space, radius, stroke
|
|
33
|
+
- [타이포그래피](./foundations/typography.md) - font, size, weight
|
|
34
|
+
- [아이콘](./foundations/icons.md) - import, 크기/색상, 카테고리
|
|
35
|
+
3. **컴포넌트**
|
|
36
|
+
- [Button](./components/button.md)
|
|
37
|
+
- [Input](./components/input.md) - Input, PasswordInput, TextArea
|
|
38
|
+
- [Select](./components/select.md)
|
|
39
|
+
- [Table](./components/table.md)
|
|
40
|
+
- [피드백](./components/feedback.md) - Alert, Toast, Badge
|
|
41
|
+
- [오버레이](./components/overlay.md) - Modal, Drawer, PopOver, Tooltip
|
|
42
|
+
- [폼 컨트롤](./components/form.md) - CheckBox, Radio, Switch
|
|
43
|
+
- [Chip & Tag](./components/chip-tag.md)
|
|
44
|
+
- [내비게이션](./components/navigation.md) - Tab, CardTab, Breadcrumb, Pagination, Steps
|
|
45
|
+
- [DatePicker](./components/datepicker.md) - Calendar, DatePicker 4종
|
|
46
|
+
- [Accordion](./components/accordion.md)
|
|
47
|
+
- [Avatar](./components/avatar.md)
|
|
48
|
+
- [Card](./components/card.md)
|
|
49
|
+
- [Chart](./components/chart.md)
|
|
50
|
+
- [데이터 표시](./components/data-display.md) - Divider, EmptyState, Skeleton, Spinner
|
|
51
|
+
- [Dropdown](./components/dropdown.md)
|
|
52
|
+
- [파일 & 미디어](./components/file-media.md) - FileUpload, ImageSelector, Video
|
|
53
|
+
- [Swiper](./components/swiper.md)
|
|
54
|
+
- [HtmlTypeWriter](./components/html-typewriter.md)
|
|
55
|
+
4. **컴포지션**
|
|
56
|
+
- [Grid](./composition/grid.md) - Grid 시스템, 위젯 패턴
|
|
57
|
+
- [Layout](./composition/layout.md) - Layout, Header, SideBar
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Accordion
|
|
2
|
+
|
|
3
|
+
접이식 패널을 표시한다. 단일/다중 모드를 지원하며, controlled/uncontrolled 모두 가능하다.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Accordion } from "@xplat/design-system";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
### 공통
|
|
12
|
+
|
|
13
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
14
|
+
|------|------|--------|------|
|
|
15
|
+
| items `*` | `AccordionItemData[]` | — | 아코디언 아이템 배열 |
|
|
16
|
+
| multiple | `boolean` | `false` | 다중 열기 허용 |
|
|
17
|
+
|
|
18
|
+
### AccordionItemData
|
|
19
|
+
|
|
20
|
+
| 필드 | 타입 | 설명 |
|
|
21
|
+
|------|------|------|
|
|
22
|
+
| key `*` | `string` | 고유 식별자 |
|
|
23
|
+
| title `*` | `ReactNode` | 헤더 영역 |
|
|
24
|
+
| content `*` | `ReactNode` | 본문 영역 |
|
|
25
|
+
|
|
26
|
+
### 단일 모드 (multiple 미지정 또는 false)
|
|
27
|
+
|
|
28
|
+
| Prop | 타입 | 설명 |
|
|
29
|
+
|------|------|------|
|
|
30
|
+
| activeKey | `string \| null` | 열린 아이템 key (controlled) |
|
|
31
|
+
| defaultActiveKey | `string` | 초기 열린 아이템 key (uncontrolled) |
|
|
32
|
+
| onChange | `(key: string \| null) => void` | 변경 콜백 |
|
|
33
|
+
|
|
34
|
+
### 다중 모드 (multiple={true})
|
|
35
|
+
|
|
36
|
+
| Prop | 타입 | 설명 |
|
|
37
|
+
|------|------|------|
|
|
38
|
+
| activeKeys | `string[]` | 열린 아이템 key 목록 (controlled) |
|
|
39
|
+
| defaultActiveKeys | `string[]` | 초기 열린 아이템 key 목록 (uncontrolled) |
|
|
40
|
+
| onChange | `(keys: string[]) => void` | 변경 콜백 |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 사용 예시
|
|
45
|
+
|
|
46
|
+
### 단일 모드 (uncontrolled)
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
<Accordion
|
|
50
|
+
defaultActiveKey="faq-1"
|
|
51
|
+
items={[
|
|
52
|
+
{ key: "faq-1", title: "질문 1", content: "답변 1" },
|
|
53
|
+
{ key: "faq-2", title: "질문 2", content: "답변 2" },
|
|
54
|
+
]}
|
|
55
|
+
/>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 다중 모드 (controlled)
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
const [openKeys, setOpenKeys] = useState<string[]>([]);
|
|
62
|
+
|
|
63
|
+
<Accordion
|
|
64
|
+
multiple
|
|
65
|
+
activeKeys={openKeys}
|
|
66
|
+
onChange={setOpenKeys}
|
|
67
|
+
items={[
|
|
68
|
+
{ key: "a", title: "섹션 A", content: <div>내용 A</div> },
|
|
69
|
+
{ key: "b", title: "섹션 B", content: <div>내용 B</div> },
|
|
70
|
+
]}
|
|
71
|
+
/>
|
|
72
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Avatar
|
|
2
|
+
|
|
3
|
+
프로필 이미지 또는 이니셜을 표시한다. `src`가 있으면 이미지를 렌더하고, 없으면 `name` 기반 이니셜을 표시한다. 둘 다 없으면 기본 사람 아이콘을 표시한다.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Avatar } from "@xplat/design-system";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
12
|
+
|------|------|--------|------|
|
|
13
|
+
| src | `string` | — | 이미지 URL |
|
|
14
|
+
| alt | `string` | name 또는 `"avatar"` | 이미지 alt 텍스트 |
|
|
15
|
+
| name | `string` | — | 이니셜 생성용 이름 (예: `"홍 길동"` → `"홍길"`) |
|
|
16
|
+
| size | `"sm" \| "md" \| "lg"` | `"md"` | 크기 |
|
|
17
|
+
|
|
18
|
+
## 색상 자동 배정
|
|
19
|
+
|
|
20
|
+
`name`의 첫 글자 charCode 기반으로 8가지 categorical color 중 하나를 자동 배정한다. 같은 이름은 항상 같은 색상이 된다.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 사용 예시
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
// 이미지
|
|
28
|
+
<Avatar src="/profile.jpg" name="김철수" size="lg" />
|
|
29
|
+
|
|
30
|
+
// 이니셜 (이미지 없음)
|
|
31
|
+
<Avatar name="홍 길동" size="md" />
|
|
32
|
+
|
|
33
|
+
// 기본 아이콘 (이름도 없음)
|
|
34
|
+
<Avatar size="sm" />
|
|
35
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
## Type
|
|
4
|
+
|
|
5
|
+
| type | 용도 |
|
|
6
|
+
|------|------|
|
|
7
|
+
| primary | 주요 액션 |
|
|
8
|
+
| secondary | 보조 액션 |
|
|
9
|
+
| danger | 삭제/위험 액션 |
|
|
10
|
+
| ghost | 텍스트만 표시 |
|
|
11
|
+
|
|
12
|
+
## Size
|
|
13
|
+
|
|
14
|
+
| size | 높이 |
|
|
15
|
+
|------|------|
|
|
16
|
+
| sm | 32px |
|
|
17
|
+
| md | 40px |
|
|
18
|
+
| lg | 48px |
|
|
19
|
+
|
|
20
|
+
## 상태
|
|
21
|
+
|
|
22
|
+
| 상태 | 설명 |
|
|
23
|
+
|------|------|
|
|
24
|
+
| default | 기본 |
|
|
25
|
+
| hover | 마우스 오버 |
|
|
26
|
+
| pressed (`:active`) | 클릭 중 |
|
|
27
|
+
| focused (`:focus-visible`) | 키보드 포커스 |
|
|
28
|
+
| disabled | 비활성화 |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 올바른 예시
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<Button type="primary" size="md">확인</Button>
|
|
36
|
+
<Button type="secondary" size="lg">취소</Button>
|
|
37
|
+
<Button type="danger">삭제</Button>
|
|
38
|
+
<Button type="primary" disabled>비활성</Button>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 잘못된 예시
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
// 금지: style prop 사용
|
|
45
|
+
<Button style={{ backgroundColor: "red" }}>삭제</Button>
|
|
46
|
+
|
|
47
|
+
// 금지: className 사용
|
|
48
|
+
<Button className="custom-btn">확인</Button>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 유사 컴포넌트 구분
|
|
54
|
+
|
|
55
|
+
| 목적 | 사용할 것 |
|
|
56
|
+
|------|----------|
|
|
57
|
+
| 페이지/외부 링크 이동 | `<a>` 또는 라우터 Link |
|
|
58
|
+
| 액션 실행 | Button |
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Card
|
|
2
|
+
|
|
3
|
+
콘텐츠를 카드 형태로 감싸는 컨테이너이다.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Card } from "@xplat/design-system";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
12
|
+
|------|------|--------|------|
|
|
13
|
+
| children `*` | `ReactNode` | — | 카드 본문 |
|
|
14
|
+
| title | `string` | — | 카드 상단 제목 |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 사용 예시
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
<Card title="매출 현황">
|
|
22
|
+
<p>이번 달 매출: 1,200만원</p>
|
|
23
|
+
</Card>
|
|
24
|
+
|
|
25
|
+
<Card>
|
|
26
|
+
<p>제목 없는 카드</p>
|
|
27
|
+
</Card>
|
|
28
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Chart
|
|
2
|
+
|
|
3
|
+
SVG 기반 차트를 렌더한다. line, bar, pie, doughnut 4가지 타입을 지원한다.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Chart } from "@xplat/design-system";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
12
|
+
|------|------|--------|------|
|
|
13
|
+
| type `*` | `"line" \| "bar" \| "pie" \| "doughnut"` | — | 차트 타입 |
|
|
14
|
+
| data `*` | `Record<string, number[]>` | — | 데이터셋 (key: 시리즈 이름, value: 값 배열) |
|
|
15
|
+
| labels `*` | `string[]` | — | x축 라벨 배열 |
|
|
16
|
+
| tooltip | `boolean` | `true` | 호버 시 툴팁 표시 |
|
|
17
|
+
|
|
18
|
+
## 색상
|
|
19
|
+
|
|
20
|
+
primitive 팔레트 기반으로 시리즈별 색상을 자동 배정한다. line/bar는 `LINE_BAR_PALETTES`, pie/doughnut는 `PIE_PALETTES`를 사용한다.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 사용 예시
|
|
25
|
+
|
|
26
|
+
### Line
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<Chart
|
|
30
|
+
type="line"
|
|
31
|
+
labels={["1월", "2월", "3월", "4월"]}
|
|
32
|
+
data={{
|
|
33
|
+
매출: [100, 200, 150, 300],
|
|
34
|
+
비용: [80, 120, 100, 200],
|
|
35
|
+
}}
|
|
36
|
+
/>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Bar
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<Chart
|
|
43
|
+
type="bar"
|
|
44
|
+
labels={["서울", "부산", "대구"]}
|
|
45
|
+
data={{ 방문자: [500, 300, 200] }}
|
|
46
|
+
/>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Pie / Doughnut
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
<Chart
|
|
53
|
+
type="doughnut"
|
|
54
|
+
labels={["모바일", "데스크톱", "태블릿"]}
|
|
55
|
+
data={{ 점유율: [60, 30, 10] }}
|
|
56
|
+
tooltip={false}
|
|
57
|
+
/>
|
|
58
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Chip & Tag
|
|
2
|
+
|
|
3
|
+
## Chip
|
|
4
|
+
|
|
5
|
+
읽기 전용 라벨이다. 삭제 기능이 없다.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Chip type="primary">진행중</Chip>
|
|
9
|
+
<Chip type="success">완료</Chip>
|
|
10
|
+
<Chip type="error">실패</Chip>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
| type | 용도 |
|
|
14
|
+
|------|------|
|
|
15
|
+
| primary | 기본 강조 |
|
|
16
|
+
| secondary | 보조 |
|
|
17
|
+
| neutral | 중립 |
|
|
18
|
+
| success | 성공 |
|
|
19
|
+
| error | 에러 |
|
|
20
|
+
| warning | 경고 |
|
|
21
|
+
| info | 정보 |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Tag
|
|
26
|
+
|
|
27
|
+
제거 가능한 태그이다. `onClose`로 삭제를 처리한다.
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
<Tag onClose={() => handleRemove("react")}>React</Tag>
|
|
31
|
+
<Tag type="categorical" colorIndex={1} onClose={handleRemove}>TypeScript</Tag>
|
|
32
|
+
<Tag disabled>삭제 불가</Tag>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
| Prop | 설명 |
|
|
36
|
+
|------|------|
|
|
37
|
+
| type | `"neutral" \| "categorical"` |
|
|
38
|
+
| onClose | 삭제 콜백 |
|
|
39
|
+
| colorIndex | categorical 타입의 색상 인덱스 |
|
|
40
|
+
| disabled | 비활성화 |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 의사결정
|
|
45
|
+
|
|
46
|
+
| 상황 | 사용할 것 |
|
|
47
|
+
|------|----------|
|
|
48
|
+
| 상태/분류 라벨 (삭제 불필요) | Chip |
|
|
49
|
+
| 사용자가 제거할 수 있는 태그 | Tag |
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# 데이터 표시: Divider / EmptyState / Skeleton / Spinner
|
|
2
|
+
|
|
3
|
+
## Divider
|
|
4
|
+
|
|
5
|
+
구분선을 표시한다.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Divider } from "@xplat/design-system";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
12
|
+
|------|------|--------|------|
|
|
13
|
+
| orientation | `"horizontal" \| "vertical"` | `"horizontal"` | 방향 |
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
<Divider />
|
|
17
|
+
<Divider orientation="vertical" />
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## EmptyState
|
|
23
|
+
|
|
24
|
+
빈 상태 안내를 표시한다.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { EmptyState } from "@xplat/design-system";
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
31
|
+
|------|------|--------|------|
|
|
32
|
+
| icon | `ReactNode` | 기본 폴더 아이콘 | 상단 아이콘 |
|
|
33
|
+
| title | `string` | `"데이터가 없습니다"` | 제목 |
|
|
34
|
+
| description | `string` | — | 부가 설명 |
|
|
35
|
+
| action | `ReactNode` | — | 하단 액션 영역 (버튼 등) |
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
<EmptyState
|
|
39
|
+
title="검색 결과가 없습니다"
|
|
40
|
+
description="다른 키워드로 검색해 보세요."
|
|
41
|
+
action={<Button type="primary">전체 목록</Button>}
|
|
42
|
+
/>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Skeleton
|
|
48
|
+
|
|
49
|
+
로딩 플레이스홀더를 표시한다.
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { Skeleton } from "@xplat/design-system";
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
56
|
+
|------|------|--------|------|
|
|
57
|
+
| variant | `"text" \| "circular" \| "rectangular"` | `"text"` | 형태 |
|
|
58
|
+
| width | `string \| number` | — | 너비 |
|
|
59
|
+
| height | `string \| number` | — | 높이 |
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
<Skeleton variant="text" width="200px" />
|
|
63
|
+
<Skeleton variant="circular" width={48} height={48} />
|
|
64
|
+
<Skeleton variant="rectangular" width="100%" height={120} />
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Spinner
|
|
70
|
+
|
|
71
|
+
로딩 인디케이터를 표시한다.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { Spinner } from "@xplat/design-system";
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
78
|
+
|------|------|--------|------|
|
|
79
|
+
| size | `"sm" \| "md" \| "lg"` | `"md"` | 크기 |
|
|
80
|
+
| type | `"brand" \| "success" \| "error" \| "warning" \| "info"` | `"brand"` | 색상 타입 |
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<Spinner />
|
|
84
|
+
<Spinner size="lg" type="success" />
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 의사결정
|
|
90
|
+
|
|
91
|
+
| 상황 | 사용할 것 |
|
|
92
|
+
|------|----------|
|
|
93
|
+
| 영역 구분선 | Divider |
|
|
94
|
+
| 데이터가 없는 상태 안내 | EmptyState |
|
|
95
|
+
| 콘텐츠 로딩 전 자리 차지 | Skeleton |
|
|
96
|
+
| 로딩 중 표시 (인디케이터) | Spinner |
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# DatePicker: Calendar / DatePicker 4종
|
|
2
|
+
|
|
3
|
+
## Calendar
|
|
4
|
+
|
|
5
|
+
달력을 표시한다. 이벤트 표시와 `renderDay` 커스텀을 지원한다.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Calendar
|
|
9
|
+
events={[{ date: "2026-03-15", type: "success" }]}
|
|
10
|
+
renderDay={(date) => <span>{date.getDate()}</span>}
|
|
11
|
+
/>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## SingleDatePicker
|
|
17
|
+
|
|
18
|
+
단일 날짜를 선택한다.
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
<SingleDatePicker value={date} onChange={(d) => setDate(d)} />
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## RangeDatePicker
|
|
25
|
+
|
|
26
|
+
날짜 범위를 선택한다.
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<RangeDatePicker startDate={start} endDate={end} onChange={handleRange} />
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## InputDatePicker
|
|
33
|
+
|
|
34
|
+
Input + 드롭다운 형태이다.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<InputDatePicker value={date} onChange={(d) => setDate(d)} />
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## PopupDatePicker
|
|
41
|
+
|
|
42
|
+
버튼 + 모달 형태이다.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
<PopupDatePicker
|
|
46
|
+
type="single"
|
|
47
|
+
component={<Button>날짜 선택</Button>}
|
|
48
|
+
value={date}
|
|
49
|
+
onChange={(d) => setDate(d)}
|
|
50
|
+
/>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 의사결정
|
|
56
|
+
|
|
57
|
+
| 상황 | 사용할 것 |
|
|
58
|
+
|------|----------|
|
|
59
|
+
| 달력 표시 / 이벤트 | Calendar |
|
|
60
|
+
| 날짜 선택 | DatePicker (Single/Range/Input/Popup) |
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Dropdown
|
|
2
|
+
|
|
3
|
+
액션 메뉴를 표시한다. `children`이 트리거 역할을 하며, 클릭 시 메뉴가 열린다.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Dropdown } from "@xplat/design-system";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
12
|
+
|------|------|--------|------|
|
|
13
|
+
| items `*` | `DropdownItem[]` | — | 메뉴 아이템 배열 |
|
|
14
|
+
| children `*` | `ReactNode` | — | 트리거 요소 |
|
|
15
|
+
|
|
16
|
+
### DropdownItem
|
|
17
|
+
|
|
18
|
+
| 필드 | 타입 | 설명 |
|
|
19
|
+
|------|------|------|
|
|
20
|
+
| key `*` | `string` | 고유 식별자 |
|
|
21
|
+
| label `*` | `ReactNode` | 표시 텍스트 |
|
|
22
|
+
| onClick | `() => void` | 클릭 콜백 |
|
|
23
|
+
| disabled | `boolean` | 비활성화 |
|
|
24
|
+
| danger | `boolean` | 위험 액션 스타일 (빨간색) |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 사용 예시
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<Dropdown
|
|
32
|
+
items={[
|
|
33
|
+
{ key: "edit", label: "수정", onClick: () => handleEdit() },
|
|
34
|
+
{ key: "copy", label: "복사", onClick: () => handleCopy() },
|
|
35
|
+
{ key: "delete", label: "삭제", onClick: () => handleDelete(), danger: true },
|
|
36
|
+
]}
|
|
37
|
+
>
|
|
38
|
+
<Button type="ghost">더보기</Button>
|
|
39
|
+
</Dropdown>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 유사 컴포넌트 구분
|
|
45
|
+
|
|
46
|
+
| 목적 | 사용할 것 |
|
|
47
|
+
|------|----------|
|
|
48
|
+
| 값 선택 (폼 필드) | Select |
|
|
49
|
+
| 액션 실행 (메뉴) | Dropdown |
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 피드백: Alert / Toast / Badge
|
|
2
|
+
|
|
3
|
+
## Alert
|
|
4
|
+
|
|
5
|
+
인라인 알림을 표시한다.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Alert type="info">정보 메시지</Alert>
|
|
9
|
+
<Alert type="success">성공</Alert>
|
|
10
|
+
<Alert type="warning">경고</Alert>
|
|
11
|
+
<Alert type="error" onClose={() => {}}>에러 (닫기 가능)</Alert>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Prop | 설명 |
|
|
15
|
+
|------|------|
|
|
16
|
+
| type | `"info" \| "success" \| "warning" \| "error"` |
|
|
17
|
+
| onClose | 닫기 버튼 콜백 (전달 시 닫기 버튼 표시) |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Toast
|
|
22
|
+
|
|
23
|
+
일시적 알림을 표시한다. **ToastProvider가 앱 최상위에 필수이다.**
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
// 앱 루트
|
|
27
|
+
<ToastProvider position="top-right">
|
|
28
|
+
<App />
|
|
29
|
+
</ToastProvider>
|
|
30
|
+
|
|
31
|
+
// 컴포넌트 내
|
|
32
|
+
const { toast } = useToast();
|
|
33
|
+
toast("success", "저장 완료");
|
|
34
|
+
toast("error", "오류 발생", 5000);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`toast(type, message, duration?)` 형태로 호출한다.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Badge
|
|
42
|
+
|
|
43
|
+
카운트 또는 도트를 표시한다.
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<Badge type="error" count={5}><BellIcon /></Badge>
|
|
47
|
+
<Badge type="success" dot><UserIcon /></Badge>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
| Prop | 설명 |
|
|
51
|
+
|------|------|
|
|
52
|
+
| type | `"error" \| "success" \| "warning" \| "info" \| "brand"` |
|
|
53
|
+
| count | 숫자 표시 |
|
|
54
|
+
| dot | 도트만 표시 |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 의사결정
|
|
59
|
+
|
|
60
|
+
| 상황 | 사용할 것 |
|
|
61
|
+
|------|----------|
|
|
62
|
+
| 인라인 알림 (페이지 내 고정) | Alert |
|
|
63
|
+
| 일시적 알림 (자동 사라짐) | Toast |
|
|
64
|
+
| 카운트/상태 표시 | Badge |
|