@conscience-technology/ctds 0.3.2 → 0.3.3

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.
@@ -488,7 +488,7 @@ export const shadows: [string, string, string][] = [
488
488
  ["shadow-sm", "var(--shadow-sm)", "Card 기본"],
489
489
  ["shadow-md", "var(--shadow-md)", "Dropdown, Popover"],
490
490
  ["shadow-lg", "var(--shadow-lg)", "Modal"],
491
- ["shadow-xl", "var(--shadow-xl)", "Command Palette"],
491
+ ["shadow-xl", "var(--shadow-xl)",],
492
492
  ["shadow-inner", "var(--shadow-inner)", "눌린 상태"],
493
493
  ];
494
494
 
@@ -554,8 +554,6 @@ export const componentSlugs: Record<string, string> = {
554
554
  "App Frame": "layout/app-frame",
555
555
  Stepper: "nav/stepper",
556
556
  "Context Menu": "overlay/context-menu",
557
- "Command Palette": "overlay/command-palette",
558
- "Accordion": "overlay/accordion",
559
557
  Callout: "feedback/callout",
560
558
  Modal: "feedback/modal",
561
559
  Drawer: "feedback/drawer",
@@ -564,7 +562,6 @@ export const componentSlugs: Record<string, string> = {
564
562
  "Table Row": "data/table-row",
565
563
  "Table Row Select": "data/table-row-select",
566
564
  "Table Row Edit": "data/table-row-edit",
567
- "Event Card": "data/event-card",
568
565
  "Event Chip": "data/event-chip",
569
566
  "List Item": "data/list-item",
570
567
  "Metric Card": "data/metric-card",
@@ -619,7 +616,7 @@ export const components: { id: string; title: string; items: string[] }[] = [
619
616
  title: "Data Display",
620
617
  items: [
621
618
  "Table Header", "Table Row", "Table Row Select", "Table Row Edit",
622
- "List Item", "Metric Card", "Gallery Item", "File Icon", "Attachment Item", "Event Chip", "Event Card",
619
+ "List Item", "Metric Card", "Gallery Item", "File Icon", "Attachment Item", "Event Chip",
623
620
  "Empty State", "Description List", "Timeline",
624
621
  ],
625
622
  },
@@ -643,8 +640,7 @@ export const components: { id: string; title: string; items: string[] }[] = [
643
640
  id: "overlay",
644
641
  title: "Overlay / Menu",
645
642
  items: [
646
- "Context Menu", "Command Palette",
647
- "Accordion", "Collapsible", "Toggle Group",
643
+ "Context Menu", "Collapsible", "Toggle Group",
648
644
  ],
649
645
  },
650
646
  {
@@ -28,7 +28,6 @@ export * from "./Disclosure";
28
28
  export * from "./Drawer";
29
29
  export * from "./DropdownMenu";
30
30
  export * from "./EmptyState";
31
- export * from "./EventCard";
32
31
  export * from "./EventChip";
33
32
  export * from "./FileIcon";
34
33
  export * from "./FilterButton";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conscience-technology/ctds",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "CTDS — 하이브리드 디자인 시스템 설치 · 온보딩 CLI (shadcn식 코드 생성기)",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -1,247 +0,0 @@
1
- /* Accordion ─────────────────────────────────────────────────────
2
- 여러 섹션 접힘/펴짐. Radix Accordion 위의 시각 레이어.
3
- 두 variant:
4
- - plain: 테두리 없음, 아이템 사이 hairline만. 설정·FAQ 흐름.
5
- - card: 각 아이템이 독립 블록(테두리 + radius). 콘텐츠 섹션 리스트.
6
- 아이템 레이아웃(leading·라벨·trailing·caret)은 trigger 내부에서 담당. */
7
-
8
- /* Root ─────────────────────────────────────────────────── */
9
- .root {
10
- display: flex;
11
- flex-direction: column;
12
- width: 100%;
13
- color: var(--fg);
14
- font-family: var(--font-sans);
15
- --accordion-trigger-h: calc(var(--space-2) * 5); /* sm 기본 40 */
16
- /* leading 아이콘 크기 — MenuItem과 동일 톤(sm 14 / md 16).
17
- caret은 한 스텝 더 작게 — 상태 보조 신호라 라벨·아이콘보다 작아야 리듬이 잡힘. */
18
- --accordion-icon-size: calc(var(--space-1) * 3.5); /* 14 */
19
- --accordion-caret-size: var(--space-3); /* 12 */
20
- }
21
-
22
- .root[data-size="md"] {
23
- --accordion-trigger-h: calc(var(--space-2) * 6); /* md 48 */
24
- --accordion-icon-size: var(--space-4); /* 16 */
25
- --accordion-caret-size: calc(var(--space-1) * 3.5); /* 14 */
26
- }
27
-
28
- .root[data-size="lg"] {
29
- --accordion-trigger-h: calc(var(--space-2) * 7); /* lg 56 */
30
- --accordion-icon-size: calc(var(--space-1) * 4.5); /* 18 */
31
- --accordion-caret-size: var(--space-4); /* 16 */
32
- }
33
-
34
- .root[data-variant="card"] {
35
- gap: var(--space-2);
36
- }
37
-
38
- /* Item ─────────────────────────────────────────────────── */
39
- /* bare: 선·여백 전부 없음. 본문 흐름에 녹아듦.
40
- plain: 아이템 사이 hairline. 첫 아이템은 상단 선 없음.
41
- card: 각 아이템이 테두리 + radius. 사이 gap은 Root에서 담당. */
42
- .item {
43
- display: flex;
44
- flex-direction: column;
45
- }
46
-
47
- .root[data-variant="plain"] .item + .item {
48
- border-top: var(--hairline) solid var(--border);
49
- }
50
-
51
- .root[data-variant="card"] .item {
52
- border: var(--hairline) solid var(--border);
53
- border-radius: var(--radius-md);
54
- background: var(--bg);
55
- overflow: hidden;
56
- }
57
-
58
- /* bare — Trigger 좌우 padding 제거, content도 좌우 0.
59
- 세로 리듬은 그대로 유지(상/하 padding은 contentInner가 담당). */
60
- .root[data-variant="bare"] .trigger {
61
- padding-left: 0;
62
- padding-right: 0;
63
- }
64
-
65
- .root[data-variant="bare"] .contentInner {
66
- padding-left: 0;
67
- padding-right: 0;
68
- }
69
-
70
- /* bare에서는 hover 배경도 꺼야 "선 없는" 톤이 유지됨. 라벨 색만 상태 신호. */
71
- .root[data-variant="bare"] .trigger:hover:not([data-state="open"]):not([data-disabled]) {
72
- background: transparent;
73
- }
74
-
75
- /* Header + Trigger ─────────────────────────────────────── */
76
- /* Radix의 Header는 <h3>로 렌더됨. 폰트/weight은 Trigger가 결정 — Header는 wrapper. */
77
- .header {
78
- margin: 0;
79
- font-size: inherit;
80
- font-weight: inherit;
81
- }
82
-
83
- .trigger {
84
- display: flex;
85
- align-items: center;
86
- gap: var(--space-2);
87
- width: 100%;
88
- min-height: var(--accordion-trigger-h);
89
- padding: 0 var(--space-3);
90
- border: 0;
91
- background: transparent;
92
- color: var(--fg);
93
- font-family: inherit;
94
- font-size: var(--text-sm);
95
- line-height: var(--lh-sm);
96
- font-weight: var(--font-weight-medium);
97
- text-align: left;
98
- cursor: pointer;
99
- outline: none;
100
- transition: var(--transition-colors);
101
- }
102
-
103
- .root[data-size="md"] .trigger {
104
- font-size: var(--text-base);
105
- line-height: var(--lh-base);
106
- }
107
-
108
- /* hover: closed일 때만 배경 변화. open에선 상태 signal(fg-strong)만 유지. */
109
- .trigger:hover:not([data-state="open"]):not([data-disabled]) {
110
- background: var(--hover);
111
- color: var(--fg-strong);
112
- }
113
-
114
- .trigger[data-state="open"] {
115
- color: var(--fg-strong);
116
- }
117
-
118
- .trigger:focus-visible {
119
- outline: none;
120
- box-shadow: var(--ring-shadow);
121
- border-radius: var(--radius-sm);
122
- }
123
-
124
- .trigger[data-disabled] {
125
- color: var(--fg-disabled);
126
- cursor: not-allowed;
127
- }
128
-
129
- /* Leading / Label / Trailing ──────────────────────────── */
130
- .leading {
131
- display: inline-flex;
132
- align-items: center;
133
- gap: var(--space-1);
134
- color: var(--fg-muted);
135
- flex-shrink: 0;
136
- /* MenuItem과 동일 — 슬롯에 들어온 svg/img는 정사각 아이콘 크기로 수렴. */
137
- font-size: var(--accordion-icon-size);
138
- }
139
-
140
- .leading > *,
141
- .leading svg,
142
- .leading img {
143
- width: var(--accordion-icon-size);
144
- height: var(--accordion-icon-size);
145
- }
146
-
147
- .trigger[data-state="open"] .leading {
148
- color: var(--fg-strong);
149
- }
150
-
151
- .leadingItem {
152
- display: inline-flex;
153
- align-items: center;
154
- }
155
-
156
- .label {
157
- flex: 1 1 auto;
158
- min-width: 0;
159
- overflow: hidden;
160
- text-overflow: ellipsis;
161
- white-space: nowrap;
162
- }
163
-
164
- .trailing {
165
- display: inline-flex;
166
- align-items: center;
167
- gap: var(--space-1);
168
- color: var(--fg-muted);
169
- flex-shrink: 0;
170
- }
171
-
172
- .trailingItem {
173
- display: inline-flex;
174
- align-items: center;
175
- }
176
-
177
- /* Caret — open이면 180도 회전.
178
- 라벨·leading 아이콘보다 한 스텝 작게. 상태 보조 신호라 작아야 리듬이 잡힘. */
179
- .caret {
180
- display: inline-flex;
181
- align-items: center;
182
- color: var(--fg-muted);
183
- flex-shrink: 0;
184
- font-size: var(--accordion-caret-size);
185
- transition: transform var(--duration-base) var(--ease-out);
186
- }
187
-
188
- .caret svg {
189
- width: var(--accordion-caret-size);
190
- height: var(--accordion-caret-size);
191
- }
192
-
193
- .trigger[data-state="open"] .caret {
194
- transform: rotate(180deg);
195
- color: var(--fg-strong);
196
- }
197
-
198
- /* Content ──────────────────────────────────────────────── */
199
- /* Radix가 측정한 --radix-accordion-content-height로 slide 애니메이션.
200
- contentInner에 padding을 깔아 열림 애니메이션이 깔끔하게 흐르도록. */
201
- .content {
202
- overflow: hidden;
203
- font-size: var(--text-sm);
204
- line-height: var(--lh-sm);
205
- color: var(--fg);
206
- }
207
-
208
- .content[data-state="open"] {
209
- animation: accordion-slide-down var(--duration-base) var(--ease-out);
210
- }
211
-
212
- .content[data-state="closed"] {
213
- animation: accordion-slide-up var(--duration-fast) var(--ease-in);
214
- }
215
-
216
- .contentInner {
217
- /* 상단은 Trigger와 리듬 유지(겹치지 않게 살짝), 하단은 다음 Trigger와 거리. */
218
- padding: var(--space-1) var(--space-3) var(--space-4);
219
- color: var(--fg);
220
- }
221
-
222
- .root[data-size="md"] .contentInner {
223
- font-size: var(--text-base);
224
- line-height: var(--lh-base);
225
- }
226
-
227
- /* Animations ───────────────────────────────────────────── */
228
- @keyframes accordion-slide-down {
229
- from { height: 0; opacity: 0; }
230
- to { height: var(--radix-accordion-content-height); opacity: 1; }
231
- }
232
-
233
- @keyframes accordion-slide-up {
234
- from { height: var(--radix-accordion-content-height); opacity: 1; }
235
- to { height: 0; opacity: 0; }
236
- }
237
-
238
- @media (prefers-reduced-motion: reduce) {
239
- .content,
240
- .content[data-state="open"],
241
- .content[data-state="closed"] {
242
- animation: none;
243
- }
244
- .caret {
245
- transition: none;
246
- }
247
- }
@@ -1,207 +0,0 @@
1
- "use client";
2
-
3
- /**
4
- * Accordion ─ 여러 섹션을 접었다 폈다 하는 구조 컴포넌트.
5
- *
6
- * 스택: Radix `@radix-ui/react-accordion` 어댑터.
7
- * - 열림/닫힘 상태·키보드 네비(↑↓ Home End)·ARIA(aria-expanded/controls)·
8
- * 콘텐츠 높이 측정은 전부 Radix가 처리.
9
- * - 시각(Trigger 레이아웃·caret·divider·card variant)만 CTDS가 담당.
10
- *
11
- * variant
12
- * - plain (기본): 테두리 없음, 아이템 사이 hairline만. 설정 그룹·FAQ용.
13
- * - card: 각 아이템이 테두리 + radius로 독립 블록. 콘텐츠 사이트의 섹션 리스트용.
14
- *
15
- * 소비 표면
16
- * <Accordion type="single" collapsible defaultValue="general">
17
- * <Accordion.Item value="general">
18
- * <Accordion.Trigger leadingIcon="gear">일반</Accordion.Trigger>
19
- * <Accordion.Content>...</Accordion.Content>
20
- * </Accordion.Item>
21
- * </Accordion>
22
- */
23
-
24
- import * as RadixAccordion from "@radix-ui/react-accordion";
25
- import {
26
- createContext,
27
- forwardRef,
28
- useContext,
29
- type ComponentPropsWithoutRef,
30
- type ReactNode,
31
- } from "react";
32
-
33
- import { Icon, type IconName } from "../Icon";
34
- import styles from "./Accordion.module.css";
35
-
36
- export type AccordionSize = "sm" | "md" | "lg";
37
- /**
38
- * - bare: 선·좌우 여백 전부 없음. 본문 흐름에 가장 투명하게 녹음(툴바·설명 블록 내부).
39
- * - plain: 테두리 없음, 아이템 사이 hairline, Trigger 좌우 padding 있음. 설정·FAQ 흐름.
40
- * - card: 각 아이템이 테두리 + radius로 독립 블록. 콘텐츠 섹션 리스트.
41
- */
42
- export type AccordionVariant = "bare" | "plain" | "card";
43
-
44
- export type AccordionAction =
45
- | ReactNode
46
- | { node: ReactNode; key?: string };
47
-
48
- /* Size·variant context — Trigger가 Root 설정 상속. */
49
- type AccordionContextValue = {
50
- size: AccordionSize;
51
- variant: AccordionVariant;
52
- };
53
- const AccordionContext = createContext<AccordionContextValue>({
54
- size: "sm",
55
- variant: "plain",
56
- });
57
-
58
- /* Root ─────────────────────────────────────────────────────── */
59
-
60
- type SingleRootProps = ComponentPropsWithoutRef<typeof RadixAccordion.Root> & {
61
- type: "single";
62
- };
63
- type MultipleRootProps = ComponentPropsWithoutRef<typeof RadixAccordion.Root> & {
64
- type: "multiple";
65
- };
66
- export type AccordionProps = (SingleRootProps | MultipleRootProps) & {
67
- size?: AccordionSize;
68
- variant?: AccordionVariant;
69
- };
70
-
71
- const Root = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(
72
- { className, size = "sm", variant = "plain", children, ...rest },
73
- ref,
74
- ) {
75
- return (
76
- <AccordionContext.Provider value={{ size, variant }}>
77
- <RadixAccordion.Root
78
- ref={ref}
79
- data-size={size}
80
- data-variant={variant}
81
- className={[styles.root, className ?? ""].filter(Boolean).join(" ")}
82
- {...(rest as ComponentPropsWithoutRef<typeof RadixAccordion.Root>)}
83
- >
84
- {children}
85
- </RadixAccordion.Root>
86
- </AccordionContext.Provider>
87
- );
88
- });
89
-
90
- /* Item ─────────────────────────────────────────────────────── */
91
-
92
- const Item = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<typeof RadixAccordion.Item>>(
93
- function AccordionItem({ className, children, ...rest }, ref) {
94
- return (
95
- <RadixAccordion.Item
96
- ref={ref}
97
- className={[styles.item, className ?? ""].filter(Boolean).join(" ")}
98
- {...rest}
99
- >
100
- {children}
101
- </RadixAccordion.Item>
102
- );
103
- },
104
- );
105
-
106
- /* Trigger ──────────────────────────────────────────────────── */
107
-
108
- export interface TriggerProps
109
- extends Omit<ComponentPropsWithoutRef<typeof RadixAccordion.Trigger>, "children"> {
110
- /** 좌측 아이콘 이름. leading 슬롯 간결 사용. */
111
- leadingIcon?: IconName;
112
- /** 커스텀 좌측 노드 배열. leadingIcon보다 우선. */
113
- leadingActions?: AccordionAction[];
114
- /** 우측 메타(배지·숫자 등). caret은 자동으로 가장 끝. */
115
- trailingActions?: AccordionAction[];
116
- children?: ReactNode;
117
- }
118
-
119
- const Trigger = forwardRef<HTMLButtonElement, TriggerProps>(function AccordionTrigger(
120
- { className, leadingIcon, leadingActions, trailingActions, children, ...rest },
121
- ref,
122
- ) {
123
- const leading =
124
- leadingActions ?? (leadingIcon ? [<Icon key="icon" name={leadingIcon} />] : undefined);
125
- return (
126
- <RadixAccordion.Header className={styles.header}>
127
- <RadixAccordion.Trigger
128
- ref={ref}
129
- className={[styles.trigger, className ?? ""].filter(Boolean).join(" ")}
130
- {...rest}
131
- >
132
- {leading && leading.length > 0 && (
133
- <span className={styles.leading} data-slot="leading" aria-hidden>
134
- {leading.map((a, i) => {
135
- const key =
136
- typeof a === "object" && a !== null && "key" in a && a.key
137
- ? a.key
138
- : String(i);
139
- const node = typeof a === "object" && a !== null && "node" in a ? a.node : a;
140
- return (
141
- <span key={key} className={styles.leadingItem}>
142
- {node as ReactNode}
143
- </span>
144
- );
145
- })}
146
- </span>
147
- )}
148
- <span className={styles.label}>{children}</span>
149
- {trailingActions && trailingActions.length > 0 && (
150
- <span className={styles.trailing} data-slot="trailing">
151
- {trailingActions.map((a, i) => {
152
- const key =
153
- typeof a === "object" && a !== null && "key" in a && a.key
154
- ? a.key
155
- : String(i);
156
- const node = typeof a === "object" && a !== null && "node" in a ? a.node : a;
157
- return (
158
- <span key={key} className={styles.trailingItem}>
159
- {node as ReactNode}
160
- </span>
161
- );
162
- })}
163
- </span>
164
- )}
165
- <span className={styles.caret} aria-hidden>
166
- <Icon name="caret-down" />
167
- </span>
168
- </RadixAccordion.Trigger>
169
- </RadixAccordion.Header>
170
- );
171
- });
172
-
173
- /* Content ──────────────────────────────────────────────────── */
174
-
175
- const Content = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<typeof RadixAccordion.Content>>(
176
- function AccordionContent({ className, children, ...rest }, ref) {
177
- return (
178
- <RadixAccordion.Content
179
- ref={ref}
180
- className={[styles.content, className ?? ""].filter(Boolean).join(" ")}
181
- {...rest}
182
- >
183
- <div className={styles.contentInner}>{children}</div>
184
- </RadixAccordion.Content>
185
- );
186
- },
187
- );
188
-
189
- /* Hook — 내부 Trigger가 size 참조할 때 (현재는 미사용, 향후 확장용) */
190
- export function useAccordionContext() {
191
- return useContext(AccordionContext);
192
- }
193
-
194
- /* Compound export ─────────────────────────────────────────── */
195
-
196
- type AccordionComponent = typeof Root & {
197
- Item: typeof Item;
198
- Trigger: typeof Trigger;
199
- Content: typeof Content;
200
- };
201
-
202
- const Accordion = Root as AccordionComponent;
203
- Accordion.Item = Item;
204
- Accordion.Trigger = Trigger;
205
- Accordion.Content = Content;
206
-
207
- export { Accordion };
@@ -1,8 +0,0 @@
1
- export { Accordion, useAccordionContext } from "./Accordion";
2
- export type {
3
- AccordionProps,
4
- AccordionSize,
5
- AccordionVariant,
6
- AccordionAction,
7
- TriggerProps as AccordionTriggerProps,
8
- } from "./Accordion";