@x-plat/design-system 0.5.46 → 0.5.47

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.
@@ -300,6 +300,91 @@ DS 컴포넌트는 자체 외부 margin 없음. 부모가 gap 안 주면 모두
300
300
  </div>
301
301
  ```
302
302
 
303
+ ### 폼 요소 구조 — 중첩 금지
304
+
305
+ **Input / TextArea / Select 안에 다른 컴포넌트를 넣지 않는다.** 레이아웃이 깨진다. 폼 요소는 항상 **형제(sibling)** 로 배치한다.
306
+
307
+ #### ❌ 금지 — 폼 요소 중첩
308
+
309
+ ```tsx
310
+ // Input 안에 Button → 잘못
311
+ <Input>
312
+ <Button>검색</Button>
313
+ </Input>
314
+
315
+ // TextArea 안에 Button → 잘못
316
+ <TextArea>
317
+ <Button>전송</Button>
318
+ </TextArea>
319
+
320
+ // Select 안에 Input → 잘못
321
+ <Select>
322
+ <Input placeholder="검색" />
323
+ </Select>
324
+
325
+ // form 안에 form → 절대 금지
326
+ <form>
327
+ <form>...</form>
328
+ </form>
329
+ ```
330
+
331
+ #### ✅ 올바른 패턴
332
+
333
+ **Pattern 1: "입력 + 전송 버튼" 합성** → `ChatInput` 컴포넌트 사용
334
+ ```tsx
335
+ import { ChatInput } from "@x-plat/design-system/components";
336
+
337
+ <ChatInput
338
+ placeholder="메시지 입력"
339
+ onSubmit={(value) => handleSend(value)}
340
+ />
341
+ ```
342
+
343
+ **Pattern 2: Input 우측 아이콘/소형 액션** → Input 의 `suffix` 슬롯 사용
344
+ ```tsx
345
+ <Input
346
+ placeholder="검색"
347
+ suffix={<Icon name="search" />}
348
+ />
349
+ ```
350
+ > `suffix` 는 작은 아이콘/버튼 1개용. 일반 `<Button>` 컴포넌트 넣지 말 것 (사이즈 충돌).
351
+
352
+ **Pattern 3: 폼 요소 + 액션 버튼** → 형제 배치, wrapper 에서 gap
353
+ ```tsx
354
+ <div style={{ display: "flex", gap: "var(--spacing-space-2)" }}>
355
+ <Input placeholder="이메일" />
356
+ <Button type="primary">확인</Button>
357
+ </div>
358
+ ```
359
+
360
+ **Pattern 4: 폼 요소들 묶음** → 모두 형제, 부모에서 gap
361
+ ```tsx
362
+ <form style={{
363
+ display: "flex",
364
+ flexDirection: "column",
365
+ gap: "var(--spacing-space-4)",
366
+ }}>
367
+ <Input label="이름" />
368
+ <TextArea label="자기소개" />
369
+ <Select label="국가" options={...} />
370
+ <Button type="primary">제출</Button>
371
+ </form>
372
+ ```
373
+
374
+ #### 폼 요소별 children/슬롯 정책
375
+
376
+ | 컴포넌트 | children 받음? | 슬롯 |
377
+ |---|---|---|
378
+ | `Input` | ❌ | `suffix` (아이콘 1개) |
379
+ | `TextArea` | ❌ | 없음 |
380
+ | `Select` | ❌ | `options` prop 사용 (children 아님) |
381
+ | `CheckBox` / `Radio` / `Switch` | ❌ | `label` prop |
382
+ | `DatePicker` / `Calendar` | ❌ | controlled value/onChange |
383
+ | `Button` | ✅ | 텍스트/아이콘만 |
384
+ | `ChatInput` | ❌ | 입력+버튼 합성 컴포넌트 |
385
+
386
+ > "입력 안에 무언가를 넣고 싶다" 는 욕구가 들면 → **다른 형태의 합성 컴포넌트가 있는지 먼저 확인**. 없으면 **wrapper + 형제** 패턴 사용.
387
+
303
388
  ### 케이스별 권장 spacing 값
304
389
 
305
390
  | 케이스 | 권장 값 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x-plat/design-system",
3
- "version": "0.5.46",
3
+ "version": "0.5.47",
4
4
  "description": "XPLAT UI Design System",
5
5
  "author": "XPLAT WOONG",
6
6
  "main": "dist/index.cjs",