@makitt.io/mds-mcp-server 0.1.2 → 0.2.0
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/README.md +142 -41
- package/dist/catalog.d.ts +16 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +383 -0
- package/dist/catalog.js.map +1 -0
- package/dist/data/catalog.json +42535 -5019
- package/dist/data/playbook/ai-fill.md +62 -49
- package/dist/data/playbook/anti-patterns.md +112 -110
- package/dist/data/playbook/array-input.md +95 -50
- package/dist/data/playbook/async-states.md +71 -61
- package/dist/data/playbook/data-grid.md +177 -80
- package/dist/data/playbook/feedback.md +107 -88
- package/dist/data/playbook/form.md +164 -134
- package/dist/data/playbook/overlay.md +98 -89
- package/dist/data/playbook/page-layout.md +96 -77
- package/dist/data/playbook/responsive-tokens.md +78 -59
- package/dist/data/recipes/admin-list-page.md +86 -0
- package/dist/data/recipes/async-state-section.md +60 -0
- package/dist/data/recipes/dashboard-overview.md +65 -0
- package/dist/data/recipes/detail-drawer.md +69 -0
- package/dist/data/recipes/modal-form.md +67 -0
- package/dist/data/recipes/settings-form-page.md +79 -0
- package/dist/index.d.ts +4 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -339
- package/dist/index.js.map +1 -1
- package/dist/loaders.d.ts +8 -0
- package/dist/loaders.d.ts.map +1 -0
- package/dist/loaders.js +120 -0
- package/dist/loaders.js.map +1 -0
- package/dist/recipes.d.ts +13 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +82 -0
- package/dist/recipes.js.map +1 -0
- package/dist/responses.d.ts +8 -0
- package/dist/responses.d.ts.map +1 -0
- package/dist/responses.js +25 -0
- package/dist/responses.js.map +1 -0
- package/dist/text.d.ts +4 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +20 -0
- package/dist/text.js.map +1 -0
- package/dist/tool-definitions.d.ts +3 -0
- package/dist/tool-definitions.d.ts.map +1 -0
- package/dist/tool-definitions.js +199 -0
- package/dist/tool-definitions.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +233 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +107 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +20 -16
|
@@ -1,95 +1,96 @@
|
|
|
1
1
|
# MDS Playbook — Overlay (Modal / Drawer / Sheet / Dialog / Popover)
|
|
2
2
|
|
|
3
|
-
화면 위 떠다니는 컨테이너
|
|
3
|
+
화면 위 떠다니는 컨테이너 선택 가이드.
|
|
4
4
|
|
|
5
|
-
> mds 의 overlay 군 — **Modal / Drawer / Sheet / Dialog / Popover** 5종.
|
|
6
|
-
>
|
|
5
|
+
> mds 의 overlay 군 — **Modal / Drawer / Sheet / Dialog / Popover** 5종. 각자
|
|
6
|
+
> 의도 분명. 헷갈리면 잘못된 mental model.
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
## 1. 5 Overlay 의도 분리
|
|
11
11
|
|
|
12
|
-
| Overlay
|
|
13
|
-
|
|
14
|
-
| **Modal**
|
|
15
|
-
| **Drawer**
|
|
16
|
-
| **Sheet**
|
|
17
|
-
| **Dialog**
|
|
18
|
-
| **Popover** | **inline 부가 정보 / 작은 picker**
|
|
12
|
+
| Overlay | 의도 | mental model | 사용 예 |
|
|
13
|
+
| ----------- | ---------------------------------------------------- | ---------------------- | ------------------------------------------------- |
|
|
14
|
+
| **Modal** | **메인 작업 중단 + 작은 sub-task** (form 입력, 확인) | 페이지 위 작은 창 | 회원 생성, 쿠폰 발급, 설정 변경 |
|
|
15
|
+
| **Drawer** | **목록 컨텍스트 유지 + side-by-side 편집** | 메인 옆 슬라이드 | 주문 행 클릭 → drawer 에서 상세, variant 편집 |
|
|
16
|
+
| **Sheet** | **모바일 bottom 시트** (mobile-friendly drawer) | 아래에서 올라오는 시트 | 모바일 의 모든 overlay (Modal / Drawer auto 변환) |
|
|
17
|
+
| **Dialog** | **확인 / 알림 / prompt** (form 아님, action 만) | 짧은 결정 강제 | "정말 삭제?", "환불 처리하시겠습니까?" |
|
|
18
|
+
| **Popover** | **inline 부가 정보 / 작은 picker** | trigger 옆 floating | DatePicker, ColorPicker, dropdown menu |
|
|
19
19
|
|
|
20
20
|
### 결정 기준
|
|
21
21
|
|
|
22
|
-
| 의도
|
|
23
|
-
|
|
24
|
-
| Form 입력 필요 (sub-entity 생성 / 수정) | Modal (페이지 작업 X) 또는 Drawer (목록 컨텍스트 유지)
|
|
25
|
-
| 확인 / 경고 / 짧은 prompt
|
|
26
|
-
| 목록 + 행 클릭 → 상세
|
|
27
|
-
| 모바일 first
|
|
28
|
-
| inline trigger 옆 작은 UI
|
|
22
|
+
| 의도 | overlay |
|
|
23
|
+
| --------------------------------------- | --------------------------------------------------------- |
|
|
24
|
+
| Form 입력 필요 (sub-entity 생성 / 수정) | Modal (페이지 작업 X) 또는 Drawer (목록 컨텍스트 유지) |
|
|
25
|
+
| 확인 / 경고 / 짧은 prompt | Dialog (`Modal.confirm` / `Modal.alert` / `Modal.prompt`) |
|
|
26
|
+
| 목록 + 행 클릭 → 상세 | Drawer |
|
|
27
|
+
| 모바일 first | Sheet |
|
|
28
|
+
| inline trigger 옆 작은 UI | Popover |
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
32
32
|
## 2. 선택 표 (lookup)
|
|
33
33
|
|
|
34
|
-
| 케이스
|
|
35
|
-
|
|
36
|
-
| "고객 새로 만들기 from 페이지"
|
|
37
|
-
| "고객 행 클릭 → 상세 편집"
|
|
38
|
-
| "정말 삭제?"
|
|
39
|
-
| "환불 처리하시겠습니까?" + 사유 입력 | `Modal.prompt` (Dialog with input)
|
|
40
|
-
| "라이선스 만료 임박" 영속 알림
|
|
41
|
-
| "DatePicker / TimePicker"
|
|
42
|
-
| "DropdownMenu"
|
|
43
|
-
| "큰 form (상품 등록)"
|
|
44
|
-
| "모바일 의 form"
|
|
45
|
-
| "Variant 추가 in 상품 등록 form"
|
|
34
|
+
| 케이스 | 답 |
|
|
35
|
+
| ------------------------------------ | --------------------------------------- |
|
|
36
|
+
| "고객 새로 만들기 from 페이지" | Modal (sub-task) |
|
|
37
|
+
| "고객 행 클릭 → 상세 편집" | Drawer (목록 컨텍스트 유지) |
|
|
38
|
+
| "정말 삭제?" | `Modal.confirm` (Dialog) |
|
|
39
|
+
| "환불 처리하시겠습니까?" + 사유 입력 | `Modal.prompt` (Dialog with input) |
|
|
40
|
+
| "라이선스 만료 임박" 영속 알림 | Banner (Step 4.2 feedback) — Modal 아님 |
|
|
41
|
+
| "DatePicker / TimePicker" | Popover (자체 컴포넌트가 사용) |
|
|
42
|
+
| "DropdownMenu" | Popover (Menu.\* 사용) |
|
|
43
|
+
| "큰 form (상품 등록)" | page-form (overlay 아님) |
|
|
44
|
+
| "모바일 의 form" | Sheet 또는 full-screen page-form |
|
|
45
|
+
| "Variant 추가 in 상품 등록 form" | nested Drawer (modal 안 modal 금지) |
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
49
|
## 3. Modal — sub-task 표준
|
|
50
50
|
|
|
51
|
-
| Slot
|
|
52
|
-
|
|
53
|
-
| Trigger
|
|
54
|
-
| Root
|
|
55
|
-
| Overlay (backdrop) | `Modal.Overlay` (자동)
|
|
56
|
-
| Container
|
|
57
|
-
| Header
|
|
58
|
-
| Body
|
|
59
|
-
| Footer
|
|
51
|
+
| Slot | mds 컴포넌트 |
|
|
52
|
+
| ------------------ | ------------------------------------------------------------- |
|
|
53
|
+
| Trigger | imperative API (`Modal.open(...)`) — overlay 가 stack-managed |
|
|
54
|
+
| Root | `Modal.Root` (Radix Dialog 의 wrapper) |
|
|
55
|
+
| Overlay (backdrop) | `Modal.Overlay` (자동) |
|
|
56
|
+
| Container | `Modal.Content` (centered, size variant) |
|
|
57
|
+
| Header | `Modal.Header` (title + close button) |
|
|
58
|
+
| Body | `Modal.Body` |
|
|
59
|
+
| Footer | `Modal.Footer` (cancel + confirm primary, 우측 정렬) |
|
|
60
60
|
|
|
61
61
|
### Size variant
|
|
62
62
|
|
|
63
|
-
| Size
|
|
64
|
-
|
|
65
|
-
| xs
|
|
66
|
-
| sm
|
|
67
|
-
| md (default) | 480px | 기본 form
|
|
68
|
-
| lg
|
|
69
|
-
| xl
|
|
63
|
+
| Size | Width | 사용 |
|
|
64
|
+
| ------------ | ----- | ------------------------- |
|
|
65
|
+
| xs | 320px | 짧은 confirm dialog |
|
|
66
|
+
| sm | 400px | 단순 form (3-5 필드) |
|
|
67
|
+
| md (default) | 480px | 기본 form |
|
|
68
|
+
| lg | 640px | 복잡 form / 데이터 list |
|
|
69
|
+
| xl | 800px | 대형 (편집기 / 설정 다단) |
|
|
70
70
|
|
|
71
|
-
> Mobile 변형 — md 이상 = full-screen Sheet (자동 변환 — Step 3.4 의
|
|
71
|
+
> Mobile 변형 — md 이상 = full-screen Sheet (자동 변환 — Step 3.4 의
|
|
72
|
+
> useBreakpoint 활용)
|
|
72
73
|
|
|
73
74
|
---
|
|
74
75
|
|
|
75
76
|
## 4. Drawer — 목록 컨텍스트 표준
|
|
76
77
|
|
|
77
|
-
| Slot
|
|
78
|
-
|
|
79
|
-
| Trigger
|
|
80
|
-
| Root
|
|
81
|
-
| Container | `Drawer.Content` (side variant)
|
|
82
|
-
| Header
|
|
83
|
-
| Body
|
|
84
|
-
| Footer
|
|
78
|
+
| Slot | mds 컴포넌트 |
|
|
79
|
+
| --------- | --------------------------------------------- |
|
|
80
|
+
| Trigger | row click handler (의도된 사용) |
|
|
81
|
+
| Root | `Drawer.Root` |
|
|
82
|
+
| Container | `Drawer.Content` (side variant) |
|
|
83
|
+
| Header | `Drawer.Header` (title + close) |
|
|
84
|
+
| Body | `Drawer.Body` (scroll) |
|
|
85
|
+
| Footer | `Drawer.Footer` (action — Modal 과 동일 패턴) |
|
|
85
86
|
|
|
86
87
|
### Side variant
|
|
87
88
|
|
|
88
|
-
| Side
|
|
89
|
-
|
|
90
|
-
| right (default) | 메인 옆 슬라이드 in (가장 일반)
|
|
91
|
-
| left
|
|
92
|
-
| top / bottom
|
|
89
|
+
| Side | 사용 | Default size |
|
|
90
|
+
| --------------- | --------------------------------- | ---------------------------------------- |
|
|
91
|
+
| right (default) | 메인 옆 슬라이드 in (가장 일반) | 480px (--size-drawer-default-horizontal) |
|
|
92
|
+
| left | 별 사용 안 함 (sidebar 와 헷갈림) | 480px |
|
|
93
|
+
| top / bottom | 모바일 bottom Sheet / 알림 | 320px (--size-drawer-default-vertical) |
|
|
93
94
|
|
|
94
95
|
### Drawer vs Modal 결정
|
|
95
96
|
|
|
@@ -127,17 +128,18 @@ const reason = await Modal.prompt({
|
|
|
127
128
|
});
|
|
128
129
|
```
|
|
129
130
|
|
|
130
|
-
> mds 의 ConfirmDialog / AlertDialog / PromptDialog — `imperative API`
|
|
131
|
+
> mds 의 ConfirmDialog / AlertDialog / PromptDialog — `imperative API`
|
|
132
|
+
> (forwardRef-required 룰 예외).
|
|
131
133
|
|
|
132
134
|
---
|
|
133
135
|
|
|
134
136
|
## 6. Popover — inline floating
|
|
135
137
|
|
|
136
|
-
| Slot
|
|
137
|
-
|
|
138
|
+
| Slot | mds 컴포넌트 |
|
|
139
|
+
| ------- | ---------------------------------------------- |
|
|
138
140
|
| Trigger | `Popover.Trigger` (자체 컴포넌트 또는 asChild) |
|
|
139
|
-
| Content | `Popover.Content` (자동 positioning by Radix)
|
|
140
|
-
| Arrow
|
|
141
|
+
| Content | `Popover.Content` (자동 positioning by Radix) |
|
|
142
|
+
| Arrow | `Popover.Arrow` (선택) |
|
|
141
143
|
|
|
142
144
|
### Popover vs Modal
|
|
143
145
|
|
|
@@ -150,33 +152,35 @@ const reason = await Modal.prompt({
|
|
|
150
152
|
|
|
151
153
|
### 허용 합성
|
|
152
154
|
|
|
153
|
-
| 합성
|
|
154
|
-
|
|
155
|
-
| Modal 안 Form
|
|
156
|
-
| Drawer 안 Form
|
|
157
|
-
| Modal 안 Popover
|
|
158
|
-
| Drawer 안 Popover | 동일
|
|
155
|
+
| 합성 | 사용 |
|
|
156
|
+
| ----------------- | ------------------------------------------------------------ |
|
|
157
|
+
| Modal 안 Form | sub-task 의 form (modal-form) |
|
|
158
|
+
| Drawer 안 Form | 목록 옆 편집 (drawer-form) |
|
|
159
|
+
| Modal 안 Popover | DatePicker / DropdownMenu 가 modal 안 ok |
|
|
160
|
+
| Drawer 안 Popover | 동일 |
|
|
159
161
|
| **nested Drawer** | 메인 form (page or drawer) 안 sub-entity 편집 (variant 추가) |
|
|
160
162
|
|
|
161
163
|
### 절대 금지
|
|
162
164
|
|
|
163
165
|
- ❌ **Modal 안 Modal** — 3단 mental stack. drawer 또는 페이지 이동
|
|
164
166
|
- ❌ **Drawer 안 Drawer** — 동일 이유
|
|
165
|
-
- ❌ **Modal 안 Drawer** / **Drawer 안 Modal** — sub-overlay 의 layer / focus
|
|
166
|
-
|
|
167
|
+
- ❌ **Modal 안 Drawer** / **Drawer 안 Modal** — sub-overlay 의 layer / focus
|
|
168
|
+
충돌
|
|
169
|
+
- ❌ **Popover 안 Popover** — Radix Popover Root 의 자식이 또 다른 Popover
|
|
170
|
+
(auto-position 충돌)
|
|
167
171
|
|
|
168
172
|
---
|
|
169
173
|
|
|
170
174
|
## 8. Mobile 변형
|
|
171
175
|
|
|
172
|
-
| Desktop
|
|
173
|
-
|
|
174
|
-
| Modal (xs / sm)
|
|
175
|
-
| Modal (md+)
|
|
176
|
+
| Desktop | Mobile (< md) |
|
|
177
|
+
| --------------------- | ------------------------------ |
|
|
178
|
+
| Modal (xs / sm) | 그대로 (작아서 모바일 OK) |
|
|
179
|
+
| Modal (md+) | full-screen Sheet 또는 그대로 |
|
|
176
180
|
| Drawer (right / left) | bottom Sheet (`side="bottom"`) |
|
|
177
|
-
| Sheet
|
|
178
|
-
| Dialog
|
|
179
|
-
| Popover
|
|
181
|
+
| Sheet | 그대로 |
|
|
182
|
+
| Dialog | 그대로 |
|
|
183
|
+
| Popover | 그대로 (자체 positioning) |
|
|
180
184
|
|
|
181
185
|
> Mobile 변환 mechanism — `useIsBreakpointUp('md')` hook 으로 caller 가 명시.
|
|
182
186
|
> 자동 변환 — mds 의 SheetAdapter 추가 (TBD).
|
|
@@ -186,7 +190,8 @@ const reason = await Modal.prompt({
|
|
|
186
190
|
## 9. 안티 패턴
|
|
187
191
|
|
|
188
192
|
- ❌ Modal 안 Modal (nested form 강제)
|
|
189
|
-
- ❌ Dialog (`Modal.confirm`) 안 form (input multiple) — `Modal.prompt` 또는
|
|
193
|
+
- ❌ Dialog (`Modal.confirm`) 안 form (input multiple) — `Modal.prompt` 또는
|
|
194
|
+
form Modal 사용
|
|
190
195
|
- ❌ Popover 안 큰 form — Popover 의 의도 (작은 inline) 아님
|
|
191
196
|
- ❌ Drawer 의 width 변경 (사용자 resize 가능) — caller 가 fix size
|
|
192
197
|
- ❌ Modal close 시 force confirmation 없음 — `isDirty` 시 confirm
|
|
@@ -196,20 +201,22 @@ const reason = await Modal.prompt({
|
|
|
196
201
|
|
|
197
202
|
## 10. Cross-cutting
|
|
198
203
|
|
|
199
|
-
| Axis
|
|
200
|
-
|
|
201
|
-
| **Responsive**
|
|
202
|
-
| **A11y**
|
|
204
|
+
| Axis | 적용 |
|
|
205
|
+
| ------------------ | ----------------------------------------------------------------------- |
|
|
206
|
+
| **Responsive** | useIsBreakpointUp + side 변환 |
|
|
207
|
+
| **A11y** | Radix Dialog 기반 — focus trap / aria / esc 자동 |
|
|
203
208
|
| **Imperative API** | Modal.confirm / Modal.open — overlay stack 관리 (caller 가 ref 안 받음) |
|
|
204
|
-
| **Telemetry**
|
|
209
|
+
| **Telemetry** | overlay 의 open/close 추적 (Step 7) |
|
|
205
210
|
|
|
206
211
|
---
|
|
207
212
|
|
|
208
213
|
## 11. TBD
|
|
209
214
|
|
|
210
|
-
1. **SheetAdapter 자동 변환** — `<Modal>` 가 mobile 에서 `<Sheet>` 자동 변환
|
|
215
|
+
1. **SheetAdapter 자동 변환** — `<Modal>` 가 mobile 에서 `<Sheet>` 자동 변환
|
|
216
|
+
컴포넌트 추가 여부
|
|
211
217
|
2. **isDirty 감지** — form 안 dirty 자동 confirm dialog (RHF 의 isDirty 의존)
|
|
212
|
-
3. **Modal stacking** 최대 depth — 1 default, 2 까지 허용? (현재 nested Drawer
|
|
218
|
+
3. **Modal stacking** 최대 depth — 1 default, 2 까지 허용? (현재 nested Drawer
|
|
219
|
+
만)
|
|
213
220
|
4. **Drawer resize handle** — 사용자 resize 가능 vs caller fix
|
|
214
221
|
5. **Sheet 의 default snap point** — 30% / 60% / 100% (Vaul 같은 패턴)
|
|
215
222
|
|
|
@@ -218,5 +225,7 @@ const reason = await Modal.prompt({
|
|
|
218
225
|
## Related Playbooks
|
|
219
226
|
|
|
220
227
|
- [form.md](./form.md) — Modal-form / Drawer-form / nested-drawer (Step 4.1)
|
|
221
|
-
- [feedback.md](./feedback.md) — Toast / Notification / Banner / Modal Dialog
|
|
222
|
-
|
|
228
|
+
- [feedback.md](./feedback.md) — Toast / Notification / Banner / Modal Dialog
|
|
229
|
+
(Step 4.2)
|
|
230
|
+
- [page-layout.md](./page-layout.md) — Page Shell / Sidebar 와 overlay 관계
|
|
231
|
+
(Step 4.5)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# MDS Playbook — Page Layout (Shell / Sidebar / PageHeader / padding / max-width)
|
|
2
2
|
|
|
3
|
-
페이지
|
|
3
|
+
페이지 layout 에 대한 약속.
|
|
4
4
|
|
|
5
|
-
> 모든 셀러 admin 페이지가 **같은 layout structure** 따라야 균일. mds 의 shells
|
|
5
|
+
> 모든 셀러 admin 페이지가 **같은 layout structure** 따라야 균일. mds 의 shells
|
|
6
|
+
> 활용.
|
|
6
7
|
|
|
7
8
|
---
|
|
8
9
|
|
|
@@ -20,14 +21,14 @@
|
|
|
20
21
|
</AppShell>
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
| Shell 컴포넌트
|
|
24
|
-
|
|
25
|
-
| `AppShell`
|
|
26
|
-
| `Sidebar`
|
|
27
|
-
| `Topbar` (선택)
|
|
28
|
-
| `Page`
|
|
29
|
-
| `PageHeader`
|
|
30
|
-
| `Section` (선택) | content 안 의미 단위 분할
|
|
24
|
+
| Shell 컴포넌트 | 역할 | 위치 |
|
|
25
|
+
| ---------------- | ---------------------------------------- | --------------------------- |
|
|
26
|
+
| `AppShell` | top-level wrapper (Sidebar + Page) | route layout (Next.js) |
|
|
27
|
+
| `Sidebar` | nav menu (sticky left) | desktop left, mobile drawer |
|
|
28
|
+
| `Topbar` (선택) | global header (logo / user / breadcrumb) | top sticky |
|
|
29
|
+
| `Page` | content area | sidebar 우측 |
|
|
30
|
+
| `PageHeader` | title + breadcrumb + actions | content 상단 |
|
|
31
|
+
| `Section` (선택) | content 안 의미 단위 분할 | Page 안 |
|
|
31
32
|
|
|
32
33
|
---
|
|
33
34
|
|
|
@@ -35,19 +36,21 @@
|
|
|
35
36
|
|
|
36
37
|
### 결정 표
|
|
37
38
|
|
|
38
|
-
| 페이지 종류
|
|
39
|
-
|
|
40
|
-
| **DataGrid list 페이지** (customers / orders)
|
|
41
|
-
| **단순 form 페이지** (회원가입 / 단일 entity)
|
|
42
|
-
| **복잡 form 페이지** (상품 등록 — Section + AnchorNav) | **content 자체 max-width X**, AnchorNav 좌측 + form 우측 (둘 다 fill) | 큰 form 은 넓은 공간 활용
|
|
43
|
-
| **분석 / dashboard** (KPI + chart)
|
|
44
|
-
| **정보 페이지** (about / docs / blog)
|
|
39
|
+
| 페이지 종류 | max-width | 이유 |
|
|
40
|
+
| ------------------------------------------------------ | --------------------------------------------------------------------- | ---------------------------------------------- |
|
|
41
|
+
| **DataGrid list 페이지** (customers / orders) | **full-bleed** (max-width X) | table 의 column 다 보임. 큰 모니터에서 더 좋음 |
|
|
42
|
+
| **단순 form 페이지** (회원가입 / 단일 entity) | **640px** (modal-sm 와 같음) | 가독성 (긴 가로 input 어색) |
|
|
43
|
+
| **복잡 form 페이지** (상품 등록 — Section + AnchorNav) | **content 자체 max-width X**, AnchorNav 좌측 + form 우측 (둘 다 fill) | 큰 form 은 넓은 공간 활용 |
|
|
44
|
+
| **분석 / dashboard** (KPI + chart) | **full-bleed** | grid layout 의 cols 활용 |
|
|
45
|
+
| **정보 페이지** (about / docs / blog) | **800-960px** | 글 가독성 |
|
|
45
46
|
|
|
46
47
|
→ **default = full-bleed**. 가독성 필요한 경우 (form / 정보) 만 max-width.
|
|
47
48
|
|
|
48
49
|
### 이전 발견 (apps/web 의 max-width 답답함)
|
|
49
50
|
|
|
50
|
-
기존 apps/web 의 content 가 `max-w-7xl` (1280px) 같은 작은 fix → 1920px+
|
|
51
|
+
기존 apps/web 의 content 가 `max-w-7xl` (1280px) 같은 작은 fix → 1920px+
|
|
52
|
+
모니터에서 양쪽 빔. **수정 필요**:
|
|
53
|
+
|
|
51
54
|
- DataGrid 페이지 → full-bleed
|
|
52
55
|
- form 페이지 → 명시적 max-width (640 or 800)
|
|
53
56
|
|
|
@@ -55,25 +58,26 @@
|
|
|
55
58
|
|
|
56
59
|
## 3. Padding 표준
|
|
57
60
|
|
|
58
|
-
| Level
|
|
59
|
-
|
|
60
|
-
| Page (content area 의 outer) | `var(--space-6)` ~ `var(--space-8)` (24~32px)
|
|
61
|
-
| Page (mobile)
|
|
62
|
-
| Section gap
|
|
63
|
-
| Card padding
|
|
64
|
-
| Form 안 row gap
|
|
61
|
+
| Level | Padding token | 사용 |
|
|
62
|
+
| ---------------------------- | ---------------------------------------------------- | ------------ |
|
|
63
|
+
| Page (content area 의 outer) | `var(--space-6)` ~ `var(--space-8)` (24~32px) | desktop |
|
|
64
|
+
| Page (mobile) | `var(--space-4)` (16px) | mobile |
|
|
65
|
+
| Section gap | `var(--section-gap)` (theme 별 — admin-light = 48px) | section 사이 |
|
|
66
|
+
| Card padding | `var(--space-4)` (16px) — default | Card 안 |
|
|
67
|
+
| Form 안 row gap | `var(--space-3)` (12px) | field 사이 |
|
|
65
68
|
|
|
66
|
-
> Padding 의 mobile 자동 — Page shell 의 prop 또는 SCSS
|
|
69
|
+
> Padding 의 mobile 자동 — Page shell 의 prop 또는 SCSS
|
|
70
|
+
> `@media (max-width: 768px)` 분기.
|
|
67
71
|
|
|
68
72
|
---
|
|
69
73
|
|
|
70
74
|
## 4. Sidebar — desktop vs mobile
|
|
71
75
|
|
|
72
|
-
| State
|
|
73
|
-
|
|
74
|
-
| 항상 표시
|
|
75
|
-
| Collapsed (icon only) | `Sidebar collapsed`
|
|
76
|
-
| Active route
|
|
76
|
+
| State | Desktop | Mobile |
|
|
77
|
+
| --------------------- | ----------------------------------------------------------------------- | -------------------------------------- |
|
|
78
|
+
| 항상 표시 | `Sidebar` (sticky left) | drawer (top trigger 의 hamburger menu) |
|
|
79
|
+
| Collapsed (icon only) | `Sidebar collapsed` | drawer + 그대로 |
|
|
80
|
+
| Active route | `Sidebar.SubItem` 의 `data-active="true"` (Sidebar.subItemActive style) | drawer 안 동일 |
|
|
77
81
|
|
|
78
82
|
> Mobile 변환 — `useIsBreakpointUp('lg')` (1024px) — 그 미만 = drawer.
|
|
79
83
|
|
|
@@ -95,15 +99,16 @@
|
|
|
95
99
|
/>
|
|
96
100
|
```
|
|
97
101
|
|
|
98
|
-
| Slot
|
|
99
|
-
|
|
100
|
-
| `title`
|
|
101
|
-
| `description` | 부제 (optional)
|
|
102
|
-
| `breadcrumb`
|
|
103
|
-
| `actions`
|
|
104
|
-
| `tabs`
|
|
102
|
+
| Slot | 사용 |
|
|
103
|
+
| ------------- | -------------------------------------------------- |
|
|
104
|
+
| `title` | h1 — 페이지 이름 |
|
|
105
|
+
| `description` | 부제 (optional) |
|
|
106
|
+
| `breadcrumb` | 위치 (홈 → category → 현 페이지) |
|
|
107
|
+
| `actions` | 우측 primary / secondary buttons (예: "+ 새 주문") |
|
|
108
|
+
| `tabs` | (선택) 페이지 안 sub-section 탭 |
|
|
105
109
|
|
|
106
|
-
> PageHeader 의 actions = **페이지 단위 primary action**. row-level action 은
|
|
110
|
+
> PageHeader 의 actions = **페이지 단위 primary action**. row-level action 은
|
|
111
|
+
> DataGrid 의 column action.
|
|
107
112
|
|
|
108
113
|
---
|
|
109
114
|
|
|
@@ -119,15 +124,25 @@
|
|
|
119
124
|
```tsx
|
|
120
125
|
<Page>
|
|
121
126
|
<PageHeader title="상품 등록" actions={<Button>저장</Button>} />
|
|
122
|
-
<div
|
|
127
|
+
<div
|
|
128
|
+
style={{
|
|
129
|
+
display: 'grid',
|
|
130
|
+
gridTemplateColumns: '200px 1fr',
|
|
131
|
+
gap: 'var(--space-6)',
|
|
132
|
+
}}
|
|
133
|
+
>
|
|
123
134
|
<AnchorNav sticky>
|
|
124
135
|
<AnchorNav.Item href="#basic">기본 정보</AnchorNav.Item>
|
|
125
136
|
<AnchorNav.Item href="#images">이미지</AnchorNav.Item>
|
|
126
137
|
{/* ... */}
|
|
127
138
|
</AnchorNav>
|
|
128
139
|
<div>
|
|
129
|
-
<Section id="basic" title="기본 정보"
|
|
130
|
-
|
|
140
|
+
<Section id="basic" title="기본 정보">
|
|
141
|
+
...
|
|
142
|
+
</Section>
|
|
143
|
+
<Section id="images" title="이미지">
|
|
144
|
+
...
|
|
145
|
+
</Section>
|
|
131
146
|
{/* ... */}
|
|
132
147
|
</div>
|
|
133
148
|
</div>
|
|
@@ -140,38 +155,40 @@
|
|
|
140
155
|
|
|
141
156
|
## 7. 결정 표 (lookup)
|
|
142
157
|
|
|
143
|
-
| 케이스
|
|
144
|
-
|
|
145
|
-
| "list 페이지 (DataGrid)"
|
|
146
|
-
| "단일 entity form"
|
|
147
|
-
| "큰 form (상품 등록)"
|
|
148
|
-
| "dashboard (KPI + chart)"
|
|
149
|
-
| "단순 정보 페이지"
|
|
150
|
-
| "mobile"
|
|
151
|
-
| "settings 페이지 (다 section)" | AppShell + PageHeader + Section/AnchorNav (left nav)
|
|
152
|
-
| "page 안 sub-page tabs"
|
|
158
|
+
| 케이스 | 답 |
|
|
159
|
+
| ------------------------------ | ---------------------------------------------------------------- |
|
|
160
|
+
| "list 페이지 (DataGrid)" | full-bleed AppShell + PageHeader + DataGrid |
|
|
161
|
+
| "단일 entity form" | AppShell + PageHeader + max-width 640 form |
|
|
162
|
+
| "큰 form (상품 등록)" | AppShell + PageHeader + Section/AnchorNav layout |
|
|
163
|
+
| "dashboard (KPI + chart)" | full-bleed AppShell + Grid cols=4 (KPI) + Grid cols=2 (chart) |
|
|
164
|
+
| "단순 정보 페이지" | AppShell + max-width 800 + body text |
|
|
165
|
+
| "mobile" | Sidebar → drawer (`useIsBreakpointUp('lg')`) + Page padding 축소 |
|
|
166
|
+
| "settings 페이지 (다 section)" | AppShell + PageHeader + Section/AnchorNav (left nav) |
|
|
167
|
+
| "page 안 sub-page tabs" | PageHeader 의 `tabs` slot |
|
|
153
168
|
|
|
154
169
|
---
|
|
155
170
|
|
|
156
171
|
## 8. Mobile 변형
|
|
157
172
|
|
|
158
|
-
| Desktop
|
|
159
|
-
|
|
160
|
-
| Sidebar (left sticky)
|
|
161
|
-
| Page padding (24-32px)
|
|
162
|
-
| Section/AnchorNav (2-col) | Section only + AnchorNav drawer
|
|
163
|
-
| DataGrid (table)
|
|
164
|
-
| PageHeader (1줄)
|
|
165
|
-
| max-width 640 form
|
|
173
|
+
| Desktop | Mobile (< lg) |
|
|
174
|
+
| ------------------------- | --------------------------------------------------------------- |
|
|
175
|
+
| Sidebar (left sticky) | Drawer (top trigger의 hamburger) |
|
|
176
|
+
| Page padding (24-32px) | Page padding 16px |
|
|
177
|
+
| Section/AnchorNav (2-col) | Section only + AnchorNav drawer |
|
|
178
|
+
| DataGrid (table) | Card list (data-grid.md §3) |
|
|
179
|
+
| PageHeader (1줄) | PageHeader (vertical stack — title / breadcrumb / actions 분리) |
|
|
180
|
+
| max-width 640 form | full-width form |
|
|
166
181
|
|
|
167
182
|
---
|
|
168
183
|
|
|
169
184
|
## 9. 안티 패턴
|
|
170
185
|
|
|
171
|
-
- ❌ **Page 마다 다른 layout** (사용자 mental model 깨짐) — 모든 페이지 같은
|
|
186
|
+
- ❌ **Page 마다 다른 layout** (사용자 mental model 깨짐) — 모든 페이지 같은
|
|
187
|
+
AppShell + PageHeader
|
|
172
188
|
- ❌ **DataGrid 페이지에 max-width** — content 가 자연스럽지 못함. full-bleed
|
|
173
189
|
- ❌ **form 페이지에 max-width 없음** — 1920px 의 가로 input 한 줄 어색
|
|
174
|
-
- ❌ **PageHeader 의 actions 가 row-level** (예: row 의 "edit" 버튼) — DataGrid
|
|
190
|
+
- ❌ **PageHeader 의 actions 가 row-level** (예: row 의 "edit" 버튼) — DataGrid
|
|
191
|
+
column action
|
|
175
192
|
- ❌ **Sidebar 안 sub-Item 3 단계 이상** — 깊이 제한 (mental load)
|
|
176
193
|
- ❌ **section 사이 gap 의 hardcoded px** — `var(--section-gap)` 사용
|
|
177
194
|
- ❌ **page padding 의 hardcoded** — `var(--space-*)` token
|
|
@@ -181,36 +198,38 @@
|
|
|
181
198
|
|
|
182
199
|
## 10. Cross-cutting
|
|
183
200
|
|
|
184
|
-
| Axis
|
|
185
|
-
|
|
201
|
+
| Axis | 적용 |
|
|
202
|
+
| -------------- | ------------------------------------------------------------------------------- |
|
|
186
203
|
| **Responsive** | Sidebar → drawer / padding 축소 / Section/AnchorNav 변환 / DataGrid → card list |
|
|
187
|
-
| **A11y**
|
|
188
|
-
| **i18n**
|
|
189
|
-
| **Permission** | Sidebar.Item 의 권한별 hide (Step 7 Web Playbook)
|
|
190
|
-
| **Telemetry**
|
|
204
|
+
| **A11y** | Sidebar `<nav>` semantic / PageHeader `<h1>` / Breadcrumb aria-label |
|
|
205
|
+
| **i18n** | nav label / title / breadcrumb 모두 `t()` |
|
|
206
|
+
| **Permission** | Sidebar.Item 의 권한별 hide (Step 7 Web Playbook) |
|
|
207
|
+
| **Telemetry** | nav click / page view 자동 log (Step 7) |
|
|
191
208
|
|
|
192
209
|
---
|
|
193
210
|
|
|
194
211
|
## 11. apps/web 의 실 사용 (Step 7 Web Playbook 의 baseline)
|
|
195
212
|
|
|
196
|
-
| Route
|
|
197
|
-
|
|
198
|
-
| `/merchant/customers`, `/merchant/orders` etc.
|
|
199
|
-
| `/merchant/products/new`, `/merchant/products/[id]`
|
|
200
|
-
| `/merchant/shop/business-info`, `/merchant/account/security` | AppShell + PageHeader + max-width 640 단순 form
|
|
201
|
-
| `/merchant/dashboard` (home)
|
|
202
|
-
| `/merchant/shop` (settings 종합)
|
|
213
|
+
| Route | Layout |
|
|
214
|
+
| ------------------------------------------------------------ | ------------------------------------------------------ |
|
|
215
|
+
| `/merchant/customers`, `/merchant/orders` etc. | AppShell + PageHeader + DataGrid (full-bleed) |
|
|
216
|
+
| `/merchant/products/new`, `/merchant/products/[id]` | AppShell + PageHeader + Section/AnchorNav (큰 form) |
|
|
217
|
+
| `/merchant/shop/business-info`, `/merchant/account/security` | AppShell + PageHeader + max-width 640 단순 form |
|
|
218
|
+
| `/merchant/dashboard` (home) | AppShell + PageHeader + Grid (KPI / chart) full-bleed |
|
|
219
|
+
| `/merchant/shop` (settings 종합) | AppShell + PageHeader + Section/AnchorNav (다 section) |
|
|
203
220
|
|
|
204
221
|
---
|
|
205
222
|
|
|
206
223
|
## 12. TBD
|
|
207
224
|
|
|
208
225
|
1. **max-width 정확 px** — form 640? 720? 800? 페이지 종류별 정확 token
|
|
209
|
-
2. **Sidebar collapsed (icon only) trigger** — 자동 (viewport 작음) vs 사용자
|
|
226
|
+
2. **Sidebar collapsed (icon only) trigger** — 자동 (viewport 작음) vs 사용자
|
|
227
|
+
button
|
|
210
228
|
3. **PageHeader sticky** — 스크롤 시 항상 위 또는 page top 만
|
|
211
229
|
4. **AnchorNav drawer (mobile)** — top trigger vs bottom Sheet
|
|
212
230
|
5. **Section gap responsive** — desktop 48px / mobile 32px 자동
|
|
213
|
-
6. **container queries** — Page 안 Card 의 internal layout 이 Page width 아닌
|
|
231
|
+
6. **container queries** — Page 안 Card 의 internal layout 이 Page width 아닌
|
|
232
|
+
Card width 기반
|
|
214
233
|
|
|
215
234
|
---
|
|
216
235
|
|