@x-plat/design-system 0.5.0 → 0.5.1
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,95 @@
|
|
|
1
|
+
# 파일/미디어: FileUpload / ImageSelector / Video
|
|
2
|
+
|
|
3
|
+
## FileUpload
|
|
4
|
+
|
|
5
|
+
파일 업로드 영역을 표시한다. 드래그 앤 드롭과 클릭 업로드를 모두 지원한다.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { FileUpload } from "@xplat/design-system";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
12
|
+
|------|------|--------|------|
|
|
13
|
+
| accept | `string` | — | 허용 파일 타입 (예: `"image/*,.pdf"`) |
|
|
14
|
+
| multiple | `boolean` | `false` | 다중 파일 허용 |
|
|
15
|
+
| maxSize | `number` | — | 최대 파일 크기 (bytes). 초과 파일은 자동 필터 |
|
|
16
|
+
| onChange | `(files: File[]) => void` | — | 파일 선택 콜백 |
|
|
17
|
+
| label | `string` | `"파일을 드래그하거나 클릭하여 업로드"` | 안내 텍스트 |
|
|
18
|
+
| description | `string` | — | 부가 설명 |
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
<FileUpload
|
|
22
|
+
accept="image/*"
|
|
23
|
+
multiple
|
|
24
|
+
maxSize={5 * 1024 * 1024}
|
|
25
|
+
onChange={(files) => console.log(files)}
|
|
26
|
+
description="최대 5MB, 이미지만 허용"
|
|
27
|
+
/>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## ImageSelector
|
|
33
|
+
|
|
34
|
+
단일 이미지를 선택/미리보기하는 컨트롤이다. controlled 방식으로 동작한다.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { ImageSelector } from "@xplat/design-system";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
41
|
+
|------|------|--------|------|
|
|
42
|
+
| value | `File` | — | 선택된 이미지 파일 |
|
|
43
|
+
| label | `string` | `"이미지 추가하기"` | 빈 상태 안내 텍스트 |
|
|
44
|
+
| onChange | `(value: File \| undefined) => void` | — | 변경 콜백 (삭제 시 `undefined`) |
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
const [image, setImage] = useState<File | undefined>();
|
|
48
|
+
|
|
49
|
+
<ImageSelector value={image} onChange={setImage} />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Video
|
|
55
|
+
|
|
56
|
+
비디오 플레이어를 표시한다. `controls={false}`이면 커스텀 재생/일시정지 오버레이를 표시한다. `ref`를 지원한다.
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { Video } from "@xplat/design-system";
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
63
|
+
|------|------|--------|------|
|
|
64
|
+
| src `*` | `string` | — | 비디오 URL |
|
|
65
|
+
| poster | `string` | — | 썸네일 이미지 URL |
|
|
66
|
+
| controls | `boolean` | `true` | 네이티브 컨트롤 표시. `false`면 커스텀 오버레이 |
|
|
67
|
+
| autoPlay | `boolean` | — | 자동 재생 |
|
|
68
|
+
| muted | `boolean` | — | 음소거 |
|
|
69
|
+
| loop | `boolean` | — | 반복 재생 |
|
|
70
|
+
| playsInline | `boolean` | `true` | 인라인 재생 (모바일) |
|
|
71
|
+
|
|
72
|
+
`HTMLVideoElement`의 나머지 속성도 전달 가능하다.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
const videoRef = useRef<HTMLVideoElement>(null);
|
|
76
|
+
|
|
77
|
+
<Video
|
|
78
|
+
ref={videoRef}
|
|
79
|
+
src="/intro.mp4"
|
|
80
|
+
poster="/thumb.jpg"
|
|
81
|
+
controls={false}
|
|
82
|
+
muted
|
|
83
|
+
loop
|
|
84
|
+
/>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 의사결정
|
|
90
|
+
|
|
91
|
+
| 상황 | 사용할 것 |
|
|
92
|
+
|------|----------|
|
|
93
|
+
| 파일 업로드 (범용) | FileUpload |
|
|
94
|
+
| 이미지 1장 선택 + 미리보기 | ImageSelector |
|
|
95
|
+
| 비디오 재생 | Video |
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# 폼 컨트롤: CheckBox / Radio / Switch
|
|
2
|
+
|
|
3
|
+
## CheckBox
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
<CheckBox label="동의합니다" checked={checked} onChange={setChecked} />
|
|
7
|
+
<CheckBox label="에러 상태" type="error" checked={false} />
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
| Prop | 설명 |
|
|
11
|
+
|------|------|
|
|
12
|
+
| label | 라벨 텍스트 |
|
|
13
|
+
| checked | 체크 상태 |
|
|
14
|
+
| type | `"brand" \| "success" \| "error" \| "warning" \| "info"` |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Radio
|
|
19
|
+
|
|
20
|
+
**RadioGroup 안에 Radio를 조합한다.**
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
<RadioGroup name="fruit" value={value} onChange={(e) => setValue(e.target.value)}>
|
|
24
|
+
<Radio value="apple" label="사과" />
|
|
25
|
+
<Radio value="banana" label="바나나" />
|
|
26
|
+
</RadioGroup>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Prop (RadioGroup) | 설명 |
|
|
30
|
+
|-------------------|------|
|
|
31
|
+
| name | 그룹 이름 |
|
|
32
|
+
| value | 선택된 값 |
|
|
33
|
+
| onChange | 변경 콜백 |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Switch
|
|
38
|
+
|
|
39
|
+
**controlled 패턴**을 사용한다.
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<Switch value={isOn} onChange={setIsOn} />
|
|
43
|
+
<Switch value={isOn} onChange={setIsOn} type="brand" />
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
| Prop | 설명 |
|
|
47
|
+
|------|------|
|
|
48
|
+
| value | 토글 상태 |
|
|
49
|
+
| onChange | 변경 콜백 |
|
|
50
|
+
| type | 스타일 타입 |
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 의사결정
|
|
55
|
+
|
|
56
|
+
| 상황 | 사용할 것 |
|
|
57
|
+
|------|----------|
|
|
58
|
+
| 다중 선택 | CheckBox |
|
|
59
|
+
| 단일 선택 (여러 옵션 중 하나) | Radio |
|
|
60
|
+
| 켜기/끄기 토글 | Switch |
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# HtmlTypeWriter
|
|
2
|
+
|
|
3
|
+
HTML 문자열을 한 글자씩 타이핑하는 효과를 표시한다. HTML 태그 구조를 유지하면서 텍스트만 순차적으로 렌더한다.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { HtmlTypeWriter } from "@xplat/design-system";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
12
|
+
|------|------|--------|------|
|
|
13
|
+
| html `*` | `string` | — | 타이핑할 HTML 문자열 |
|
|
14
|
+
| duration | `number` | `20` | 글자당 타이핑 간격 (ms) |
|
|
15
|
+
| onDone | `() => void` | — | 타이핑 완료 콜백 |
|
|
16
|
+
| onChange | `() => void` | — | 타이핑 진행 중 매 글자마다 호출 |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 사용 예시
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
<HtmlTypeWriter
|
|
24
|
+
html="<p>안녕하세요. <strong>타이핑</strong> 효과입니다.</p>"
|
|
25
|
+
duration={30}
|
|
26
|
+
onDone={() => console.log("타이핑 완료")}
|
|
27
|
+
/>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 동적 HTML 변경
|
|
31
|
+
|
|
32
|
+
`html` prop이 변경되면 타이핑을 처음부터 다시 시작한다.
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
const [content, setContent] = useState("<p>첫 번째 메시지</p>");
|
|
36
|
+
|
|
37
|
+
<HtmlTypeWriter html={content} onDone={() => setContent("<p>두 번째 메시지</p>")} />
|
|
38
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Input / PasswordInput / TextArea
|
|
2
|
+
|
|
3
|
+
## Input
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
<Input placeholder="이름" />
|
|
7
|
+
<Input type="email" placeholder="이메일" />
|
|
8
|
+
<Input
|
|
9
|
+
type="tel"
|
|
10
|
+
validations={[{ status: "error", message: "필수 항목입니다" }]}
|
|
11
|
+
/>
|
|
12
|
+
<Input suffix={<SearchIcon />} />
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
16
|
+
|------|------|--------|------|
|
|
17
|
+
| type | `"text" \| "number" \| "email" \| "tel"` | `"text"` | 입력 타입 |
|
|
18
|
+
| size | `"sm" \| "md" \| "lg"` | `"md"` | 크기 |
|
|
19
|
+
| validations | `{ status, message }[]` | - | 유효성 검사 |
|
|
20
|
+
| suffix | `ReactNode` | - | 우측 아이콘 |
|
|
21
|
+
|
|
22
|
+
`ref` 전달을 지원한다 (`HTMLInputElement`).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## PasswordInput
|
|
27
|
+
|
|
28
|
+
비밀번호 입력 전용이다. 눈 아이콘으로 비밀번호 표시/숨김을 토글한다.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<PasswordInput placeholder="비밀번호" />
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## TextArea
|
|
37
|
+
|
|
38
|
+
자동 높이 조정을 지원한다. `ref` 전달을 지원한다 (`HTMLTextAreaElement`).
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
<TextArea placeholder="내용을 입력하세요" />
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 상태
|
|
47
|
+
|
|
48
|
+
| 상태 | 설명 |
|
|
49
|
+
|------|------|
|
|
50
|
+
| default | 기본 |
|
|
51
|
+
| hover | 마우스 오버 |
|
|
52
|
+
| focused | 포커스 |
|
|
53
|
+
| typing | 입력 중 |
|
|
54
|
+
| filled | 입력 완료 |
|
|
55
|
+
| disabled | 비활성화 |
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# 내비게이션: Tab / CardTab / Breadcrumb / Pagination / Steps
|
|
2
|
+
|
|
3
|
+
## Tab
|
|
4
|
+
|
|
5
|
+
인덱스 기반 탭이다. 탭 영역만 제공한다.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Tab activeIndex={activeIndex} onChange={setActiveIndex} type="default">
|
|
9
|
+
<Tab.Item>탭1</Tab.Item>
|
|
10
|
+
<Tab.Item>탭2</Tab.Item>
|
|
11
|
+
</Tab>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Prop | 설명 |
|
|
15
|
+
|------|------|
|
|
16
|
+
| activeIndex | 활성 탭 인덱스 (controlled) |
|
|
17
|
+
| type | `"default" \| "toggle"` |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## CardTab
|
|
22
|
+
|
|
23
|
+
값 기반 탭이다. **CardTab.Panel만 children으로 허용한다.**
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
<CardTab tabs={[{ value: "tab1", title: "탭1" }, { value: "tab2", title: "탭2" }]}>
|
|
27
|
+
<CardTab.Panel value="tab1">탭1 내용</CardTab.Panel>
|
|
28
|
+
<CardTab.Panel value="tab2">탭2 내용</CardTab.Panel>
|
|
29
|
+
</CardTab>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Breadcrumb
|
|
35
|
+
|
|
36
|
+
경로를 표시한다.
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<Breadcrumb items={[
|
|
40
|
+
{ label: "홈", href: "/" },
|
|
41
|
+
{ label: "설정", href: "/settings" },
|
|
42
|
+
{ label: "프로필" },
|
|
43
|
+
]} />
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Pagination
|
|
49
|
+
|
|
50
|
+
페이지네이션을 표시한다.
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<Pagination current={page} total={100} onChange={setPage} />
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Steps
|
|
59
|
+
|
|
60
|
+
단계 진행을 표시한다.
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
<Steps
|
|
64
|
+
items={[
|
|
65
|
+
{ title: "정보 입력" },
|
|
66
|
+
{ title: "확인" },
|
|
67
|
+
{ title: "완료" },
|
|
68
|
+
]}
|
|
69
|
+
current={1}
|
|
70
|
+
/>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 의사결정
|
|
76
|
+
|
|
77
|
+
| 상황 | 사용할 것 |
|
|
78
|
+
|------|----------|
|
|
79
|
+
| 탭 영역만 (콘텐츠는 직접 관리) | Tab |
|
|
80
|
+
| 탭 + 패널 콘텐츠 | CardTab |
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# 오버레이: Modal / Drawer / PopOver / Tooltip
|
|
2
|
+
|
|
3
|
+
모두 **controlled 패턴**을 사용한다 (`isOpen`, `onClose`).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Modal
|
|
8
|
+
|
|
9
|
+
중앙 다이얼로그를 표시한다.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
|
|
13
|
+
<h2>제목</h2>
|
|
14
|
+
<p>내용</p>
|
|
15
|
+
</Modal>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Drawer
|
|
21
|
+
|
|
22
|
+
사이드 패널을 표시한다.
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
<Drawer isOpen={isOpen} onClose={handleClose} placement="right" width={400}>
|
|
26
|
+
<p>사이드 패널</p>
|
|
27
|
+
</Drawer>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Prop | 설명 |
|
|
31
|
+
|------|------|
|
|
32
|
+
| placement | `"left" \| "right"` |
|
|
33
|
+
| width | 패널 너비 |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## PopOver
|
|
38
|
+
|
|
39
|
+
트리거 요소 기반 팝오버를 표시한다.
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<PopOver
|
|
43
|
+
isOpen={isOpen}
|
|
44
|
+
onClose={() => setIsOpen(false)}
|
|
45
|
+
trigger={<Button>열기</Button>}
|
|
46
|
+
>
|
|
47
|
+
<p>팝오버 내용</p>
|
|
48
|
+
</PopOver>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Tooltip
|
|
54
|
+
|
|
55
|
+
부가 정보를 표시한다. **description이 필수이다.** children이 트리거이다.
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<Tooltip description="도움말 텍스트">
|
|
59
|
+
<Button>호버하세요</Button>
|
|
60
|
+
</Tooltip>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 의사결정
|
|
66
|
+
|
|
67
|
+
| 상황 | 사용할 것 |
|
|
68
|
+
|------|----------|
|
|
69
|
+
| 전체 화면 차단 (확인/취소) | Modal |
|
|
70
|
+
| 사이드 패널 (상세 정보/폼) | Drawer |
|
|
71
|
+
| 트리거 기반 부가 정보 | PopOver |
|
|
72
|
+
| 간단한 설명 텍스트 | Tooltip |
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Select
|
|
2
|
+
|
|
3
|
+
**Select.Item만 children으로 허용한다.**
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
<Select placeholder="선택하세요" onChange={(value, label) => console.log(value)}>
|
|
7
|
+
<Select.Item value="apple">사과</Select.Item>
|
|
8
|
+
<Select.Item value="banana">바나나</Select.Item>
|
|
9
|
+
</Select>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## onChange
|
|
13
|
+
|
|
14
|
+
`onChange(value: string, label: string)` 형태로 선택된 값과 라벨을 전달한다.
|
|
15
|
+
|
|
16
|
+
## Controlled / Uncontrolled
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
// controlled
|
|
20
|
+
<Select value={selected} onChange={(v) => setSelected(v)}>
|
|
21
|
+
<Select.Item value="a">A</Select.Item>
|
|
22
|
+
</Select>
|
|
23
|
+
|
|
24
|
+
// uncontrolled
|
|
25
|
+
<Select defaultValue="a">
|
|
26
|
+
<Select.Item value="a">A</Select.Item>
|
|
27
|
+
</Select>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 상태
|
|
31
|
+
|
|
32
|
+
| 상태 | 설명 |
|
|
33
|
+
|------|------|
|
|
34
|
+
| error | 에러 표시 |
|
|
35
|
+
| disabled | 비활성화 |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 유사 컴포넌트 구분
|
|
40
|
+
|
|
41
|
+
| 목적 | 사용할 것 |
|
|
42
|
+
|------|----------|
|
|
43
|
+
| 값 선택 (onChange) | Select |
|
|
44
|
+
| 액션 메뉴 (onClick per item) | Dropdown |
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Swiper
|
|
2
|
+
|
|
3
|
+
슬라이더/캐러셀을 표시한다. 드래그, 자동 재생, 루프를 지원하며 controlled/uncontrolled 모두 가능하다.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Swiper } from "@xplat/design-system";
|
|
7
|
+
import type { SwiperHandle } from "@xplat/design-system";
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Props
|
|
11
|
+
|
|
12
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
13
|
+
|------|------|--------|------|
|
|
14
|
+
| renderItems | `ReactNode[]` | `[]` | 슬라이드 아이템 배열 |
|
|
15
|
+
| viewItemCount | `number` | `1` | 한 번에 보이는 아이템 수 |
|
|
16
|
+
| maxItems | `number` | — | 최대 아이템 수 (초과 시 잘림) |
|
|
17
|
+
| spaceBetween | `number` | `16` | 슬라이드 간격 (px) |
|
|
18
|
+
| speed | `number` | `300` | 전환 속도 (ms) |
|
|
19
|
+
| slideBy | `number` | `1` | 한 번에 이동할 슬라이드 수 |
|
|
20
|
+
| auto | `boolean` | `false` | 자동 슬라이딩 |
|
|
21
|
+
| autoplayDelay | `number` | `3000` | 오토플레이 간격 (ms) |
|
|
22
|
+
| loop | `boolean` | `false` | 무한 루프 |
|
|
23
|
+
| showProgress | `boolean` | `false` | 진행바 표시 |
|
|
24
|
+
| index | `number` | — | 현재 인덱스 (controlled) |
|
|
25
|
+
| onChange | `(index: number) => void` | — | 슬라이드 변경 콜백 |
|
|
26
|
+
| swiperRef | `RefObject<SwiperHandle>` | — | 명령형 제어 ref |
|
|
27
|
+
|
|
28
|
+
### SwiperHandle
|
|
29
|
+
|
|
30
|
+
| 메서드 | 설명 |
|
|
31
|
+
|--------|------|
|
|
32
|
+
| `slidePrev()` | 이전 슬라이드로 이동 |
|
|
33
|
+
| `slideNext()` | 다음 슬라이드로 이동 |
|
|
34
|
+
| `slideTo(index)` | 특정 인덱스로 이동 |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 사용 예시
|
|
39
|
+
|
|
40
|
+
### 기본
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
<Swiper
|
|
44
|
+
renderItems={[
|
|
45
|
+
<img src="/img1.jpg" />,
|
|
46
|
+
<img src="/img2.jpg" />,
|
|
47
|
+
<img src="/img3.jpg" />,
|
|
48
|
+
]}
|
|
49
|
+
/>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 자동 재생 + 루프 + 진행바
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<Swiper
|
|
56
|
+
renderItems={slides}
|
|
57
|
+
auto
|
|
58
|
+
loop
|
|
59
|
+
showProgress
|
|
60
|
+
autoplayDelay={5000}
|
|
61
|
+
/>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 명령형 제어
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
const ref = useRef<SwiperHandle>(null);
|
|
68
|
+
|
|
69
|
+
<Swiper swiperRef={ref} renderItems={slides} />
|
|
70
|
+
|
|
71
|
+
<button onClick={() => ref.current?.slidePrev()}>이전</button>
|
|
72
|
+
<button onClick={() => ref.current?.slideNext()}>다음</button>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 다중 아이템 뷰
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
<Swiper
|
|
79
|
+
renderItems={cards}
|
|
80
|
+
viewItemCount={3}
|
|
81
|
+
spaceBetween={24}
|
|
82
|
+
slideBy={3}
|
|
83
|
+
/>
|
|
84
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Table
|
|
2
|
+
|
|
3
|
+
**반드시 `Table > TableHead/TableBody > TableRow > TableCell` 구조를 따른다.**
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
<Table>
|
|
7
|
+
<TableHead>
|
|
8
|
+
<TableRow>
|
|
9
|
+
<TableCell>이름</TableCell>
|
|
10
|
+
<TableCell>나이</TableCell>
|
|
11
|
+
</TableRow>
|
|
12
|
+
</TableHead>
|
|
13
|
+
<TableBody>
|
|
14
|
+
<TableRow>
|
|
15
|
+
<TableCell>홍길동</TableCell>
|
|
16
|
+
<TableCell>30</TableCell>
|
|
17
|
+
</TableRow>
|
|
18
|
+
</TableBody>
|
|
19
|
+
</Table>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Props
|
|
23
|
+
|
|
24
|
+
| Prop | 설명 |
|
|
25
|
+
|------|------|
|
|
26
|
+
| headerSticky | 헤더 고정 |
|
|
27
|
+
| isSticky | 특정 셀 고정 |
|
|
28
|
+
|
|
29
|
+
## TableRow type
|
|
30
|
+
|
|
31
|
+
| type | 용도 |
|
|
32
|
+
|------|------|
|
|
33
|
+
| primary | 기본 행 |
|
|
34
|
+
| secondary | 보조 행 (배경색 구분) |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 올바른 예시
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
<Table headerSticky>
|
|
42
|
+
<TableHead>
|
|
43
|
+
<TableRow>
|
|
44
|
+
<TableCell isSticky>이름</TableCell>
|
|
45
|
+
<TableCell>부서</TableCell>
|
|
46
|
+
<TableCell>직급</TableCell>
|
|
47
|
+
</TableRow>
|
|
48
|
+
</TableHead>
|
|
49
|
+
<TableBody>
|
|
50
|
+
<TableRow type="primary">
|
|
51
|
+
<TableCell isSticky>홍길동</TableCell>
|
|
52
|
+
<TableCell>개발팀</TableCell>
|
|
53
|
+
<TableCell>선임</TableCell>
|
|
54
|
+
</TableRow>
|
|
55
|
+
<TableRow type="secondary">
|
|
56
|
+
<TableCell isSticky>김철수</TableCell>
|
|
57
|
+
<TableCell>디자인팀</TableCell>
|
|
58
|
+
<TableCell>책임</TableCell>
|
|
59
|
+
</TableRow>
|
|
60
|
+
</TableBody>
|
|
61
|
+
</Table>
|
|
62
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Grid 시스템
|
|
2
|
+
|
|
3
|
+
페이지 레이아웃과 컴포넌트 내부 배치 모두 Grid를 사용한다.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { FullGrid, FullScreen, GridItem } from "@x-plat/design-system/layout";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## 컴포넌트
|
|
10
|
+
|
|
11
|
+
| 컴포넌트 | 용도 |
|
|
12
|
+
|---------|------|
|
|
13
|
+
| FullGrid | 12컬럼 그리드 컨테이너 |
|
|
14
|
+
| FullScreen | 전체 화면 그리드 |
|
|
15
|
+
| GridItem | 그리드 아이템 |
|
|
16
|
+
|
|
17
|
+
## gap
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
<FullGrid gap={16}>
|
|
21
|
+
<GridItem column={6}>왼쪽</GridItem>
|
|
22
|
+
<GridItem column={6}>오른쪽</GridItem>
|
|
23
|
+
</FullGrid>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 반응형 브레이크포인트
|
|
29
|
+
|
|
30
|
+
| 브레이크포인트 | 범위 | 최대 컬럼 |
|
|
31
|
+
|---------------|------|-----------|
|
|
32
|
+
| laptop (default) | 1024px ~ | 12 |
|
|
33
|
+
| tablet | 768px ~ 1024px | 8 |
|
|
34
|
+
| mobile | ~ 768px | 4 |
|
|
35
|
+
|
|
36
|
+
## Column 상속 규칙
|
|
37
|
+
|
|
38
|
+
하위 브레이크포인트를 지정하지 않으면 상위 값을 상속한다.
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
<GridItem column={{ default: 6, tablet: 4, mobile: 4 }}>
|
|
42
|
+
내용
|
|
43
|
+
</GridItem>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 위젯 패턴
|
|
49
|
+
|
|
50
|
+
### 대시보드
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<FullGrid>
|
|
54
|
+
<GridItem column={{ default: 4, tablet: 4, mobile: 4 }}>
|
|
55
|
+
<Card>위젯 A</Card>
|
|
56
|
+
</GridItem>
|
|
57
|
+
<GridItem column={{ default: 4, tablet: 4, mobile: 4 }}>
|
|
58
|
+
<Card>위젯 B</Card>
|
|
59
|
+
</GridItem>
|
|
60
|
+
<GridItem column={{ default: 4, tablet: 8, mobile: 4 }}>
|
|
61
|
+
<Card>위젯 C</Card>
|
|
62
|
+
</GridItem>
|
|
63
|
+
</FullGrid>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 폼
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<FullGrid>
|
|
70
|
+
<GridItem column={{ default: 6, tablet: 4, mobile: 4 }}>
|
|
71
|
+
<Input placeholder="이름" />
|
|
72
|
+
</GridItem>
|
|
73
|
+
<GridItem column={{ default: 6, tablet: 4, mobile: 4 }}>
|
|
74
|
+
<Input placeholder="이메일" type="email" />
|
|
75
|
+
</GridItem>
|
|
76
|
+
<GridItem column={{ default: 12, tablet: 8, mobile: 4 }}>
|
|
77
|
+
<Button type="primary">저장</Button>
|
|
78
|
+
</GridItem>
|
|
79
|
+
</FullGrid>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 중첩 Grid
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
<Card title="사용자 정보">
|
|
86
|
+
<FullGrid>
|
|
87
|
+
<GridItem column={{ default: 3, tablet: 2, mobile: 4 }}>
|
|
88
|
+
<Avatar name="홍길동" size="lg" />
|
|
89
|
+
</GridItem>
|
|
90
|
+
<GridItem column={{ default: 9, tablet: 6, mobile: 4 }}>
|
|
91
|
+
<Input placeholder="이름" />
|
|
92
|
+
</GridItem>
|
|
93
|
+
</FullGrid>
|
|
94
|
+
</Card>
|
|
95
|
+
```
|