@conscience-technology/ctds 0.3.4 → 0.4.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/assets/components/Button/Button.module.css +2 -2
- package/assets/components/EventListItem/EventListItem.module.css +220 -0
- package/assets/components/EventListItem/EventListItem.tsx +205 -0
- package/assets/components/EventListItem/index.ts +8 -0
- package/assets/components/Icon/Icon.tsx +80 -41
- package/assets/components/ListItem/ListItem.module.css +91 -211
- package/assets/components/ListItem/ListItem.tsx +130 -154
- package/assets/components/ListItem/index.ts +2 -2
- package/assets/components/MetricCard/MetricCard.module.css +5 -5
- package/assets/components/Sidebar/Sidebar.module.css +81 -4
- package/assets/components/Sidebar/Sidebar.tsx +11 -2
- package/assets/components/SplitButton/SplitButton.module.css +3 -3
- package/assets/components/Stepper/Stepper.module.css +196 -52
- package/assets/components/Stepper/Stepper.tsx +68 -13
- package/assets/components/Switch/Switch.module.css +1 -9
- package/assets/components/Topbar/Topbar.module.css +33 -5
- package/assets/components/Topbar/Topbar.tsx +62 -7
- package/assets/components/_data.ts +11 -4
- package/assets/components/index.ts +2 -0
- package/assets/components/tokens.css +23 -10
- package/assets/prompts/ASSEMBLY.md +219 -0
- package/assets/prompts/PRINCIPLES.md +70 -0
- package/assets/prompts/axes/icon.md +7 -1
- package/assets/prompts/axes/palette.md +11 -0
- package/assets/prompts/components/_variants.md +5 -1
- package/assets/prompts/components/callout.md +3 -3
- package/assets/prompts/components/event-list-item.md +103 -0
- package/assets/prompts/components/generated-image.md +80 -0
- package/assets/prompts/components/list-item.md +182 -204
- package/assets/prompts/components/metric-card.md +2 -2
- package/assets/prompts/components/toast.md +1 -0
- package/assets/prompts/components/topbar.md +77 -59
- package/assets/prompts/themes/focus.md +72 -0
- package/assets/skills/ctds/SKILL.md +1 -0
- package/assets/skills/ctds-page/SKILL.md +12 -2
- package/assets/skills/ctds-wireframe/SKILL.md +35 -1
- package/package.json +2 -4
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
- 비동기 로딩 상태(spinner Toast)로 쓰지 않는다 — Toast는 완료 신호 전용.
|
|
25
25
|
- 플로팅이지만 `data-side` 기반 `.m-float` 유틸은 쓰지 않는다 — Toast는 placement별 slide-in 전용 애니.
|
|
26
26
|
- 영구 안내·설명·FAQ 유도에 쓰지 않는다 — [[components/callout]] 영역.
|
|
27
|
+
- `duration`을 [[axes/motion]] 스케일로 조절하지 않는다 — motion은 애니메이션 속도 축이고, duration은 "사용자 읽는 시간" 축. 둘은 독립. motion=`none`이어도 duration은 그대로(툭 나타나 4초 보고 툭 사라짐이 정상).
|
|
27
28
|
|
|
28
29
|
### Fallback
|
|
29
30
|
`tone` 애매하면 `neutral`. `surface` 애매하면 `inverse`. `placement` 애매하면 `bottom-right`. `duration` 애매하면 `4000`.
|
|
@@ -3,14 +3,18 @@
|
|
|
3
3
|
### 원칙
|
|
4
4
|
앱 shell 최상단의 가로 bar — Breadcrumb·탐색·검색·알림·사용자 메뉴처럼 **"지금 어느 자리인지 + 공용 액션"**만 담는 chrome. 콘텐츠 자체(hero head, 큰 환영 메시지, 섹션 제목)는 Topbar의 자리가 아니라 **아래 body의 첫 블록 자리**다. Topbar는 세로 높이가 고정된 **얇은 축**이므로, 수직 리듬이 큰 요소를 끼우면 align이 깨지고 bar 자체가 "들뜬다".
|
|
5
5
|
|
|
6
|
+
구조는 **leading / center / trailing 3-zone 고정**. 루트가 부모 폭을 꽉 채우고 세 zone이 자리를 나눈다. "왼쪽에 몰림" 현상은 구조적으로 발생하지 않는다 — zone이 없으면 애초에 Topbar를 쓰지 않는다.
|
|
7
|
+
|
|
6
8
|
### Do
|
|
9
|
+
- `Topbar.Leading` + `Topbar.Trailing` **짝**을 기본으로. 한쪽만 있는 경우도 OK — 반드시 zone 안에 넣는다.
|
|
10
|
+
- 가운데에 pin하고 싶은 요소(검색 트리거 pill 등)는 `Topbar.Center`로. 비우면 L↔T 사이 공간이 자동으로 벌어진다.
|
|
7
11
|
- Breadcrumb·검색 Input·알림 IconButton·avatar menu·탐색 Tabs처럼 **반복적으로 쓰이는 공용 액션만** 담는다.
|
|
8
12
|
- 세로는 `size` prop(`sm`/`md`)이 결정하는 한 줄만. 수직으로 쌓지 않는다.
|
|
9
|
-
- 좌/우 정렬은 `Topbar.Spacer`로. 가운데 그룹이 필요하면 중앙에 또 하나의 Spacer를 끼운다.
|
|
10
13
|
- 자체 chrome(bg/border/shadow)은 두지 않는다 — 표현은 상위 [[components/app-frame]] variant가 담당.
|
|
11
14
|
- 페이지의 "지금 어디" 신호는 **Breadcrumb**로. 큰 타이틀로 쓰고 싶으면 Topbar가 아니라 body 첫 블록.
|
|
12
15
|
|
|
13
16
|
### Don't
|
|
17
|
+
- zone 밖에 **자식을 바로 넣지 않는다**. `<Topbar><Breadcrumb/>...</Topbar>` 같은 구조 금지 — 반드시 Leading/Center/Trailing 중 하나로 감싼다.
|
|
14
18
|
- `h1`·큰 hero head·환영 메시지("good morning, …")·페이지 섹션 타이틀을 Topbar 안에 넣지 않는다 — Topbar는 **얇은 축**이고 큰 타이포가 들어가는 순간 `align-items` 전쟁이 벌어진다. 이걸 로컬 CSS로 때우는 순간(`align-items: flex-start`, `padding-bottom` override 등) Topbar의 "축" 약속이 깨지고, 아래 body와의 수직 리듬도 어긋난다. hero는 body의 첫 섹션으로 꺼낸다.
|
|
15
19
|
- 수직 스택(eyebrow + title 세로 두 줄 같은 조합)을 Topbar 안에 넣지 않는다. 수직 리듬은 body의 섹션 head에서.
|
|
16
20
|
- 알림·검색·Breadcrumb 외의 **콘텐츠**(KPI·요약·공지 문구)를 Topbar에 끼우지 않는다. 그건 body hero 섹션 또는 Callout의 자리.
|
|
@@ -20,7 +24,7 @@
|
|
|
20
24
|
|
|
21
25
|
### Fallback
|
|
22
26
|
`size` 애매하면 `md`. 콘텐츠 밀도가 아주 낮은 랜딩/문서 shell이면 `sm`.
|
|
23
|
-
|
|
27
|
+
Leading·Trailing 둘 다 비면 Topbar를 두지 않는다 — 빈 bar는 수직 공간만 먹는다.
|
|
24
28
|
|
|
25
29
|
### 관련
|
|
26
30
|
- [[components/app-frame]] — Topbar를 품는 shell. bg/border/shadow 등 chrome 표현은 AppFrame variant가 쥔다.
|
|
@@ -33,12 +37,19 @@ Breadcrumb 자리·공용 액션 자리 둘 다 비면 Topbar를 두지 않는
|
|
|
33
37
|
### Props 시그니처
|
|
34
38
|
```tsx
|
|
35
39
|
<Topbar size="sm | md">
|
|
36
|
-
{
|
|
40
|
+
<Topbar.Leading>{/* brand·back·breadcrumb·title */}</Topbar.Leading>
|
|
41
|
+
<Topbar.Center>{/* 선택: 가운데 pin 요소 (검색 트리거 등) */}</Topbar.Center>
|
|
42
|
+
<Topbar.Trailing>{/* 공용 액션: 검색·알림·avatar·primary 버튼 */}</Topbar.Trailing>
|
|
37
43
|
</Topbar>
|
|
38
|
-
|
|
39
|
-
<Topbar.Spacer /> {/* 좌/우 정렬용 flex:1 빈 블록 */}
|
|
40
44
|
```
|
|
41
45
|
|
|
46
|
+
| 요소 | 역할 |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `Topbar` | width:100%, 세로 flex 축. 높이만 `size`로 결정 |
|
|
49
|
+
| `Topbar.Leading` | 왼쪽 zone, 자연 폭. 자식 gap `--space-1` |
|
|
50
|
+
| `Topbar.Center` | 가운데 zone, 1fr + 중앙 정렬. 비우면 L↔T 자동 분리 |
|
|
51
|
+
| `Topbar.Trailing` | 오른쪽 zone, 자연 폭 + `margin-inline-start: auto`로 오른쪽 pin |
|
|
52
|
+
|
|
42
53
|
### Size 매트릭스
|
|
43
54
|
|
|
44
55
|
| size | 세로 높이 | 용도 |
|
|
@@ -47,6 +58,7 @@ Breadcrumb 자리·공용 액션 자리 둘 다 비면 Topbar를 두지 않는
|
|
|
47
58
|
| `md` | 기본 | 앱 콘솔. Breadcrumb + 공용 액션 2~3개 |
|
|
48
59
|
|
|
49
60
|
### 금지 조합
|
|
61
|
+
- zone 없이 바로 자식 삽입 — Leading/Center/Trailing 중 하나로 반드시 감싼다.
|
|
50
62
|
- Topbar 안에 `h1`·`h2`·hero head 삽입 — "얇은 축" 약속 깨짐. body hero 섹션으로 꺼낸다.
|
|
51
63
|
- Topbar 안에 수직 스택(eyebrow + title 2줄) — 단일 줄 원칙 깨짐.
|
|
52
64
|
- 로컬 CSS로 `align-items: flex-start` + `padding-bottom` 늘려서 큰 타이포 수용 — 수습이 필요한 순간 그 요소가 자리가 아니라는 신호.
|
|
@@ -56,77 +68,83 @@ Breadcrumb 자리·공용 액션 자리 둘 다 비면 Topbar를 두지 않는
|
|
|
56
68
|
|
|
57
69
|
### 조합 예시
|
|
58
70
|
|
|
59
|
-
Topbar는
|
|
71
|
+
Topbar는 **3-zone 자유 슬롯 컨테이너**다. "page / detail / panel" 같은 variant를 따로 두지 않고, **같은 Topbar에 다른 children**을 넣어 역할을 바꾼다. 뒤로가기·close도 전용 컴포넌트가 아니라 `IconButton` + `Icon`을 zone에 꽂는 조립.
|
|
60
72
|
|
|
61
73
|
```tsx
|
|
62
74
|
// 1) page — 운영 콘솔. Breadcrumb + 검색 + 알림
|
|
63
75
|
<Topbar size="md">
|
|
64
|
-
<
|
|
65
|
-
<Breadcrumb
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
<Topbar.Leading>
|
|
77
|
+
<Breadcrumb>
|
|
78
|
+
<Breadcrumb.Item href="/today">today</Breadcrumb.Item>
|
|
79
|
+
<Breadcrumb.Current>meetings</Breadcrumb.Current>
|
|
80
|
+
</Breadcrumb>
|
|
81
|
+
</Topbar.Leading>
|
|
82
|
+
<Topbar.Trailing>
|
|
83
|
+
<Input
|
|
84
|
+
size="md"
|
|
85
|
+
variant="filled"
|
|
86
|
+
placeholder="search anything"
|
|
87
|
+
leftIcon={<Icon name="search" />}
|
|
88
|
+
rightAction={<Shortcut size="sm">⌘K</Shortcut>}
|
|
89
|
+
/>
|
|
90
|
+
<IconButton icon={<Icon name="bell" />} size="md" variant="ghost" />
|
|
91
|
+
</Topbar.Trailing>
|
|
77
92
|
</Topbar>
|
|
78
93
|
|
|
79
94
|
// 2) detail — 뒤로가기 + Breadcrumb로 현재 위치 + overflow 액션
|
|
80
95
|
<Topbar size="md">
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
<Breadcrumb
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
<Topbar.Leading>
|
|
97
|
+
<IconButton
|
|
98
|
+
icon={<Icon name="caret-left" />}
|
|
99
|
+
size="md"
|
|
100
|
+
variant="ghost"
|
|
101
|
+
aria-label="back"
|
|
102
|
+
/>
|
|
103
|
+
<Breadcrumb>
|
|
104
|
+
<Breadcrumb.Item href="/meetings">meetings</Breadcrumb.Item>
|
|
105
|
+
<Breadcrumb.Current>oct 5 standup</Breadcrumb.Current>
|
|
106
|
+
</Breadcrumb>
|
|
107
|
+
</Topbar.Leading>
|
|
108
|
+
<Topbar.Trailing>
|
|
109
|
+
<IconButton
|
|
110
|
+
icon={<Icon name="dots-three" />}
|
|
111
|
+
size="md"
|
|
112
|
+
variant="ghost"
|
|
113
|
+
aria-label="more"
|
|
114
|
+
/>
|
|
115
|
+
</Topbar.Trailing>
|
|
98
116
|
</Topbar>
|
|
99
117
|
|
|
100
118
|
// 3) panel — 사이드패널/드로어 내부. 더 얇게 + close
|
|
101
119
|
<Topbar size="sm">
|
|
102
|
-
<
|
|
103
|
-
<Breadcrumb
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
120
|
+
<Topbar.Leading>
|
|
121
|
+
<Breadcrumb>
|
|
122
|
+
<Breadcrumb.Current>filters</Breadcrumb.Current>
|
|
123
|
+
</Breadcrumb>
|
|
124
|
+
</Topbar.Leading>
|
|
125
|
+
<Topbar.Trailing>
|
|
126
|
+
<IconButton
|
|
127
|
+
icon={<Icon name="x" />}
|
|
128
|
+
size="sm"
|
|
129
|
+
variant="ghost"
|
|
130
|
+
aria-label="close"
|
|
131
|
+
/>
|
|
132
|
+
</Topbar.Trailing>
|
|
112
133
|
</Topbar>
|
|
113
134
|
|
|
114
|
-
//
|
|
115
|
-
<
|
|
116
|
-
<Topbar
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
{ /* 이하 KPI, 섹션들 … */ }
|
|
124
|
-
</main>
|
|
135
|
+
// 4) center zone — 가운데에 pin해야 할 때
|
|
136
|
+
<Topbar size="md">
|
|
137
|
+
<Topbar.Leading>{/* brand */}</Topbar.Leading>
|
|
138
|
+
<Topbar.Center>
|
|
139
|
+
<SearchTrigger />
|
|
140
|
+
</Topbar.Center>
|
|
141
|
+
<Topbar.Trailing>{/* 알림·avatar */}</Topbar.Trailing>
|
|
142
|
+
</Topbar>
|
|
125
143
|
```
|
|
126
144
|
|
|
127
|
-
### 역할별
|
|
145
|
+
### 역할별 zone 공식
|
|
128
146
|
|
|
129
|
-
| 역할 |
|
|
147
|
+
| 역할 | Leading | Center | Trailing | size |
|
|
130
148
|
|---|---|---|---|---|
|
|
131
149
|
| page | Breadcrumb | — | 검색 Input, 알림/avatar IconButton | `md` |
|
|
132
150
|
| detail | `IconButton icon="caret-left" variant="ghost"` + Breadcrumb | — | overflow/share 등 IconButton | `md` |
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Focus
|
|
2
|
+
|
|
3
|
+
### 원칙
|
|
4
|
+
데이터 밀도 중심 — 관리자 대시보드, 분석 도구, 로그 뷰어, 트레이딩 콘솔처럼 **한 화면에 많은 정보를 올려야 하고 사용자가 매일 몇 시간씩 들여다보는** 자리의 Theme. 꾸밈을 걷어내고 밀도를 올려 "읽기 좋음"에 전부를 투자한다. `spare`가 "매일 쓰는 도구의 중앙값"이라면 `focus`는 그 극단 — 밀도를 한 단계 더 올리고 브랜드 액센트를 완전히 중성화한다.
|
|
5
|
+
|
|
6
|
+
### Do
|
|
7
|
+
- 테이블·리스트·사이드바에 가능한 많은 행을 노출. 섹션 간 호흡은 Density가 결정하되 추가 margin은 금지.
|
|
8
|
+
- 상태는 색이 아니라 **배지·형태·weight**로 먼저 전달. 색은 status(warning/danger/success/info)에만 남긴다.
|
|
9
|
+
- 액션은 Toolbar·IconButton·DropdownMenu 중심. 큰 primary 버튼은 폼 제출·CTA 자리에만.
|
|
10
|
+
- 모든 숫자·금액 셀은 좌측 정렬 유지 — [[feedback_no_right_align_numbers]] 그대로.
|
|
11
|
+
- 사이드바·탑바는 작은 size(sm)로 밀도를 더 쪼은다.
|
|
12
|
+
|
|
13
|
+
### Don't
|
|
14
|
+
- 마케팅·랜딩·온보딩에 쓰지 않는다. 액센트가 없어 전환이 안 터진다.
|
|
15
|
+
- "비어 보여서" 간격이나 장식을 추가하지 않는다. compact density는 의도된 밀도.
|
|
16
|
+
- `vivid`/`pastel` palette로 override하지 않는다 — 밀도가 높을수록 색 노이즈가 피로를 가속.
|
|
17
|
+
- 브랜드 identity를 색으로 보여야 하는 자리엔 이 Theme이 맞지 않음. [[themes/spare]]나 [[themes/expressive]]로.
|
|
18
|
+
|
|
19
|
+
### Fallback
|
|
20
|
+
축 preset은 아래 표 값으로 고정. palette만 브랜드 선호에 따라 `mono` ↔ `standard` 사이 선택 가능.
|
|
21
|
+
|
|
22
|
+
### 관련
|
|
23
|
+
- [[themes/_SCHEMA]] — Theme 스키마
|
|
24
|
+
- [[themes/spare]] — "매일 쓰는 도구의 중앙값". 밀도를 한 단계 낮춘 버전.
|
|
25
|
+
- [[axes/palette]] — `mono` 값과의 상호작용(아이콘·포커스·nav-active 전부 중성 fg 톤).
|
|
26
|
+
- [[axes/density]] — `compact` 값 전용 프리셋.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### Signature
|
|
31
|
+
이 Theme IS "매일 몇 시간씩 머무는 작업실" UI. 데이터 밀도가 디자인의 1원칙이고, 꾸밈은 피로 가속기라는 전제 위에 있다. 터미널의 자제력을 웹 앱의 레이어에 끌어들인 결과물 — not minimalism, but engineered legibility.
|
|
32
|
+
|
|
33
|
+
### Preset
|
|
34
|
+
|
|
35
|
+
| Axis | Value | Why |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| [[axes/mode]] | `dark` | 장시간 사용 환경에서 피로 최소화. light override는 소비자 선호. |
|
|
38
|
+
| [[axes/palette]] | `mono` | 브랜드 액센트 완전 제거. 아이콘·포커스·nav-active 전부 fg 톤. status만 유색 유지. |
|
|
39
|
+
| [[axes/shape]] | `crisp` | 격자 자체가 신호. soft radius는 밀도 환경에서 "뭉개짐"으로 읽힌다. |
|
|
40
|
+
| [[axes/density]] | `compact` | 핵심 축. 행 간격·컨트롤 높이가 한 단계 좁아진다. |
|
|
41
|
+
| [[axes/font]] | `lang=ko` | 한국어 기본. 폰트 스택은 Font 축이 담당. |
|
|
42
|
+
| [[axes/icon]] | `phosphor` | regular/fill 매트릭 완전 매칭. 밀도 환경에선 아이콘 식별이 중요. |
|
|
43
|
+
| [[axes/motion]] | `calm` | 애니메이션 최소화 — 눈이 머무는 시간이 길어 bounce/overshoot가 피로. none은 접근성 승인된 사용자용. |
|
|
44
|
+
|
|
45
|
+
### Layout
|
|
46
|
+
2-column 또는 3-pane이 디폴트 — 좌측 사이드바(sm size) + 중앙 작업 영역 + 우측 디테일 패널. 한 화면에 가능한 많은 정보를 수평으로 분할. 1-column 중심 레이아웃(블로그·마케팅)엔 맞지 않음.
|
|
47
|
+
|
|
48
|
+
### Imagery
|
|
49
|
+
없음. 데이터와 아이콘만. 사진·일러스트는 이 Theme의 성격과 어긋남 — 작업 중 시선을 분산시킴. 예외: 사용자 아바타·조직 로고 같은 identity 식별자.
|
|
50
|
+
|
|
51
|
+
### Decoration
|
|
52
|
+
없음. hairline과 bg-subtle의 톤 차이만으로 그룹 구분. gradient·noise·pattern 금지. 이 Theme에서 "장식은 피로"의 공리.
|
|
53
|
+
|
|
54
|
+
### Negative
|
|
55
|
+
- no primary accent color — status 외 모든 색은 중성 fg 톤
|
|
56
|
+
- no large hero section — "눈에 띄는 한 자리"가 없는 게 디폴트
|
|
57
|
+
- no illustrations · no photography — 작업 영역에 아트는 노이즈
|
|
58
|
+
- no soft radius — crisp 격자가 밀도의 전제
|
|
59
|
+
- no bouncy motion — overshoot는 매일 보기 피곤
|
|
60
|
+
|
|
61
|
+
### Override
|
|
62
|
+
전부 자유. 사용자가 "focus에서 shape만 soft로"처럼 지시하면 그대로 적용. 책임은 사용자. Theme 선언을 벗어난 조합의 완성도는 보증하지 않는다 ([[PRINCIPLES]] §7).
|
|
63
|
+
|
|
64
|
+
### Known Gaps
|
|
65
|
+
- 랜딩·마케팅 자리는 커버 안 함 — [[themes/expressive]]로.
|
|
66
|
+
- 모바일 터치 중심 UX는 커버 안 함 — compact density는 데스크톱·태블릿 가로 전제.
|
|
67
|
+
- 색으로 identity를 전달해야 하는 브랜드엔 맞지 않음 — mono가 디폴트이므로.
|
|
68
|
+
|
|
69
|
+
### Iteration Guide
|
|
70
|
+
1. 밀도를 더 올리고 싶으면 size prop(xs/sm)으로 가되, density 축 자체는 compact에서 더 내릴 수 없다 — compact이 최종 밀도.
|
|
71
|
+
2. palette를 `mono`에서 `standard` 또는 `calm`으로 올리는 override는 허용. 그 외(vivid/pastel)는 Theme과 상충.
|
|
72
|
+
3. motion을 bouncy로 올리는 override는 **금지** — focus의 핵심 자제가 깨짐.
|
|
@@ -7,22 +7,32 @@ description: CTDS 페이지·대시보드·레이아웃을 조합할 때 발동.
|
|
|
7
7
|
|
|
8
8
|
페이지는 **조합**이지 제작이 아니다. 기존 `web/components/` 에서 골라 배치하고, 축 값에 따라 간격·크기·배치를 조정한다. 새 컴포넌트가 필요하면 `ctds-component`로 넘긴다.
|
|
9
9
|
|
|
10
|
+
**벤더에 없는 자리를 수제 조립해야 하면 반드시 `prompts/ASSEMBLY.md`를 먼저 읽는다.** 조립 알고리즘 5단계와 자리별 레시피(`prompts/recipes/`)가 리듬·위계·여백을 보장한다.
|
|
11
|
+
|
|
10
12
|
## 판단 순서
|
|
11
13
|
|
|
12
14
|
1. 현재 프리셋·축 값 확인 — 특히 **Density** (compact / comfortable)
|
|
13
15
|
2. 필요한 컴포넌트가 모두 존재하는지 확인 → `web/components/`
|
|
14
16
|
3. shell 선택 (AppFrame / Sidebar / SidebarSplit / Topbar) — `web/components/AppFrame/` 등
|
|
15
17
|
4. 섹션 조립 — Spacing 토큰으로 간격, Density에 따라 스케일링
|
|
16
|
-
5.
|
|
17
|
-
6.
|
|
18
|
+
5. **벤더에 없는 자리는 `prompts/ASSEMBLY.md` 알고리즘대로 조립 + `recipes/*.md` 참조**
|
|
19
|
+
6. 접촉 금지·스크롤 패딩 등 레이아웃 규칙 적용
|
|
20
|
+
7. 접근성 — 랜드마크, 포커스 순서, 키보드 네비
|
|
18
21
|
|
|
19
22
|
## 참조 매트릭스
|
|
20
23
|
|
|
21
24
|
| 조건 | 읽을 문서 |
|
|
22
25
|
|---|---|
|
|
23
26
|
| 항상 | `prompts/PRINCIPLES.md` |
|
|
27
|
+
| 벤더에 없는 자리 조립 | `prompts/ASSEMBLY.md` + `prompts/recipes/<자리>.md` |
|
|
24
28
|
| 간격·여백 | `prompts/tokens/spacing.md` + `prompts/axes/density.md` |
|
|
25
29
|
| shell·네비 | `prompts/components/topbar.md`, `web/components/{AppFrame,Sidebar,SidebarSplit,Topbar}/` |
|
|
30
|
+
| 페이지 상단 블록 | `prompts/recipes/page-header.md` |
|
|
31
|
+
| 섹션 상단 블록 | `prompts/recipes/section-header.md` |
|
|
32
|
+
| 카드처럼 보이는 리스트 row | `prompts/recipes/card-row.md` |
|
|
33
|
+
| 메타 라벨 가로 나열 | `prompts/recipes/meta-line.md` |
|
|
34
|
+
| 폼·모달 하단 액션 | `prompts/recipes/form-footer.md` |
|
|
35
|
+
| 페이지 폭 안내 바 | `prompts/recipes/page-banner.md` |
|
|
26
36
|
| 리스트 | `prompts/components/list-item.md` |
|
|
27
37
|
| 테이블 | `prompts/components/{table-row,table-row-edit,table-row-select,table-header}.md` |
|
|
28
38
|
| 폼 | `prompts/components/{form-field,input,select,checkbox,radio,switch}.md` |
|
|
@@ -44,6 +44,7 @@ description: 와이어프레임·목업·기존 페이지를 CTDS로 번역·교
|
|
|
44
44
|
5. **여백 리듬** ⭐ — 섹션 간 여백이 `--space-4/6/8` 토큰 리듬을 따르는가? 하드코딩이나 중구난방인 간격 플래그.
|
|
45
45
|
6. **"빈 자리" 감지** — 눈으로 봤을 때 어색하게 비어 보이는 자리가 있는가? 그 자리에 CTDS가 요구하는 요소(타이틀·설명 1줄·보조 액션)가 들어가야 하는가?
|
|
46
46
|
7. **그룹핑** — 가까이 있는데 역할이 다른 요소가 섞여있지 않은가? 역할이 같은데 분리돼 있지 않은가?
|
|
47
|
+
8. **"한 몸처럼 붙은 두 버튼" 감지** ⭐ — 라벨 영역 옆에 작은 caret(▾)·아이콘 영역이 **구분선 하나로 붙어있는** 형태가 보이면 거의 100% **SplitButton**이다. Button 두 개로 조립하거나 Button 안에 caret을 억지로 넣지 말 것. ([[antipattern_split_button_as_two_buttons]])
|
|
47
48
|
|
|
48
49
|
진단 결과는 보정 패스 전에 **글로 적어서 사용자에게 공유**. 자동으로 넘어가지 말 것.
|
|
49
50
|
|
|
@@ -59,10 +60,35 @@ description: 와이어프레임·목업·기존 페이지를 CTDS로 번역·교
|
|
|
59
60
|
| 네모 박스 안 숫자 | 그냥 Card | MetricCard (label + value + delta) |
|
|
60
61
|
| 긴 가로 바 액션 (저장·취소) | 큰 Button 2개 | 페이지 하단 Toolbar 또는 폼 Footer 패턴 |
|
|
61
62
|
| "+ 새로 만들기" 가로 바 | FilterButton | Button variant="primary" 또는 EmptyState CTA |
|
|
63
|
+
| **라벨 + 작은 ▾ caret이 한 몸처럼 붙은 버튼** (예: `+ New note ▾`, `저장 ▾`) | 수제 Button + Button 조립, Button 안에 caret 아이콘 억지로 넣기 | **SplitButton** — main(기본 액션) + menu(▾ 드롭다운). 둘이 시각적으로 붙어있고 클릭 영역이 분리된 모든 패턴 ([[components/split-button]]) |
|
|
62
64
|
| 색상 라벨 (상태) | Chip | Badge (상태·메타=Badge, 선택 필터=Chip) |
|
|
63
65
|
|
|
64
66
|
의미 매핑 안티패턴은 `~/.claude/projects/-Users-heeyoung-Documents-CTDS/memory/` 에서 `antipattern_*.md` 로 축적된다. 매핑 전에 메모리 인덱스에서 관련 안티패턴 검색.
|
|
65
67
|
|
|
68
|
+
### 패스 3.5. 커버리지 결정 — 벤더 그대로 vs 로컬 파생 vs 수제 (⭐ 통일성의 핵심)
|
|
69
|
+
|
|
70
|
+
패스 3에서 매핑한 각 자리에 대해 **세 단계 중 어느 길인지** 반드시 결정하고 글로 적는다. 수제(div+span 조립)로 빠지는 순간 토큰·여백·사이즈 리듬이 전부 깨진다 — 이게 번역이 어색해지는 1번 원인.
|
|
71
|
+
|
|
72
|
+
**결정 트리** (위에서부터 순서대로 적용):
|
|
73
|
+
|
|
74
|
+
1. **CTDS 벤더 컴포넌트가 그대로 맞음** → 그대로 import해서 사용. 끝.
|
|
75
|
+
2. **살짝 다름** (라벨 하나 더, trailing 영역 하나 추가, 특정 variant 미지원 등) → **로컬 파생 컴포넌트** 생성:
|
|
76
|
+
- 가장 비슷한 CTDS 벤더 컴포넌트 코드(JSX + CSS Module)를 **그대로 복사해서 소비 프로젝트 로컬 경로**(예: `web/app/_components/` 또는 `app/components/<page>/_parts/`)에 **다른 이름**으로 둠.
|
|
77
|
+
- 거기서 **디자인만 살짝** 조정. 토큰·height·padding·gap·radius 기본값은 **건드리지 말고 유지** — 조정은 추가 요소/위치/variant 수준.
|
|
78
|
+
- **CTDS 벤더 패키지는 절대 수정 금지** ([[feedback_no_vendor_modification]]).
|
|
79
|
+
3. **벤더에 비슷한 것조차 없음** → `prompts/recipes/<자리>.md` 반드시 확인 ([[ASSEMBLY]]). 레시피에도 없으면 **수제가 아니라 사용자에게 보고** — "이 자리 벤더/레시피 둘 다 없음, 어떻게 할지" 물어본다. 임의로 div+span 수제 조립 금지.
|
|
80
|
+
|
|
81
|
+
**왜 로컬 파생이 수제보다 통일성이 좋은가**:
|
|
82
|
+
- 수제 조립은 토큰 선택부터 틀어진다. padding `12px`·gap `8px` 같은 직관에서 뽑은 값들이 CTDS space scale(--space-2=8, --space-3=12 등)과 미묘하게 어긋나거나, 심지어 하드코딩됨 ([[feedback_no_hardcoded_values]]).
|
|
83
|
+
- 로컬 파생은 **CTDS 벤더의 토큰 선택을 그대로 베낀 상태에서 시작**하므로 height·radius·font·icon size·transition까지 전부 CTDS 궤도 위에 올라가 있음. 조정은 "추가 요소를 어디 꽂을지"만 결정하면 됨.
|
|
84
|
+
- Shape/Density/Hue 축이 바뀌어도 벤더 토큰을 참조하고 있으니 로컬 파생도 같이 반응.
|
|
85
|
+
|
|
86
|
+
**로컬 파생 결정 시 확인**:
|
|
87
|
+
- 어떤 벤더 컴포넌트에서 베낄지 (파일 경로 명시)
|
|
88
|
+
- 어디에 둘지 (`_components/` or `_parts/`)
|
|
89
|
+
- 무엇을 바꿀지 (추가 slot, 삭제한 variant, 추가 라벨 — "디자인 기본값 건드리지 않음" 명시)
|
|
90
|
+
- 베끼면서 토큰 하드코딩 금지, 기존 토큰 그대로 유지
|
|
91
|
+
|
|
66
92
|
### 패스 4. 보정 — CTDS 리듬으로 재설계
|
|
67
93
|
|
|
68
94
|
패스 2에서 플래그한 어색함을 전부 보정한 뒤에만 코드 작성:
|
|
@@ -72,12 +98,19 @@ description: 와이어프레임·목업·기존 페이지를 CTDS로 번역·교
|
|
|
72
98
|
- **여백 리듬**: 섹션 간 `--space-6` 또는 `--space-8`, 섹션 안 블록 간 `--space-4`, 작은 컴포넌트 간 `--space-1`.
|
|
73
99
|
- **그룹핑 재편**: 역할이 같은 것은 하나의 Section/Card에, 다른 것은 분리.
|
|
74
100
|
- **원본에 없던 CTDS 패턴 추가**: EmptyState·Toolbar·Breadcrumb 등 원본엔 없지만 CTDS 페이지에 필요한 요소는 **추가하는 게 기본**.
|
|
101
|
+
- **벤더에 없는 자리는 레시피 참조**: 페이지 헤더·섹션 헤더·카드 row·메타 라인·폼 푸터·안내 배너 등 자주 등장하는 자리는 `prompts/recipes/<자리>.md`를 **반드시 열어** 토큰·구조 조합을 확인. 수제 조립로 가지 않는다 ([[ASSEMBLY]]).
|
|
75
102
|
|
|
76
103
|
## 체크리스트 — 번역 완료 전 전부 통과
|
|
77
104
|
|
|
78
105
|
- [ ] 패스 1 (분석) 결과를 글로 적었는가
|
|
79
106
|
- [ ] 패스 2 (진단) 결과를 사용자에게 공유했는가 — 자동 넘김 금지
|
|
80
107
|
- [ ] 1:1 매핑이 아닌 역할 기반 매핑인가
|
|
108
|
+
- [ ] **각 자리마다 "벤더 그대로 / 로컬 파생 / 레시피 조립" 중 어느 길인지 글로 결정했는가** ⭐
|
|
109
|
+
- [ ] **수제 조립(div+span, 토큰 하드코딩)으로 간 자리가 하나도 없는가** ⭐ 벤더에 비슷한 것도 없고 레시피에도 없으면 **사용자에게 보고**
|
|
110
|
+
- [ ] 로컬 파생을 만든 경우: 벤더 코드 그대로 베꼈고 토큰 기본값 유지했는가 (디자인 조정은 추가 요소·위치 수준)
|
|
111
|
+
- [ ] CTDS 벤더 패키지(`packages/ctds-cli/assets/`, `node_modules/ctds/`)를 수정하지 않았는가
|
|
112
|
+
- [ ] **Sidebar가 있으면 Header/Body inner/Footer 패딩 공급 계획을 조립 전에 세웠는가** ⭐ ([[feedback_wireframe_sidebar_padding_check]])
|
|
113
|
+
- [ ] **Topbar 안 IdentityButton·identity 트리거에 sub prop 넣지 않았는가** (2줄 금지, [[feedback_topbar_single_line_identity]])
|
|
81
114
|
- [ ] Topbar에 h1 또는 breadcrumb가 있는가 (없다면 명시적으로 이유)
|
|
82
115
|
- [ ] 라벨 없는 섹션이 없는가
|
|
83
116
|
- [ ] 한 영역 안 컴포넌트 `size` 통일 — 기본 `sm`
|
|
@@ -90,7 +123,8 @@ description: 와이어프레임·목업·기존 페이지를 CTDS로 번역·교
|
|
|
90
123
|
|
|
91
124
|
| 조건 | 읽을 문서 |
|
|
92
125
|
|---|---|
|
|
93
|
-
| 항상 | `prompts/PRINCIPLES.md` + 메모리 `antipattern_*.md` 전체 |
|
|
126
|
+
| 항상 | `prompts/PRINCIPLES.md` + `prompts/ASSEMBLY.md` + 메모리 `antipattern_*.md` 전체 |
|
|
127
|
+
| 벤더에 없는 자리 조립 | `prompts/recipes/<자리>.md` (page-header, section-header, card-row, meta-line, form-footer, page-banner 등) |
|
|
94
128
|
| 밀도 결정 | `prompts/axes/density.md` + [[feedback_default_size_sm]] |
|
|
95
129
|
| 여백 리듬 | `prompts/tokens/spacing.md` |
|
|
96
130
|
| shell·네비 | `prompts/components/{topbar,sidebar,app-frame}.md` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conscience-technology/ctds",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "CTDS — 하이브리드 디자인 시스템 설치 · 온보딩 CLI (shadcn식 코드 생성기)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -14,15 +14,13 @@
|
|
|
14
14
|
"bin",
|
|
15
15
|
"src",
|
|
16
16
|
"assets",
|
|
17
|
-
"templates",
|
|
18
17
|
"README.md"
|
|
19
18
|
],
|
|
20
19
|
"exports": {
|
|
21
20
|
".": {
|
|
22
21
|
"import": "./bin/ctds.js"
|
|
23
22
|
},
|
|
24
|
-
"./assets/*": "./assets/*"
|
|
25
|
-
"./templates/*": "./templates/*"
|
|
23
|
+
"./assets/*": "./assets/*"
|
|
26
24
|
},
|
|
27
25
|
"scripts": {
|
|
28
26
|
"bundle-assets": "node ./scripts/bundle-assets.mjs",
|