@conscience-technology/ctds 0.1.8 → 0.1.9
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.
|
@@ -127,26 +127,29 @@
|
|
|
127
127
|
padding: 0 var(--space-2) var(--space-2);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
/* SingleLine
|
|
130
|
+
/* SingleLine — Shift+Enter로 자라면 textarea 상단으로 확장, 좌/우 버튼은 하단 고정.
|
|
131
|
+
MultiLine과 동일 max-height(≈8줄)에서 스크롤. */
|
|
131
132
|
.shape-single .body {
|
|
132
133
|
flex-direction: row;
|
|
133
|
-
align-items:
|
|
134
|
+
align-items: flex-end; /* 버튼들 하단 고정 */
|
|
134
135
|
gap: var(--space-0_5);
|
|
135
136
|
padding: var(--space-2) var(--space-2);
|
|
136
137
|
}
|
|
137
138
|
.singleField {
|
|
138
139
|
flex: 1 1 auto;
|
|
139
140
|
min-width: 0;
|
|
140
|
-
padding:
|
|
141
|
+
padding: calc((var(--space-8) - var(--text-sm) * 1.5) / 2) var(--space-1);
|
|
141
142
|
background: transparent;
|
|
142
143
|
border: 0;
|
|
143
144
|
outline: none;
|
|
144
145
|
resize: none;
|
|
145
|
-
overflow: hidden;
|
|
146
146
|
color: var(--fg-strong);
|
|
147
147
|
font: inherit;
|
|
148
148
|
font-size: var(--text-sm);
|
|
149
149
|
line-height: 1.5;
|
|
150
|
+
/* MultiLine과 동일 상한 — 넘으면 textarea 자체 스크롤 */
|
|
151
|
+
max-height: calc(var(--text-sm) * 1.5 * 8);
|
|
152
|
+
overflow-y: auto;
|
|
150
153
|
}
|
|
151
154
|
.singleField::placeholder {
|
|
152
155
|
color: var(--fg-muted);
|
|
@@ -108,14 +108,15 @@ export const ChatInput = forwardRef<HTMLDivElement, ChatInputProps>(
|
|
|
108
108
|
const canSend = !disabled && (value.trim().length > 0 || attachments.length > 0);
|
|
109
109
|
const showStop = isStreaming && !!onStop;
|
|
110
110
|
|
|
111
|
-
/* autoResize — multi/single 둘 다. textarea는 content에 맞춰
|
|
112
|
-
|
|
113
|
-
Shift+Enter로 줄바꿈 → textarea가 즉시 자라고, SingleLine도 자연스레 늘어남. */
|
|
111
|
+
/* autoResize — multi/single 둘 다. textarea는 content에 맞춰 자람.
|
|
112
|
+
Shift+Enter로 줄바꿈 → textarea 즉시 확장. max 넘으면 CSS max-height가 scroll 생성. */
|
|
114
113
|
useLayoutEffect(() => {
|
|
115
114
|
const el = taRef.current;
|
|
116
115
|
if (!el) return;
|
|
117
116
|
el.style.height = "auto";
|
|
118
|
-
|
|
117
|
+
// scrollHeight로 설정하되 CSS max-height가 override하도록 직접 min
|
|
118
|
+
const nextH = el.scrollHeight;
|
|
119
|
+
el.style.height = `${nextH}px`;
|
|
119
120
|
}, [shape, value]);
|
|
120
121
|
|
|
121
122
|
const handleKeyDown = useCallback(
|
|
@@ -19,7 +19,7 @@ root는 `<div role="menuitem">`이다 — `leadingActions`/`trailingActions`에
|
|
|
19
19
|
### Don't
|
|
20
20
|
- MenuItem 안에 두 개 이상의 “주된 액션”을 두지 않는다 — 아이템 전체가 하나의 selection. 부가 액션(즐겨찾기 토글·⋯메뉴)만 slot에 얹는다.
|
|
21
21
|
- 라벨을 두 줄 이상 넣지 않는다. 설명이 필요하면 [[components/command-palette]] description 슬롯이나 [[components/tooltip]].
|
|
22
|
-
- 페이지 이동에 root click 시맨틱 금지. 라우팅 아이템이면 `asChild`로 `<Link>`/`<a>`에 위임.
|
|
22
|
+
- 페이지 이동에 root click 시맨틱 금지. 라우팅 아이템이면 `asChild`로 `<Link>`/`<a>`에 위임. **단, `asChild`일 땐 라벨 `.label` 래퍼가 적용되지 않는다** — 자식(`<Link>`) 자체가 라벨 역할이라 truncation·color·weight가 자동 상속되지 않음. 긴 라벨이면 `<Link>` 쪽에 truncate 유틸을 걸거나, 짧게 유지하는 설계로.
|
|
23
23
|
- height를 CSS로 덮어쓰지 않는다. `size` prop 경유 (Density 축이 스왑).
|
|
24
24
|
- hover-only 액션을 “시각적으로 숨김”으로만 처리하지 않는다 — `opacity: 0` + `pointer-events: none`이 짝. 안 그러면 안 보이는 버튼이 클릭됨.
|
|
25
25
|
|
|
@@ -81,6 +81,7 @@ type MenuItemAction =
|
|
|
81
81
|
checked={boolean} // leadingActions 맨 앞에 checkmark 자동 삽입
|
|
82
82
|
active={boolean} // 현재 페이지/선택 아이템 강조
|
|
83
83
|
disabled={boolean}
|
|
84
|
+
collapsed={boolean} // icon-only. leading 하나만 남기고 label/trailing/shortcut 전부 숨김. (Sidebar가 자동 주입)
|
|
84
85
|
asChild={boolean} // Radix Slot — <Link>/<a>/DropdownMenu.Item 등에 위임
|
|
85
86
|
onClick={(e) => void}
|
|
86
87
|
/>
|
|
@@ -1,23 +1,38 @@
|
|
|
1
1
|
# Sidebar
|
|
2
2
|
|
|
3
3
|
### 원칙
|
|
4
|
-
좌측 세로 nav. **라우팅 전용** — Tabs/필터는 쓸 곳이 아님.
|
|
4
|
+
좌측 세로 nav. **라우팅 전용** — Tabs/필터는 쓸 곳이 아님. Header(고정) + Body(스크롤) + Footer(고정) 3영역 세로 쉘에, Brand + Section + Item + Separator + Profile을 compound로 조합. `collapsed`로 icon-only 축소. Item은 [[components/menu-item]]을 그대로 어댑트 — 시각·상태 규칙 공유.
|
|
5
|
+
|
|
6
|
+
### 3영역 구조 (중요)
|
|
7
|
+
Sidebar는 **Header / Body / Footer 세 영역으로 강제 분리**된다. 역할 혼동이 레이아웃 사고의 1순위 원인.
|
|
8
|
+
|
|
9
|
+
| 영역 | 스크롤 | 레이아웃 | 담는 것 |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| `Sidebar.Header` | ❌ 고정 | **가로 flex 행** (brand symbol + wordmark 나란히) | `Sidebar.Brand` 전용 |
|
|
12
|
+
| `Sidebar.Body` | ✅ 세로 스크롤 | 세로 flex 열 | `Sidebar.Section` · `Sidebar.Separator` 전부 여기 |
|
|
13
|
+
| `Sidebar.Footer` | ❌ 고정 | 가로 flex 행 | `Sidebar.Profile` 또는 보조 액션 |
|
|
14
|
+
|
|
15
|
+
Header는 **가로 행**이기 때문에 Section을 넣으면 nav 전체가 가로 1줄로 눌려 겹친다. Section·Item·Separator는 반드시 `Sidebar.Body` 안에.
|
|
5
16
|
|
|
6
17
|
### Do
|
|
7
|
-
-
|
|
18
|
+
- Section·Separator는 반드시 **`Sidebar.Body` 안에** 둔다 — Body만 스크롤되는 영역.
|
|
19
|
+
- 라우트 이동은 Item에 `asChild` + Next `<Link>`. 단, `asChild`일 땐 라벨 truncation이 `<Link>` 쪽 책임이 된다 ([[components/menu-item]] Slot 동작) — 긴 라벨이면 Link에 `truncate` 유틸 또는 `title` 속성을 걸 것.
|
|
8
20
|
- 현재 라우트는 `active`로 명시 (MenuItem의 active 시각 그대로).
|
|
9
21
|
- Brand는 Home 링크 자리로. `symbol`(항상 노출) + `wordmark`(expanded만).
|
|
10
22
|
- Section 묶음은 `title`로 그룹. collapsed일 땐 title 자동 숨김.
|
|
11
23
|
- `collapsed` 상태에서는 `aria-label`과 `title`을 자동으로 걸어 접근성 유지.
|
|
24
|
+
- 콘텐츠 영역과의 **경계선은 [[components/app-frame]] `variant="outlined"`** 가 그린다 — Sidebar 자체는 border를 그리지 않음. 사이드바가 녹아 보이면 AppFrame variant부터 확인.
|
|
12
25
|
|
|
13
26
|
### Don't
|
|
27
|
+
- **Header에 Section·Item·nav를 넣지 않는다** — Header는 가로 flex 행이라 세로 nav가 깔리면 전부 눌려 겹친다. Brand 전용.
|
|
14
28
|
- 페이지 안 뷰 전환에 쓰지 않는다 — 그건 [[components/tabs]].
|
|
15
29
|
- Item 안에 variant로 다른 톤을 쓰지 않는다. active 외의 강조 금지.
|
|
16
30
|
- Sidebar 자체에 padding/width를 CSS로 덮지 않는다. `--sidebar-w*` 토큰 경유.
|
|
31
|
+
- `.root`에 padding을 꽂지 않는다 — Body가 스크롤 컨테이너라 스크롤바가 안쪽으로 밀려 가장자리에 안 붙는다. 좌우 여백은 Header/Section/Footer가 각자 담당([[project_scroll_rule]]).
|
|
17
32
|
- Brand symbol·wordmark 크기 override 금지. `--sidebar-brand-symbol-max`·`--sidebar-brand-wordmark-max` 상한 안에서만.
|
|
18
33
|
|
|
19
34
|
### Fallback
|
|
20
|
-
collapsed 결정 애매하면 `false`. Section title 애매하면 생략.
|
|
35
|
+
collapsed 결정 애매하면 `false`. Section title 애매하면 생략. 경계선 애매하면 AppFrame `variant="outlined"`.
|
|
21
36
|
|
|
22
37
|
### 관련
|
|
23
38
|
- [[components/menu-item]] — Item 시각·상태 전부 재사용
|
|
@@ -29,26 +44,31 @@ collapsed 결정 애매하면 `false`. Section title 애매하면 생략.
|
|
|
29
44
|
### Props 시그니처
|
|
30
45
|
```tsx
|
|
31
46
|
<Sidebar collapsed={boolean}> // default: false
|
|
47
|
+
{/* Header — 고정, 가로 행. Brand 전용. */}
|
|
32
48
|
<Sidebar.Header>
|
|
33
49
|
<Sidebar.Brand symbol={<Icon />} wordmark={<Logo /> | "CTDS"} />
|
|
34
50
|
</Sidebar.Header>
|
|
35
51
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
{/* Body — 세로 스크롤 트랙. Section·Separator 전부 여기. 여러 개 두면 각자 독립 스크롤. */}
|
|
53
|
+
<Sidebar.Body>
|
|
54
|
+
<Sidebar.Section title="워크스페이스">
|
|
55
|
+
<Sidebar.Item
|
|
56
|
+
icon={<Icon name="house" />}
|
|
57
|
+
label="대시보드"
|
|
58
|
+
active={boolean}
|
|
59
|
+
trailing={ReactNode} // 배지·카운트
|
|
60
|
+
shortcut="⌘1"
|
|
61
|
+
hasSubmenu={boolean}
|
|
62
|
+
disabled={boolean}
|
|
63
|
+
asChild={boolean}
|
|
64
|
+
onClick={(e) => void}
|
|
65
|
+
/>
|
|
66
|
+
</Sidebar.Section>
|
|
67
|
+
|
|
68
|
+
<Sidebar.Separator />
|
|
69
|
+
</Sidebar.Body>
|
|
70
|
+
|
|
71
|
+
{/* Footer — 고정, 하단. Profile 또는 보조 액션. */}
|
|
52
72
|
<Sidebar.Footer>
|
|
53
73
|
<Sidebar.Profile
|
|
54
74
|
name="희영"
|
|
@@ -69,26 +89,28 @@ collapsed 결정 애매하면 `false`. Section title 애매하면 생략.
|
|
|
69
89
|
|
|
70
90
|
### 조합 예시
|
|
71
91
|
```tsx
|
|
72
|
-
// 기본 — 섹션 2개 + Profile
|
|
92
|
+
// 기본 — 섹션 2개 + Profile. Section·Separator는 Body 안.
|
|
73
93
|
<Sidebar>
|
|
74
94
|
<Sidebar.Header>
|
|
75
95
|
<Sidebar.Brand symbol={<Icon name="rocket-launch" />} wordmark="CTDS" />
|
|
76
96
|
</Sidebar.Header>
|
|
77
97
|
|
|
78
|
-
<Sidebar.
|
|
79
|
-
<Sidebar.
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
<Sidebar.Body>
|
|
99
|
+
<Sidebar.Section title="워크스페이스">
|
|
100
|
+
<Sidebar.Item asChild icon={<Icon name="house" />} label="대시보드" active>
|
|
101
|
+
<Link href="/">대시보드</Link>
|
|
102
|
+
</Sidebar.Item>
|
|
103
|
+
<Sidebar.Item asChild icon={<Icon name="chart-line" />} label="분석">
|
|
104
|
+
<Link href="/analytics">분석</Link>
|
|
105
|
+
</Sidebar.Item>
|
|
106
|
+
</Sidebar.Section>
|
|
86
107
|
|
|
87
|
-
|
|
108
|
+
<Sidebar.Separator />
|
|
88
109
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
110
|
+
<Sidebar.Section title="설정">
|
|
111
|
+
<Sidebar.Item icon={<Icon name="gear" />} label="환경설정" shortcut="⌘," />
|
|
112
|
+
</Sidebar.Section>
|
|
113
|
+
</Sidebar.Body>
|
|
92
114
|
|
|
93
115
|
<Sidebar.Footer>
|
|
94
116
|
<Sidebar.Profile name="희영" sub="admin@ctds.dev" avatar={{ status: "online" }} />
|
|
@@ -100,8 +122,10 @@ collapsed 결정 애매하면 `false`. Section title 애매하면 생략.
|
|
|
100
122
|
<Sidebar.Header>
|
|
101
123
|
<Sidebar.Brand symbol={<Icon name="rocket-launch" />} />
|
|
102
124
|
</Sidebar.Header>
|
|
103
|
-
<Sidebar.
|
|
104
|
-
<Sidebar.
|
|
105
|
-
|
|
125
|
+
<Sidebar.Body>
|
|
126
|
+
<Sidebar.Section>
|
|
127
|
+
<Sidebar.Item icon={<Icon name="house" />} label="대시보드" active />
|
|
128
|
+
</Sidebar.Section>
|
|
129
|
+
</Sidebar.Body>
|
|
106
130
|
</Sidebar>
|
|
107
131
|
```
|
package/assets/skill/SKILL.md
CHANGED
|
@@ -29,6 +29,7 @@ Layer 1(shadcn 방식 컴포넌트 코드) + Layer 2(AI 프롬프트 컨텍스
|
|
|
29
29
|
|---|---|
|
|
30
30
|
| 컴포넌트 신규 제작·variant/prop 수정 (`web/components/<Name>/` 또는 `prompts/components/<name>.md`) | `ctds-component` |
|
|
31
31
|
| 페이지·대시보드·레이아웃 조합 (`web/app/**/page.tsx`) | `ctds-page` |
|
|
32
|
+
| **와이어프레임/기존 페이지를 CTDS로 번역·교체** (사용자가 "CTDS로 바꿔줘/교체해줘/일괄 변경" 요청, 또는 와이어프레임 코드·이미지를 입력) | `ctds-wireframe` |
|
|
32
33
|
| 테마 프리셋 생성·수정 (`prompts/themes/*` 또는 `web/app/theme-demo/*`) | `ctds-theme` |
|
|
33
34
|
| 코드 검증 (하드코딩·유령 토큰·메모리 규칙·문서-코드 동기화) | `ctds-validate` |
|
|
34
35
|
| 3D 아이콘 일러스트 자산 생성 | `ctds-illust` |
|