@x-plat/design-system 0.12.0 → 0.14.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/dist/{breakpoints-DsXkJgdl.d.cts → breakpoints-CKkNxA-y.d.cts} +1 -1
- package/dist/{breakpoints-DsXkJgdl.d.ts → breakpoints-CKkNxA-y.d.ts} +1 -1
- package/dist/components/AutoResizeTextArea/index.cjs +2 -2
- package/dist/components/AutoResizeTextArea/index.js +2 -2
- package/dist/components/Badge/index.d.cts +1 -1
- package/dist/components/Badge/index.d.ts +1 -1
- package/dist/components/ChatInput/index.cjs +2 -2
- package/dist/components/ChatInput/index.js +2 -2
- package/dist/components/CheckBox/index.cjs +2 -2
- package/dist/components/CheckBox/index.js +2 -2
- package/dist/components/DatePicker/index.cjs +109 -75
- package/dist/components/DatePicker/index.d.cts +19 -0
- package/dist/components/DatePicker/index.d.ts +19 -0
- package/dist/components/DatePicker/index.js +109 -75
- package/dist/components/Editor/index.css +3 -0
- package/dist/components/FieldMessage/index.cjs +2 -2
- package/dist/components/FieldMessage/index.d.cts +8 -0
- package/dist/components/FieldMessage/index.d.ts +8 -0
- package/dist/components/FieldMessage/index.js +2 -2
- package/dist/components/FileUpload/index.cjs +10 -6
- package/dist/components/FileUpload/index.d.cts +15 -2
- package/dist/components/FileUpload/index.d.ts +15 -2
- package/dist/components/FileUpload/index.js +10 -6
- package/dist/components/ImageSelector/index.cjs +7 -6
- package/dist/components/ImageSelector/index.d.cts +15 -2
- package/dist/components/ImageSelector/index.d.ts +15 -2
- package/dist/components/ImageSelector/index.js +7 -6
- package/dist/components/Input/index.cjs +2 -2
- package/dist/components/Input/index.d.cts +4 -0
- package/dist/components/Input/index.d.ts +4 -0
- package/dist/components/Input/index.js +2 -2
- package/dist/components/Radio/index.cjs +2 -2
- package/dist/components/Radio/index.js +2 -2
- package/dist/components/Select/index.cjs +2 -2
- package/dist/components/Select/index.d.cts +1 -2
- package/dist/components/Select/index.d.ts +1 -2
- package/dist/components/Select/index.js +2 -2
- package/dist/components/Switch/index.cjs +2 -2
- package/dist/components/Switch/index.js +2 -2
- package/dist/components/TextArea/index.cjs +2 -2
- package/dist/components/TextArea/index.js +2 -2
- package/dist/components/TimePicker/index.cjs +2 -2
- package/dist/components/TimePicker/index.js +2 -2
- package/dist/components/ToggleChip/index.cjs +69 -0
- package/dist/components/ToggleChip/index.css +102 -0
- package/dist/components/ToggleChip/index.d.cts +37 -0
- package/dist/components/ToggleChip/index.d.ts +37 -0
- package/dist/components/ToggleChip/index.js +42 -0
- package/dist/components/index.cjs +184 -119
- package/dist/components/index.css +40 -0
- package/dist/components/index.d.cts +2 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.js +174 -110
- package/dist/index.cjs +203 -138
- package/dist/index.css +40 -0
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +191 -127
- package/dist/layout/Grid/Item/index.d.cts +1 -1
- package/dist/layout/Grid/Item/index.d.ts +1 -1
- package/dist/layout/Grid/index.d.cts +1 -1
- package/dist/layout/Grid/index.d.ts +1 -1
- package/dist/layout/index.d.cts +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/tokens/index.d.cts +1 -1
- package/dist/tokens/index.d.ts +1 -1
- package/guidelines/Guidelines.md +13 -1
- package/guidelines/MIGRATION.md +297 -0
- package/guidelines/components/chip-tag.md +75 -2
- package/guidelines/components/datepicker.md +26 -0
- package/guidelines/components/file-media.md +21 -4
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { FullGrid } from './FullGrid/index.cjs';
|
|
2
2
|
export { FullScreen } from './FullScreen/index.cjs';
|
|
3
3
|
export { GridItem } from './Item/index.cjs';
|
|
4
|
-
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey,
|
|
4
|
+
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey, G as GridColumnConfig, b as GridSpanFor } from '../../breakpoints-CKkNxA-y.cjs';
|
|
5
5
|
import 'react';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { FullGrid } from './FullGrid/index.js';
|
|
2
2
|
export { FullScreen } from './FullScreen/index.js';
|
|
3
3
|
export { GridItem } from './Item/index.js';
|
|
4
|
-
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey,
|
|
4
|
+
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey, G as GridColumnConfig, b as GridSpanFor } from '../../breakpoints-CKkNxA-y.js';
|
|
5
5
|
import 'react';
|
package/dist/layout/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { FullGrid } from './Grid/FullGrid/index.cjs';
|
|
2
2
|
export { FullScreen } from './Grid/FullScreen/index.cjs';
|
|
3
3
|
export { GridItem } from './Grid/Item/index.cjs';
|
|
4
|
-
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey,
|
|
4
|
+
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey, G as GridColumnConfig, b as GridSpanFor } from '../breakpoints-CKkNxA-y.cjs';
|
|
5
5
|
export { Header } from './Header/index.cjs';
|
|
6
6
|
export { Layout } from './Layout/index.cjs';
|
|
7
7
|
export { SideBar, SideBarContext, useSideBarContext } from './SideBar/index.cjs';
|
package/dist/layout/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { FullGrid } from './Grid/FullGrid/index.js';
|
|
2
2
|
export { FullScreen } from './Grid/FullScreen/index.js';
|
|
3
3
|
export { GridItem } from './Grid/Item/index.js';
|
|
4
|
-
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey,
|
|
4
|
+
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey, G as GridColumnConfig, b as GridSpanFor } from '../breakpoints-CKkNxA-y.js';
|
|
5
5
|
export { Header } from './Header/index.js';
|
|
6
6
|
export { Layout } from './Layout/index.js';
|
|
7
7
|
export { SideBar, SideBarContext, useSideBarContext } from './SideBar/index.js';
|
package/dist/tokens/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey,
|
|
1
|
+
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey, G as GridColumnConfig, b as GridSpanFor, c as breakpoints, g as gridColumns } from '../breakpoints-CKkNxA-y.cjs';
|
|
2
2
|
export { TokenVar, cssVar, semantic } from '@x-plat/tokens-core';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
|
package/dist/tokens/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey,
|
|
1
|
+
export { B as BREAKPOINT_KEYS_ORDERED, a as BreakpointKey, G as GridColumnConfig, b as GridSpanFor, c as breakpoints, g as gridColumns } from '../breakpoints-CKkNxA-y.js';
|
|
2
2
|
export { TokenVar, cssVar, semantic } from '@x-plat/tokens-core';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
|
package/guidelines/Guidelines.md
CHANGED
|
@@ -55,7 +55,7 @@ React 기반 디자인 시스템 라이브러리이다. Figma Make Kit과 1:1
|
|
|
55
55
|
- [피드백](./components/feedback.md) - Alert, Toast, NotificationBadge
|
|
56
56
|
- [오버레이](./components/overlay.md) - Modal, Drawer, PopOver, Tooltip
|
|
57
57
|
- [폼 컨트롤](./components/form.md) - CheckBox, Radio, Switch
|
|
58
|
-
- [Chip & Tag](./components/chip-tag.md)
|
|
58
|
+
- [Chip & ToggleChip & Tag](./components/chip-tag.md)
|
|
59
59
|
- [내비게이션](./components/navigation.md) - Tab, CardTab, Breadcrumb, Pagination, Steps
|
|
60
60
|
- [DatePicker](./components/datepicker.md) - Calendar, DatePicker 4종
|
|
61
61
|
- [Accordion](./components/accordion.md)
|
|
@@ -74,3 +74,15 @@ React 기반 디자인 시스템 라이브러리이다. Figma Make Kit과 1:1
|
|
|
74
74
|
4. **컴포지션**
|
|
75
75
|
- [Grid](./composition/grid.md) - Grid 시스템, 위젯 패턴
|
|
76
76
|
- [Layout](./composition/layout.md) - Layout, Header, SideBar
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 버전을 올릴 때
|
|
81
|
+
|
|
82
|
+
[마이그레이션 노트](./MIGRATION.md) — 0.5.x 이후 **실제로 깨지는 것만** 버전별로
|
|
83
|
+
모아 뒀다. 자기 버전부터 아래로 읽으면 된다.
|
|
84
|
+
|
|
85
|
+
- 최신본: `https://unpkg.com/@x-plat/design-system/guidelines/MIGRATION.md`
|
|
86
|
+
- 커밋 제목만 보고 판단하지 말 것. `refactor!` 인데 별칭이 살아 있어 안 깨지는
|
|
87
|
+
것이 있고, 평범한 `refactor` 인데 prop 이 사라진 것이 있다.
|
|
88
|
+
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# @x-plat/design-system — 마이그레이션 노트
|
|
2
|
+
|
|
3
|
+
버전을 올릴 때 **실제로 깨지는 것만** 모았다. 추가된 기능은 여기 적지 않는다 —
|
|
4
|
+
그건 각 컴포넌트 문서에 있다.
|
|
5
|
+
|
|
6
|
+
- 최신본 URL: `https://unpkg.com/@x-plat/design-system/guidelines/MIGRATION.md`
|
|
7
|
+
- 자기 버전부터 아래로 읽어 내려가면 된다.
|
|
8
|
+
|
|
9
|
+
## 먼저: 지금 내가 위험한가
|
|
10
|
+
|
|
11
|
+
**`0.x` 에서 캐럿(`^`)은 마이너를 고정한다.** 메이저가 0 이면 npm 은 마이너 번호를
|
|
12
|
+
메이저처럼 다룬다.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
^0.12.0 ≡ >=0.12.0 <0.13.0 ← 0.13.0 은 안 온다
|
|
16
|
+
^0.5.42 ≡ >=0.5.42 <0.6.0 ← 0.6.0 은 안 온다
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
그래서 **`install` 을 다시 돌려도 아래 변경들은 오지 않는다.** 전부
|
|
20
|
+
`package.json` 의 명시 버전을 직접 올리는 순간에 한꺼번에 온다.
|
|
21
|
+
|
|
22
|
+
이 말은 두 가지를 뜻한다.
|
|
23
|
+
|
|
24
|
+
1. **당장 안 올릴 거면 이 문서를 읽지 않아도 된다.** 지금 화면은 안 깨진다.
|
|
25
|
+
2. **올릴 때는 건너뛴 구간의 절을 전부 읽어야 한다.** 한 마이너씩 올라가는 게
|
|
26
|
+
아니라 여러 마이너를 한 번에 건너뛰게 되기 때문이다.
|
|
27
|
+
|
|
28
|
+
특히 오래 머물러 있던 저장소는 **성격이 다른 변경 둘을 한꺼번에 맞는다.**
|
|
29
|
+
`0.5.x` 에서 최신으로 올리면 [0.6.0 CSS 변수 개명](#05x--060--css-변수-이름-전면-교체)과
|
|
30
|
+
[0.13.0 `label` 의미 변경](#0120--0130--fileupload--imageselector-의-label-뜻이-바뀜)을
|
|
31
|
+
같이 겪는다. **둘 다 타입이나 빌드가 잡아 주지 않고 화면만 바뀐다.** 이관 후
|
|
32
|
+
눈으로 확인할 것.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 이 문서를 믿어도 되는 범위
|
|
37
|
+
|
|
38
|
+
각 항목은 **커밋 해시**를 달아 뒀다. 커밋 제목만 보고 판단하지 말 것 —
|
|
39
|
+
`refactor!` 라고 외치지만 별칭이 살아 있어 안 깨지는 것이 있고(0.7.1 `Badge`),
|
|
40
|
+
평범한 `refactor` 인데 prop 이 사라진 것이 있다(0.8.0 `Button`).
|
|
41
|
+
|
|
42
|
+
「실제로 걸린 것」 표는 진짜 이관에서 확인된 것이고, 나머지는 소스에서 확인한 것이다.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 0.5.x → 0.6.0 — CSS 변수 이름 전면 교체
|
|
47
|
+
|
|
48
|
+
**`92dac35` · 가장 큰 변경이다.** Figma 변수 컬렉션 구조에 맞춰 컬러 레이어를
|
|
49
|
+
4단계에서 3단계로 줄이면서 semantic 이름을 전부 바꿨다.
|
|
50
|
+
|
|
51
|
+
`var(--semantic-*)` 를 직접 쓰는 CSS 가 있으면 **조용히 깨진다** — 정의되지 않은
|
|
52
|
+
변수는 오류를 내지 않고 색만 사라진다. 이관 후 화면을 눈으로 확인할 것.
|
|
53
|
+
|
|
54
|
+
| 예전 | 지금 |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `--semantic-*-strong` | `--semantic-*-primary` |
|
|
57
|
+
| `--semantic-*-subtle` | `--semantic-*-secondary` |
|
|
58
|
+
| `--semantic-*-muted` | `--semantic-*-tertiary` |
|
|
59
|
+
| `--semantic-*-brand` | `--semantic-*-brand-primary` |
|
|
60
|
+
| `--semantic-*-sunday` | `--semantic-*-accent-red` |
|
|
61
|
+
| `--semantic-*-saturday` | `--semantic-*-accent-blue` |
|
|
62
|
+
| `--semantic-*-emphasis-*` | 삭제 → `--semantic-surface-*-strong` |
|
|
63
|
+
| `--brand-base-black-alpha-10/25` | `--brand-base-overlay-5/10/25/50/75/85` |
|
|
64
|
+
|
|
65
|
+
`color/primitive.ts` 가 삭제되고 `brand`/`system` 이 hex 실값을 직접 갖는다.
|
|
66
|
+
`var(--primitive-*)` 를 참조하던 곳은 전부 끊긴다.
|
|
67
|
+
|
|
68
|
+
**값이 바뀐 것 6건** (이름은 그대로인데 색이 달라진다):
|
|
69
|
+
`text-brand-primary` · `border-brand-primary` · `border-warning` ·
|
|
70
|
+
`surface-info-default` · `icon-success` · `icon-info`.
|
|
71
|
+
`system.link` 는 purple → deep-purple.
|
|
72
|
+
|
|
73
|
+
> 컴포넌트만 쓰고 CSS 변수를 직접 참조하지 않는다면 이 절은 건너뛰어도 된다.
|
|
74
|
+
|
|
75
|
+
## 0.6.0 → 0.7.0 — effects · typography 토큰 정합
|
|
76
|
+
|
|
77
|
+
**`6429909`** 컴포넌트가 하드코딩하던 그림자·폰트를 토큰으로 옮겼다.
|
|
78
|
+
컴포넌트를 그대로 쓰면 영향 없다. 그림자나 폰트 크기를 CSS 로 덮어쓰고 있었다면
|
|
79
|
+
우선순위가 달라질 수 있다.
|
|
80
|
+
|
|
81
|
+
## 0.7.0 → 0.7.1 — Badge 이름 변경
|
|
82
|
+
|
|
83
|
+
**`c95ee21` · `6430c9c`**
|
|
84
|
+
|
|
85
|
+
| 대상 | 깨지나 | 조치 |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `import { Badge }` | **안 깨짐** | `Badge` 가 `@deprecated` 별칭으로 계속 나간다. 새로 쓰는 곳만 `NotificationBadge` |
|
|
88
|
+
| CSS 클래스 `.lib-xplat-badge` | **깨짐** | `.lib-xplat-notification-badge` 로. 별칭 없음 |
|
|
89
|
+
|
|
90
|
+
**`NotificationBadge` 는 알약(pill) 라벨이 아니다.** 아이콘 위에 올라타는 개수
|
|
91
|
+
인디케이터다. `count` 도 `dot` 도 없으면 **뱃지가 렌더되지 않고 children 만 통과한다.**
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
<Badge type="error">품절</Badge> // ✗ 아무것도 안 그려지고 "품절" 만 나온다
|
|
95
|
+
<NotificationBadge count={3}><BellIcon /></NotificationBadge> // ○
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
알약 라벨이 필요하면 `Tag` 를 쓴다. 이 오용은 이름이 바뀌기 전부터 조용히
|
|
99
|
+
실패하고 있었으므로, 올리기 전에 `<Badge>` 사용처를 훑어 볼 것.
|
|
100
|
+
|
|
101
|
+
## 0.7.2 → 0.8.0 — `Button` 이 `<button>` 전용으로 복귀
|
|
102
|
+
|
|
103
|
+
**`f5668dd` · `0a4ab14` · 실제로 제일 많이 깨지는 항목이다.**
|
|
104
|
+
|
|
105
|
+
`Button` 은 이제 `<button>` 하나만 렌더한다. `href` prop 이 없다.
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
<Button href="/about">소개</Button> // ✗ 더 이상 없다
|
|
109
|
+
<LinkButton href="/about">소개</LinkButton> // ○
|
|
110
|
+
<Link href="/about">소개</Link> // ○ 본문 안 링크
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
> ⚠ 커밋 `f5668dd` 에 나오는 **`buttonClass()` 는 쓰지 말 것.** 바로 다음 커밋
|
|
114
|
+
> `0a4ab14` 에서 `LinkButton` 으로 대체됐고 지금 소스에 없다(export 0건).
|
|
115
|
+
> 커밋을 순서대로 훑다 보면 유효한 경로로 오해하기 쉽다.
|
|
116
|
+
|
|
117
|
+
## 0.8.0 → 0.8.1 — 오버레이가 항상 `document.body` 로 portal
|
|
118
|
+
|
|
119
|
+
**`17004e7`** Modal · Select · Dropdown · PopOver · TimePicker 의 팝업이 조상
|
|
120
|
+
DOM 이 아니라 항상 `body` 로 들어간다. 조상에 `transform`/`filter`/`will-change`/
|
|
121
|
+
`contain` 이 있으면 `position: fixed` 의 기준이 그 조상으로 바뀌어 오버레이가
|
|
122
|
+
엉뚱한 자리에 뜨던 것을 고친 것이다.
|
|
123
|
+
|
|
124
|
+
**오버레이를 조상 기준으로 위치 잡는 CSS 가 있으면 깨진다.** 그런 CSS 는 지워야 한다 —
|
|
125
|
+
위치는 DS 가 계산한다.
|
|
126
|
+
|
|
127
|
+
## 0.8.1 → 0.8.2 — `modal-box` 에 `position: relative`
|
|
128
|
+
|
|
129
|
+
**`c3611ee`** 0.8.1 에서 모달의 `transform` 을 걷어내면서 모달 **안쪽**
|
|
130
|
+
`position: absolute` 요소들의 기준이 모달이 아니라 화면 전체(`.dim`)로 튀었다.
|
|
131
|
+
그 회귀를 되돌린 것이다. 0.8.1 을 건너뛰고 0.8.2 이상으로 올리면 겪지 않는다.
|
|
132
|
+
|
|
133
|
+
## 0.8.3 → 0.9.0 — 폼 검증 API 가 `validations` 로 통일
|
|
134
|
+
|
|
135
|
+
**`6e64fbc`** 컴포넌트마다 제각각이던 에러 표시 방식을 하나로 모았다.
|
|
136
|
+
**추가이므로 기존 코드를 깨지 않는다.** 다만 이제 직접 그릴 필요가 없다.
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
validations?: { status: "error" | "warning" | "success" | "default"; message: string }[]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- 렌더는 `FieldMessage` 가 전담한다. 아이콘·색·간격이 DS 전체에서 같아진다.
|
|
143
|
+
- `aria-invalid` 도 DS 가 붙인다 — 직접 붙이던 코드는 걷어낼 것.
|
|
144
|
+
- `hasError(validations)` 가 배럴에서 나간다.
|
|
145
|
+
- `Input/InputValidations` 는 **삭제됐다.** 직접 import 하던 곳이 있으면 끊긴다.
|
|
146
|
+
|
|
147
|
+
`Select.error?: boolean` 은 하위호환으로 남아 있다. `validations` 와 OR 로
|
|
148
|
+
합쳐지므로 둘 다 써도 되지만, 새로 쓰는 곳은 `validations` 를 쓴다.
|
|
149
|
+
|
|
150
|
+
## 0.9.0 → 0.10.0 — `type` = 상태색 / `variant` = 모양 변형
|
|
151
|
+
|
|
152
|
+
**`12f4319`** 한 컴포넌트에서 `type` 이 색을 뜻하기도 하고 모양을 뜻하기도 하던
|
|
153
|
+
것을 두 축으로 갈랐다. **별칭이 살아 있어 깨지지 않는다.**
|
|
154
|
+
|
|
155
|
+
| 축 | prop | 값 |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| 상태 색 | `type` | `primary` `success` `error` `warning` `info` |
|
|
158
|
+
| 모양 변형 | `variant` | 컴포넌트마다 다름 |
|
|
159
|
+
|
|
160
|
+
- 모양 변형을 `type` 으로 주던 곳(`Tooltip` `Chart` `Tab` `Tag`)은 `variant` 로
|
|
161
|
+
옮기는 게 맞지만, `variant ?? type ?? 기본값` 으로 받으므로 **지금 동작한다.**
|
|
162
|
+
- `type="brand"` → `type="primary"`. `normalizeStatus()` 가 `brand` 를 계속 받는다.
|
|
163
|
+
|
|
164
|
+
**별칭 제거 시점은 아직 정해지지 않았다.** 업그레이드와 무관한 diff 를 섞기
|
|
165
|
+
싫으면 나중에 한 번에 정리해도 된다. 제거가 정해지면 이 문서에 적는다.
|
|
166
|
+
|
|
167
|
+
## 0.10.0 → 0.11.0 — 폼 컨트롤에 `label` / `required`
|
|
168
|
+
|
|
169
|
+
**`9f7700d` · 추가지만 기존 마크업과 겹칠 수 있다.**
|
|
170
|
+
|
|
171
|
+
`Field` 가 **진짜 `<label htmlFor>` 를 그린다.** 바깥에서 `<label>` 로 감싸던
|
|
172
|
+
코드에 DS 의 `label` prop 을 같이 주면 `<label>` 안에 `<label>` 이 들어간다 —
|
|
173
|
+
유효하지 않은 HTML 이고, 클릭 시 포커스가 어디로 갈지 브라우저마다 다르다.
|
|
174
|
+
|
|
175
|
+
> **「DS `label` 도입」과 「기존 `<label>` 제거」는 같은 커밋에 넣을 것.**
|
|
176
|
+
> 한쪽만 하면 중첩되거나 라벨이 사라진다.
|
|
177
|
+
|
|
178
|
+
같이 걷어낼 것:
|
|
179
|
+
|
|
180
|
+
- `htmlFor` / `id` — DS 가 `React.useId()` 로 만들어 잇는다. 직접 넘길 필요 없다.
|
|
181
|
+
- `aria-invalid` — DS 가 붙인다.
|
|
182
|
+
|
|
183
|
+
`Field` 는 **붙일 게 없으면 래퍼를 만들지 않고 `children` 을 그대로 통과시킨다.**
|
|
184
|
+
안 쓰는 곳의 DOM 은 늘지 않으므로 그대로 둬도 된다.
|
|
185
|
+
|
|
186
|
+
## 0.11.0 → 0.12.0 — Editor 확충
|
|
187
|
+
|
|
188
|
+
**`7bf563f` · `97e668c` · 추가만 있다.** 되돌리기/다시하기, 표, 체크리스트,
|
|
189
|
+
정렬, 문법 강조, 형광펜, 위/아래 첨자가 들어갔다.
|
|
190
|
+
|
|
191
|
+
**저장된 HTML 을 직접 다루는 쪽은 허용 태그 목록을 갱신해야 한다.**
|
|
192
|
+
저장 값에 표·체크리스트·`mark`·`sub`/`sup` 이 새로 나타난다. 태그 목록을
|
|
193
|
+
직접 들고 있다면(예: "이 값이 HTML 인가" 판별) 아래 **31개를 그대로** 복사할 것.
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
p br div span
|
|
197
|
+
h1 h2 h3 h4 h5 h6
|
|
198
|
+
ul ol li
|
|
199
|
+
blockquote pre code
|
|
200
|
+
strong b em i u s strike del
|
|
201
|
+
a img hr
|
|
202
|
+
sub sup mark
|
|
203
|
+
table thead tbody tr th td
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
주의할 점 둘:
|
|
207
|
+
|
|
208
|
+
- **`b` `i` `u` `strike` 는 옛날 태그가 아니라 평상시 출력이다.** DS 는
|
|
209
|
+
`styleWithCSS` 를 켜지 않으므로 브라우저 `execCommand` 가 `<strong>` 이 아니라
|
|
210
|
+
`<b>` 를 낸다. 굵게 쓴 글이 흔하므로 이게 빠지면 자주 밟힌다.
|
|
211
|
+
- **`input` 은 필요 없다.** 체크리스트는 `<li data-checked>` + CSS `::before` 로
|
|
212
|
+
그린다. `<input>` 은 한 번도 나오지 않는다.
|
|
213
|
+
|
|
214
|
+
허용 목록은 `Editor.tsx` 안의 상수이고 prop 으로 열려 있지 않다. 버전을 올리면
|
|
215
|
+
따라온다. `readOnly` 로 그릴 때도 같은 태그가 전부 나온다 — sanitize 경로와
|
|
216
|
+
스타일이 편집 모드와 같다.
|
|
217
|
+
|
|
218
|
+
HTML 을 검색 색인에 넣는다면 **닫는 태그를 공백이나 줄바꿈으로 치환**할 것.
|
|
219
|
+
`</td>` `</th>` `</tr>` `</li>` `</p>` `</h1>`~`</h6>` `</blockquote>` `<br>` 을
|
|
220
|
+
그냥 지우면 칸 글자가 붙어 `가격수량` 같은 낱말이 생긴다.
|
|
221
|
+
|
|
222
|
+
## 0.12.0 → 0.13.0 — `FileUpload` / `ImageSelector` 의 `label` 뜻이 바뀜
|
|
223
|
+
|
|
224
|
+
**깨진다. 그런데 타입 오류가 나지 않는다 — 글자 위치만 바뀐다.**
|
|
225
|
+
|
|
226
|
+
이 둘의 `label` 은 DS 안에서 혼자 다른 뜻이었다. 다른 폼 컨트롤에서는 컨트롤
|
|
227
|
+
**위**에 붙는 필드 라벨인데, 여기서는 상자 **안**에 찍히는 안내 문구였다.
|
|
228
|
+
그 문구를 `placeholder` 로 옮기고 `label` 을 필드 라벨로 되돌렸다.
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
// 0.12.0 이하
|
|
232
|
+
<FileUpload label="파일을 드래그하거나 클릭하여 업로드" />
|
|
233
|
+
|
|
234
|
+
// 0.13.0 — 같은 화면을 얻으려면
|
|
235
|
+
<FileUpload placeholder="파일을 드래그하거나 클릭하여 업로드" />
|
|
236
|
+
|
|
237
|
+
// 이제 가능해진 것
|
|
238
|
+
<FileUpload label="첨부파일" required placeholder="끌어다 놓으세요" />
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`label` 을 그대로 두면 **그 글자가 상자 안이 아니라 상자 위 라벨로 올라간다.**
|
|
242
|
+
`label?: string` 에서 `label?: React.ReactNode` 로 넓어졌으므로 기존 문자열도
|
|
243
|
+
타입은 통과한다. `grep -rn 'FileUpload\|ImageSelector'` 로 훑어 `label=` 이 있는
|
|
244
|
+
곳을 `placeholder=` 로 바꾸면 된다.
|
|
245
|
+
|
|
246
|
+
같이 들어간 것:
|
|
247
|
+
|
|
248
|
+
- `required` — 라벨 뒤에 `*`
|
|
249
|
+
- `htmlFor` 연결 — 라벨을 클릭하면 파일 선택창이 열린다
|
|
250
|
+
- **`ImageSelector` 의 하드코딩된 `id="image-input"` 제거.** 한 화면에 둘 이상
|
|
251
|
+
놓으면 DOM id 가 겹치던 버그였다. 이제 `React.useId()` 로 만든다.
|
|
252
|
+
`#image-input` 을 잡는 CSS 나 테스트 셀렉터가 있으면 끊긴다.
|
|
253
|
+
|
|
254
|
+
### 같은 릴리스: DatePicker 3종에 `label` / `required` / `validations`
|
|
255
|
+
|
|
256
|
+
**추가만 있다.** `SingleDatePicker` · `RangeDatePicker` · `InputDatePicker` 가
|
|
257
|
+
다른 폼 컨트롤과 같은 방식으로 라벨·검증을 받는다.
|
|
258
|
+
|
|
259
|
+
`PopupDatePicker` 와 `Dropdown` 은 받지 않는다 — 전자는 트리거를 `component` 로
|
|
260
|
+
직접 넘기는 구조라 라벨이 가리킬 대상이 없고, 후자는 `role="menu"` 인 액션
|
|
261
|
+
메뉴라 검증할 값이 없다.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## 실제 이관에서 걸린 것 / 안 걸린 것
|
|
266
|
+
|
|
267
|
+
`xplat-shop-templat` (pnpm 모노레포, 워크스페이스 4개) 을 **0.6.1 → 0.12.0** 으로
|
|
268
|
+
올렸을 때의 결과다. DS 를 어댑터 한 곳에서만 쓰는 구조였다.
|
|
269
|
+
|
|
270
|
+
| 항목 | 결과 | 이유 |
|
|
271
|
+
|---|---|---|
|
|
272
|
+
| `Button` href 제거 | 안 걸림 | `<Button href>` 사용 0곳 |
|
|
273
|
+
| `Badge` → `NotificationBadge` | 안 걸림 | `@deprecated` 별칭으로 통과 |
|
|
274
|
+
| CSS 클래스 rename | 안 걸림 | `.lib-xplat-*` 을 덮어쓰는 CSS 0곳 |
|
|
275
|
+
| 오버레이 body portal | 안 걸림 | 오버레이 기준을 잡는 CSS 없음 |
|
|
276
|
+
| **`label` 중첩** | **걸림** | 어댑터가 `<label htmlFor>` 를 직접 그리고 있었다 |
|
|
277
|
+
|
|
278
|
+
**목록을 훑기 전에 자기 저장소에서 먼저 세어 볼 것.** 위 표에서 보듯 대부분은
|
|
279
|
+
해당 사항이 없고, 진짜 걸리는 건 한둘이다. `<Button href`, `.lib-xplat-`,
|
|
280
|
+
`<label` 세 가지를 grep 하는 것으로 대부분 판별된다.
|
|
281
|
+
|
|
282
|
+
결과: 어댑터 241줄 → 216줄, 쓰이지 않던 CSS 30줄 삭제. DS 가 `label`·
|
|
283
|
+
`aria-invalid`·`useId`·검증 메시지를 맡으면서 어댑터가 얇아진다.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## 아직 확인되지 않은 것
|
|
288
|
+
|
|
289
|
+
**Editor 는 브라우저에서 검증되지 않았다.** `contentEditable`·`execCommand`·IME 는
|
|
290
|
+
자동 테스트로 흉내 낼 수 없다. 특히 아래 넷은 직접 눌러 봐야 한다.
|
|
291
|
+
|
|
292
|
+
- 한글 조합 중 `⌘Z` / `Ctrl+Z`
|
|
293
|
+
- 툴바 서식 버튼
|
|
294
|
+
- 표 안에서 Enter · Backspace
|
|
295
|
+
- 체크박스 클릭 판정
|
|
296
|
+
|
|
297
|
+
이상이 보이면 재현 조건과 함께 알려 주면 좋겠다.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Chip & Tag
|
|
1
|
+
# Chip & ToggleChip & Tag
|
|
2
2
|
|
|
3
3
|
## Chip
|
|
4
4
|
|
|
@@ -41,9 +41,82 @@
|
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
+
## ToggleChip
|
|
45
|
+
|
|
46
|
+
**눌러서 고르는** 칩이다. 켜짐/꺼짐을 다룬다 — `Tag` 의 클릭은 삭제이고, 이쪽은
|
|
47
|
+
삭제가 아니다.
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<ToggleChip selected={picked.has("ko")} onClick={() => toggle("ko")}>
|
|
51
|
+
한국어
|
|
52
|
+
</ToggleChip>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
56
|
+
|------|------|--------|------|
|
|
57
|
+
| children | `ReactNode` | — | 내용 |
|
|
58
|
+
| selected | `boolean` | `false` | 켜진 상태. `aria-pressed` 도 함께 바뀐다 |
|
|
59
|
+
| onClick | `() => void` | — | 누를 때 |
|
|
60
|
+
| disabled | `boolean` | `false` | 흐리게 하고 못 누르게 한다 |
|
|
61
|
+
| size | `"sm" \| "md" \| "lg"` | `"md"` | `Chip` 과 같은 눈금 |
|
|
62
|
+
|
|
63
|
+
**여러 개 고르기와 한 개 고르기 양쪽에 쓴다.** 몇 개까지 켤 수 있는지, 마지막
|
|
64
|
+
하나를 뗄 수 있는지 같은 규칙은 쓰는 쪽 사정이라 여기서 정하지 않는다. 묶어
|
|
65
|
+
주는 껍데기도 없다 — 낱개로 늘어놓고 상태만 쥐고 있으면 된다.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
// 여러 개 고르기
|
|
69
|
+
const [picked, setPicked] = useState<Set<string>>(new Set());
|
|
70
|
+
const toggle = (v: string) =>
|
|
71
|
+
setPicked((prev) => {
|
|
72
|
+
const next = new Set(prev);
|
|
73
|
+
next.has(v) ? next.delete(v) : next.add(v);
|
|
74
|
+
return next;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
{OPTIONS.map((o) => (
|
|
78
|
+
<ToggleChip key={o.value} selected={picked.has(o.value)} onClick={() => toggle(o.value)}>
|
|
79
|
+
{o.label}
|
|
80
|
+
</ToggleChip>
|
|
81
|
+
))}
|
|
82
|
+
|
|
83
|
+
// 한 개 고르기 (거르개)
|
|
84
|
+
{FILTERS.map((f) => (
|
|
85
|
+
<ToggleChip key={f} selected={filter === f} onClick={() => setFilter(f)}>
|
|
86
|
+
{f}
|
|
87
|
+
</ToggleChip>
|
|
88
|
+
))}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`Chip` 과 **같은 알약 모양·같은 크기 눈금**을 쓴다. 두 CSS 가 따로 있는 게
|
|
92
|
+
아니라 `ToggleChip` 이 `.lib-xplat-chip` 을 그대로 입고 상호작용분만 얹으므로
|
|
93
|
+
둘이 따로 놀 수 없다. 거르개 칩 아래에 표시용 `Chip` 이 깔리는 화면에서
|
|
94
|
+
겉돌지 않는다.
|
|
95
|
+
|
|
96
|
+
색은 `Chip` 의 상태 색(primary·success…)을 받지 않는다. **고른 것과 안 고른 것**
|
|
97
|
+
두 가지뿐이라 상태 색 어휘가 끼어들 자리가 없다. 고른 것은 옅은 브랜드 바탕에
|
|
98
|
+
브랜드 테두리다 — 여러 개를 한꺼번에 켜는 쓰임이 더 많은데 진한 채움이 여럿이면
|
|
99
|
+
화면이 시끄럽고 곁의 버튼과 구분이 안 된다.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
44
103
|
## 의사결정
|
|
45
104
|
|
|
46
105
|
| 상황 | 사용할 것 |
|
|
47
106
|
|------|----------|
|
|
48
|
-
| 상태/분류 라벨 (
|
|
107
|
+
| 상태/분류 라벨 (누를 일 없음) | Chip |
|
|
108
|
+
| 눌러서 고르기 (켜짐/꺼짐) | **ToggleChip** |
|
|
49
109
|
| 사용자가 제거할 수 있는 태그 | Tag |
|
|
110
|
+
| 개수·점 표시 | NotificationBadge |
|
|
111
|
+
|
|
112
|
+
셋이 비슷하게 생겼으므로 **무엇이 일어나는가**로 고른다.
|
|
113
|
+
|
|
114
|
+
| | 누르면 | 렌더 |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `Chip` | 아무 일도 없다 | `<div>` |
|
|
117
|
+
| `ToggleChip` | 켜지거나 꺼진다 | `<button aria-pressed>` |
|
|
118
|
+
| `Tag` | (X 를 누르면) 사라진다 | `<span>` + 닫기 `<button>` |
|
|
119
|
+
|
|
120
|
+
> 고르는 칩을 `Chip` 을 `<button>` 으로 감싸서 만들지 말 것. 커서·초점 테두리·
|
|
121
|
+
> `aria-pressed` 가 빠지고, 실제로 그렇게 만든 화면들에서 **아무도 누를 수 있는
|
|
122
|
+
> 줄 몰랐다.** `ToggleChip` 이 그 셋을 기본으로 갖는다.
|
|
@@ -50,6 +50,32 @@ Input + 드롭다운 형태이다.
|
|
|
50
50
|
/>
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
## 라벨과 검증
|
|
54
|
+
|
|
55
|
+
`SingleDatePicker` · `RangeDatePicker` · `InputDatePicker` 는 다른 폼 컨트롤과
|
|
56
|
+
똑같이 `label` · `required` · `validations` 를 받는다.
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<InputDatePicker
|
|
60
|
+
value={date}
|
|
61
|
+
onChange={setDate}
|
|
62
|
+
label="계약일"
|
|
63
|
+
required
|
|
64
|
+
validations={[{ status: "error", message: "계약일을 선택하세요" }]}
|
|
65
|
+
/>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
검증 메시지는 `FieldMessage` 가 그린다 — 아이콘·색·간격이 Input·Select 와 같다.
|
|
69
|
+
직접 `<p>` 로 그리지 말 것.
|
|
70
|
+
|
|
71
|
+
달력을 펼쳐 놓는 `SingleDatePicker` · `RangeDatePicker` 는 **포커스 대상이 날짜
|
|
72
|
+
칸마다 있어 `htmlFor` 로 하나를 고를 수 없다.** 그래서 `role="group"` +
|
|
73
|
+
`aria-labelledby` 로 라벨과 묶는다. 쓰는 쪽에서 신경 쓸 것은 없다.
|
|
74
|
+
|
|
75
|
+
`PopupDatePicker` 는 라벨·검증을 받지 않는다 — 트리거를 `component` 로 직접
|
|
76
|
+
넘기는 구조라 라벨이 가리킬 대상이 정해지지 않는다. 라벨이 필요하면 트리거로
|
|
77
|
+
`InputDatePicker` 를 쓰거나 바깥에서 `Field` 로 감싼다.
|
|
78
|
+
|
|
53
79
|
---
|
|
54
80
|
|
|
55
81
|
## 의사결정
|
|
@@ -14,16 +14,27 @@ import { FileUpload } from "@x-plat/design-system";
|
|
|
14
14
|
| multiple | `boolean` | `false` | 다중 파일 허용 |
|
|
15
15
|
| maxSize | `number` | — | 최대 파일 크기 (bytes). 초과 파일은 자동 필터 |
|
|
16
16
|
| onChange | `(files: File[]) => void` | — | 파일 선택 콜백 |
|
|
17
|
-
|
|
|
18
|
-
| description | `string` | — | 부가 설명 |
|
|
17
|
+
| placeholder | `string` | `"파일을 드래그하거나 클릭하여 업로드"` | **상자 안** 안내 텍스트 |
|
|
18
|
+
| description | `string` | — | 상자 안 부가 설명 |
|
|
19
|
+
| label | `ReactNode` | — | **상자 위** 필드 라벨. 클릭하면 파일 선택창이 열린다 |
|
|
20
|
+
| required | `boolean` | `false` | 라벨 뒤에 `*` 표시 |
|
|
21
|
+
| validations | `Validation[]` | — | 상자 아래 검증 메시지 |
|
|
22
|
+
|
|
23
|
+
> ⚠ **0.13.0 에서 `label` 의 뜻이 바뀌었다.** 예전에는 상자 **안** 글자였고
|
|
24
|
+
> 지금은 상자 **위** 필드 라벨이다. 상자 안 글자는 `placeholder` 로 옮겼다.
|
|
25
|
+
> 타입 오류가 나지 않고 글자 위치만 바뀌므로 눈으로 확인해야 한다.
|
|
26
|
+
> 자세한 것은 [마이그레이션 노트](../MIGRATION.md) 참고.
|
|
19
27
|
|
|
20
28
|
```tsx
|
|
21
29
|
<FileUpload
|
|
30
|
+
label="첨부파일"
|
|
31
|
+
required
|
|
22
32
|
accept="image/*"
|
|
23
33
|
multiple
|
|
24
34
|
maxSize={5 * 1024 * 1024}
|
|
25
35
|
onChange={(files) => console.log(files)}
|
|
26
36
|
description="최대 5MB, 이미지만 허용"
|
|
37
|
+
validations={[{ status: "error", message: "파일을 첨부하세요" }]}
|
|
27
38
|
/>
|
|
28
39
|
```
|
|
29
40
|
|
|
@@ -40,13 +51,19 @@ import { ImageSelector } from "@x-plat/design-system";
|
|
|
40
51
|
| Prop | 타입 | 기본값 | 설명 |
|
|
41
52
|
|------|------|--------|------|
|
|
42
53
|
| value | `File` | — | 선택된 이미지 파일 |
|
|
43
|
-
|
|
|
54
|
+
| placeholder | `string` | `"이미지 추가하기"` | **상자 안** 빈 상태 안내 텍스트 |
|
|
44
55
|
| onChange | `(value: File \| undefined) => void` | — | 변경 콜백 (삭제 시 `undefined`) |
|
|
56
|
+
| label | `ReactNode` | — | **상자 위** 필드 라벨 |
|
|
57
|
+
| required | `boolean` | `false` | 라벨 뒤에 `*` 표시 |
|
|
58
|
+
| validations | `Validation[]` | — | 상자 아래 검증 메시지 |
|
|
59
|
+
|
|
60
|
+
> ⚠ `FileUpload` 와 같은 변경이 0.13.0 에 있었다. `label` 은 이제 필드 라벨이고,
|
|
61
|
+
> 상자 안 글자는 `placeholder` 다.
|
|
45
62
|
|
|
46
63
|
```tsx
|
|
47
64
|
const [image, setImage] = useState<File | undefined>();
|
|
48
65
|
|
|
49
|
-
<ImageSelector value={image} onChange={setImage} />
|
|
66
|
+
<ImageSelector label="대표 이미지" required value={image} onChange={setImage} />
|
|
50
67
|
```
|
|
51
68
|
|
|
52
69
|
---
|