@naeil/ui 0.1.0 → 0.3.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.
Files changed (170) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/DESIGN.md +186 -0
  3. package/LICENSE +21 -0
  4. package/README.md +85 -22
  5. package/THIRD_PARTY_NOTICES.md +49 -0
  6. package/dist/chunk-JBTDRVZ7.js +46 -0
  7. package/dist/chunk-QKVN6Q6C.js +438 -0
  8. package/dist/components/index.d.ts +87 -0
  9. package/dist/components/index.js +832 -0
  10. package/dist/components/ui/index.d.ts +105 -0
  11. package/dist/components/ui/index.js +736 -0
  12. package/dist/lib/utils.d.ts +5 -0
  13. package/dist/lib/utils.js +7 -0
  14. package/dist/source/components/footer.d.ts +15 -0
  15. package/dist/source/components/footer.js +172 -0
  16. package/dist/source/components/index.d.ts +11 -0
  17. package/dist/source/components/index.js +26 -0
  18. package/dist/source/components/locale-switcher.d.ts +17 -0
  19. package/dist/source/components/locale-switcher.js +66 -0
  20. package/dist/source/components/logo.d.ts +9 -0
  21. package/dist/source/components/logo.js +52 -0
  22. package/dist/source/components/nav.d.ts +39 -0
  23. package/dist/source/components/nav.js +412 -0
  24. package/dist/source/components/theme-provider.d.ts +6 -0
  25. package/dist/source/components/theme-provider.js +45 -0
  26. package/dist/source/components/theme-toggle-icon.d.ts +5 -0
  27. package/dist/source/components/theme-toggle-icon.js +62 -0
  28. package/dist/source/components/theme-toggle.d.ts +5 -0
  29. package/dist/source/components/theme-toggle.js +34 -0
  30. package/dist/source/components/typography.d.ts +12 -0
  31. package/dist/source/components/typography.js +49 -0
  32. package/dist/source/components/ui/avatar.d.ts +14 -0
  33. package/dist/source/components/ui/avatar.js +137 -0
  34. package/dist/source/components/ui/badge.d.ts +13 -0
  35. package/dist/source/components/ui/badge.js +76 -0
  36. package/dist/source/components/ui/button.d.ts +14 -0
  37. package/dist/source/components/ui/button.js +88 -0
  38. package/dist/source/components/ui/card.d.ts +13 -0
  39. package/dist/source/components/ui/card.js +135 -0
  40. package/dist/source/components/ui/checkbox.d.ts +7 -0
  41. package/dist/source/components/ui/checkbox.js +58 -0
  42. package/dist/source/components/ui/dialog.d.ts +20 -0
  43. package/dist/source/components/ui/dialog.js +182 -0
  44. package/dist/source/components/ui/dropdown-menu.d.ts +28 -0
  45. package/dist/source/components/ui/dropdown-menu.js +282 -0
  46. package/dist/source/components/ui/index.d.ts +19 -0
  47. package/dist/source/components/ui/index.js +131 -0
  48. package/dist/source/components/ui/input.d.ts +6 -0
  49. package/dist/source/components/ui/input.js +49 -0
  50. package/dist/source/components/ui/select.d.ts +16 -0
  51. package/dist/source/components/ui/select.js +197 -0
  52. package/dist/source/components/ui/sonner.d.ts +6 -0
  53. package/dist/source/components/ui/sonner.js +80 -0
  54. package/dist/source/components/ui/switch.d.ts +7 -0
  55. package/dist/source/components/ui/switch.js +54 -0
  56. package/dist/source/components/ui/tabs.d.ts +10 -0
  57. package/dist/source/components/ui/tabs.js +57 -0
  58. package/dist/source/components/ui/textarea.d.ts +6 -0
  59. package/dist/source/components/ui/textarea.js +46 -0
  60. package/dist/source/i18n/config.d.ts +6 -0
  61. package/dist/source/i18n/config.js +12 -0
  62. package/dist/source/i18n/routing.d.ts +371 -0
  63. package/dist/source/i18n/routing.js +17 -0
  64. package/dist/source/lib/design/modal-inert.d.ts +6 -0
  65. package/dist/source/lib/design/modal-inert.js +73 -0
  66. package/dist/source/lib/utils.d.ts +5 -0
  67. package/dist/source/lib/utils.js +8 -0
  68. package/dist/tokens.ts +217 -0
  69. package/docs/components/README.md +21 -0
  70. package/docs/components/avatar.md +47 -0
  71. package/docs/components/badge.md +29 -0
  72. package/docs/components/button.md +39 -0
  73. package/docs/components/card.md +32 -0
  74. package/docs/components/checkbox.md +35 -0
  75. package/docs/components/common.md +31 -0
  76. package/docs/components/composition.md +68 -0
  77. package/docs/components/dialog.md +41 -0
  78. package/docs/components/dropdown-menu.md +38 -0
  79. package/docs/components/input.md +32 -0
  80. package/docs/components/select.md +39 -0
  81. package/docs/components/sonner.md +37 -0
  82. package/docs/components/switch.md +33 -0
  83. package/docs/components/tabs.md +40 -0
  84. package/docs/components/textarea.md +35 -0
  85. package/docs/design/component-demand.md +30 -0
  86. package/docs/design/public-ui-final-verification.md +96 -0
  87. package/docs/design/public-ui-release-validation.md +86 -0
  88. package/docs/design/public-ui-stage3-verification.md +98 -0
  89. package/docs/design/public-ui-stage4-verification.md +129 -0
  90. package/docs/design/public-ui-support.md +40 -0
  91. package/docs/design/v2-migration.md +199 -0
  92. package/docs/package-release.md +89 -0
  93. package/licenses/Noto-Sans-JP-OFL.txt +93 -0
  94. package/licenses/Nunito-Sans-OFL.txt +93 -0
  95. package/licenses/Pretendard-OFL.txt +94 -0
  96. package/licenses/React-MIT.txt +21 -0
  97. package/licenses/Storybook-MIT.txt +21 -0
  98. package/licenses/popper-MIT.txt +25 -0
  99. package/licenses/react-remove-scroll-bar-MIT.txt +21 -0
  100. package/licenses/store2-MIT.txt +22 -0
  101. package/licenses/toggle-selection-MIT.txt +21 -0
  102. package/package.json +215 -26
  103. package/src/styles/components.css +276 -0
  104. package/src/styles/globals.css +18 -0
  105. package/src/styles/theme.css +293 -0
  106. package/messages/en.json +0 -221
  107. package/messages/ja.json +0 -221
  108. package/messages/ko.json +0 -221
  109. package/postcss.config.mjs +0 -7
  110. package/src/app/[locale]/(content)/baby-agent/page.tsx +0 -30
  111. package/src/app/[locale]/(content)/blog/page.tsx +0 -68
  112. package/src/app/[locale]/(content)/cc/page.tsx +0 -216
  113. package/src/app/[locale]/(content)/design/page.tsx +0 -703
  114. package/src/app/[locale]/(content)/layout.tsx +0 -7
  115. package/src/app/[locale]/(content)/pkm/page.tsx +0 -31
  116. package/src/app/[locale]/(content)/projects/page.tsx +0 -100
  117. package/src/app/[locale]/(content)/sa/page.tsx +0 -179
  118. package/src/app/[locale]/(landing)/page.tsx +0 -157
  119. package/src/app/[locale]/layout.tsx +0 -72
  120. package/src/app/[locale]/login/actions.ts +0 -10
  121. package/src/app/[locale]/login/oauth-buttons.tsx +0 -78
  122. package/src/app/[locale]/login/page.tsx +0 -85
  123. package/src/app/auth/callback/route.ts +0 -78
  124. package/src/app/favicon.ico +0 -0
  125. package/src/app/globals.css +0 -32
  126. package/src/app/layout.tsx +0 -22
  127. package/src/app/sitemap.ts +0 -26
  128. package/src/components/accent-picker.tsx +0 -62
  129. package/src/components/auth-slot.tsx +0 -96
  130. package/src/components/footer-wrapper.tsx +0 -8
  131. package/src/components/footer.tsx +0 -193
  132. package/src/components/hero-scene.tsx +0 -948
  133. package/src/components/hero-section.tsx +0 -57
  134. package/src/components/locale-switcher.tsx +0 -74
  135. package/src/components/logo.tsx +0 -51
  136. package/src/components/nav-server-wrapper.tsx +0 -22
  137. package/src/components/nav-wrapper.tsx +0 -45
  138. package/src/components/nav.tsx +0 -550
  139. package/src/components/paraglider-cursor.tsx +0 -112
  140. package/src/components/project-layout.tsx +0 -194
  141. package/src/components/theme-provider.tsx +0 -10
  142. package/src/components/theme-toggle-icon.tsx +0 -62
  143. package/src/components/theme-toggle.tsx +0 -39
  144. package/src/components/typography.tsx +0 -27
  145. package/src/components/ui/avatar.tsx +0 -109
  146. package/src/components/ui/badge.tsx +0 -47
  147. package/src/components/ui/button.tsx +0 -65
  148. package/src/components/ui/card.tsx +0 -106
  149. package/src/components/ui/dialog.tsx +0 -158
  150. package/src/components/ui/dropdown-menu.tsx +0 -257
  151. package/src/components/ui/input.tsx +0 -21
  152. package/src/components/ui/sonner.tsx +0 -54
  153. package/src/components/workflow-diagram.tsx +0 -414
  154. package/src/i18n/config.ts +0 -8
  155. package/src/i18n/request.ts +0 -16
  156. package/src/i18n/routing.ts +0 -12
  157. package/src/lib/supabase/client.ts +0 -18
  158. package/src/lib/supabase/middleware.ts +0 -42
  159. package/src/lib/supabase/server.ts +0 -37
  160. package/src/lib/utils.ts +0 -6
  161. package/src/proxy.ts +0 -62
  162. package/src/tokens/.gitkeep +0 -0
  163. package/src/tokens/color.json +0 -56
  164. package/src/tokens/radius.json +0 -9
  165. package/src/tokens/semantic.json +0 -81
  166. package/src/tokens/shadow.json +0 -7
  167. package/src/tokens/spacing.json +0 -16
  168. package/src/tokens/typography.json +0 -34
  169. package/src/types/i18n.d.ts +0 -6
  170. package/src/utils/.gitkeep +0 -0
@@ -1,703 +0,0 @@
1
- "use client";
2
-
3
- import { useTranslations } from "next-intl";
4
- import Image from "next/image";
5
- import { Button } from "@/components/ui/button";
6
- import { Input } from "@/components/ui/input";
7
- import {
8
- Card,
9
- CardElevated,
10
- CardHeader,
11
- CardTitle,
12
- CardDescription,
13
- CardContent,
14
- CardFooter,
15
- } from "@/components/ui/card";
16
- import {
17
- Dialog,
18
- DialogTrigger,
19
- DialogContent,
20
- DialogHeader,
21
- DialogTitle,
22
- DialogDescription,
23
- DialogFooter,
24
- DialogClose,
25
- } from "@/components/ui/dialog";
26
- import {
27
- DropdownMenu,
28
- DropdownMenuTrigger,
29
- DropdownMenuContent,
30
- DropdownMenuItem,
31
- DropdownMenuSeparator,
32
- DropdownMenuLabel,
33
- } from "@/components/ui/dropdown-menu";
34
- import { Badge } from "@/components/ui/badge";
35
- import {
36
- Avatar,
37
- AvatarImage,
38
- AvatarFallback,
39
- AvatarBadge,
40
- AvatarGroup,
41
- AvatarGroupCount,
42
- } from "@/components/ui/avatar";
43
- import { AccentPicker } from "@/components/accent-picker";
44
- import {
45
- PageTitle,
46
- SectionTitle,
47
- pageTitleClass,
48
- sectionTitleClass,
49
- } from "@/components/typography";
50
- import { toast } from "sonner";
51
-
52
- /* ─── Token Data (for showcase display) ─── */
53
-
54
- const GRAY_SCALE = [
55
- { step: "50", oklch: "oklch(0.985 0 0)" },
56
- { step: "100", oklch: "oklch(0.970 0 0)" },
57
- { step: "200", oklch: "oklch(0.922 0 0)" },
58
- { step: "300", oklch: "oklch(0.870 0 0)" },
59
- { step: "400", oklch: "oklch(0.708 0 0)" },
60
- { step: "500", oklch: "oklch(0.556 0 0)" },
61
- { step: "600", oklch: "oklch(0.439 0 0)" },
62
- { step: "700", oklch: "oklch(0.371 0 0)" },
63
- { step: "800", oklch: "oklch(0.269 0 0)" },
64
- { step: "900", oklch: "oklch(0.205 0 0)" },
65
- { step: "950", oklch: "oklch(0.145 0 0)" },
66
- ];
67
-
68
- const ACCENT_SCALE = [
69
- { step: "50", oklch: "oklch(0.970 0.014 254)" },
70
- { step: "100", oklch: "oklch(0.932 0.032 255)" },
71
- { step: "200", oklch: "oklch(0.882 0.059 254)" },
72
- { step: "300", oklch: "oklch(0.809 0.105 254)" },
73
- { step: "400", oklch: "oklch(0.707 0.165 254)" },
74
- { step: "500", oklch: "oklch(0.623 0.214 259)" },
75
- { step: "600", oklch: "oklch(0.546 0.245 263)" },
76
- { step: "700", oklch: "oklch(0.488 0.243 264.376)" },
77
- { step: "800", oklch: "oklch(0.424 0.199 265)" },
78
- { step: "900", oklch: "oklch(0.379 0.146 265)" },
79
- { step: "950", oklch: "oklch(0.282 0.091 267)" },
80
- ];
81
-
82
- const DESTRUCTIVE_SCALE = [
83
- { step: "50", oklch: "oklch(0.971 0.013 17)" },
84
- { step: "100", oklch: "oklch(0.936 0.032 17)" },
85
- { step: "200", oklch: "oklch(0.885 0.062 18)" },
86
- { step: "300", oklch: "oklch(0.808 0.114 19)" },
87
- { step: "400", oklch: "oklch(0.704 0.191 22.216)" },
88
- { step: "500", oklch: "oklch(0.637 0.237 25)" },
89
- { step: "600", oklch: "oklch(0.577 0.245 27.325)" },
90
- { step: "700", oklch: "oklch(0.505 0.213 27)" },
91
- { step: "800", oklch: "oklch(0.444 0.177 26)" },
92
- { step: "900", oklch: "oklch(0.396 0.141 25)" },
93
- { step: "950", oklch: "oklch(0.258 0.092 26)" },
94
- ];
95
-
96
- const SEMANTIC_TOKENS = [
97
- "background",
98
- "foreground",
99
- "card",
100
- "card-foreground",
101
- "primary",
102
- "primary-foreground",
103
- "secondary",
104
- "secondary-foreground",
105
- "muted",
106
- "muted-foreground",
107
- "accent",
108
- "accent-foreground",
109
- "destructive",
110
- "destructive-foreground",
111
- "border",
112
- "border-subtle",
113
- "border-subtle-hover",
114
- "surface-subtle",
115
- "input",
116
- "ring",
117
- ];
118
-
119
- const PROJECT_COLORS = [
120
- { name: "CC", token: "--project-cc", oklch: "oklch(0.704 0.140 181)" },
121
- { name: "SA", token: "--project-sa", oklch: "oklch(0.723 0.219 149)" },
122
- { name: "PKM", token: "--project-pkm", oklch: "oklch(0.627 0.265 303)" },
123
- { name: "naeil-ui", token: "--project-naeilUi", oklch: "oklch(0.623 0.214 259)" },
124
- { name: "Baby Agent", token: "--project-baby", oklch: "oklch(0.769 0.188 70.08)" },
125
- ];
126
-
127
- const TYPE_SIZES = [
128
- { name: "xs", class: "text-xs" },
129
- { name: "sm", class: "text-sm" },
130
- { name: "base", class: "text-base" },
131
- { name: "lg", class: "text-lg" },
132
- { name: "xl", class: "text-xl" },
133
- { name: "2xl", class: "text-2xl" },
134
- { name: "3xl", class: "text-3xl" },
135
- { name: "4xl", class: "text-4xl" },
136
- ];
137
-
138
- const SPACING_STEPS = [
139
- { name: "0", px: "0" },
140
- { name: "1", px: "4" },
141
- { name: "2", px: "8" },
142
- { name: "3", px: "12" },
143
- { name: "4", px: "16" },
144
- { name: "5", px: "20" },
145
- { name: "6", px: "24" },
146
- { name: "8", px: "32" },
147
- { name: "10", px: "40" },
148
- { name: "12", px: "48" },
149
- { name: "16", px: "64" },
150
- ];
151
-
152
- /* ─── Helper Components ─── */
153
-
154
- function SectionHeading({ children }: { children: React.ReactNode }) {
155
- return <SectionTitle>{children}</SectionTitle>;
156
- }
157
-
158
- function SubHeading({ children }: { children: React.ReactNode }) {
159
- return (
160
- <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-widest">
161
- {children}
162
- </h3>
163
- );
164
- }
165
-
166
- function ColorScale({
167
- name,
168
- colors,
169
- }: {
170
- name: string;
171
- colors: { step: string; oklch: string }[];
172
- }) {
173
- return (
174
- <div className="flex flex-col gap-2">
175
- <SubHeading>{name}</SubHeading>
176
- <div className="flex gap-1">
177
- {colors.map((c) => (
178
- <div key={c.step} className="flex flex-col items-center gap-1 flex-1">
179
- <div
180
- className="w-full aspect-square rounded-md border border-border"
181
- style={{ backgroundColor: c.oklch }}
182
- />
183
- <span className="text-[10px] text-muted-foreground font-mono">
184
- {c.step}
185
- </span>
186
- </div>
187
- ))}
188
- </div>
189
- </div>
190
- );
191
- }
192
-
193
- function SemanticTokenGrid() {
194
- return (
195
- <div className="grid grid-cols-3 gap-2 sm:grid-cols-4 md:grid-cols-6">
196
- {SEMANTIC_TOKENS.map((token) => (
197
- <div key={token} className="flex flex-col items-center gap-1">
198
- <div
199
- className="w-full aspect-square rounded-md border border-border"
200
- style={{ backgroundColor: `var(--${token})` }}
201
- />
202
- <span className="text-[10px] text-muted-foreground font-mono text-center leading-tight">
203
- {token}
204
- </span>
205
- </div>
206
- ))}
207
- </div>
208
- );
209
- }
210
-
211
- /* ─── Main Page ─── */
212
-
213
- export default function Home() {
214
- const t = useTranslations("design");
215
-
216
- return (
217
- <>
218
- {/* Hero — matches ProjectLayout */}
219
- <section className="mx-auto max-w-4xl px-6 pb-16">
220
- <div className="flex flex-col-reverse items-start gap-8 md:flex-row md:items-start md:justify-between">
221
- <div className="flex-1">
222
- <PageTitle className="mb-3">{t("title")}</PageTitle>
223
- <p className="text-muted-foreground mb-5 max-w-lg text-lg leading-relaxed">
224
- {t("subtitle")}
225
- </p>
226
- <div className="mb-6 flex flex-wrap gap-2">
227
- {["React", "Tailwind v4", "OKLCH", "shadcn/ui"].map((tag) => (
228
- <span
229
- key={tag}
230
- className="rounded-full border border-black/[0.08] px-2.5 py-1 text-[11px] text-zinc-400 dark:border-white/[0.08]"
231
- >
232
- {tag}
233
- </span>
234
- ))}
235
- </div>
236
- <div className="flex flex-wrap items-center gap-3">
237
- <a
238
- href="https://github.com/naeil-dev/design-system"
239
- target="_blank"
240
- rel="noopener noreferrer"
241
- className="inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-medium transition-colors"
242
- style={{
243
- background: "oklch(0.623 0.214 259)",
244
- color: "var(--background)",
245
- }}
246
- >
247
- GitHub →
248
- </a>
249
- </div>
250
- </div>
251
- <div className="flex-shrink-0">
252
- <Image
253
- src="/images/whale.png"
254
- alt=""
255
- width={220}
256
- height={220}
257
- className="animate-float object-contain"
258
- style={{
259
- filter: "drop-shadow(0 4px 12px color-mix(in oklch, oklch(0.623 0.214 259) 15%, transparent))",
260
- }}
261
- />
262
- </div>
263
- </div>
264
- </section>
265
-
266
- <div className="flex flex-col gap-16 pb-24 max-w-4xl mx-auto px-6">
267
-
268
- {/* ════════════════════════════════════════════
269
- T45: Accent Demo
270
- ════════════════════════════════════════════ */}
271
- <section className="flex flex-col gap-4">
272
- <SectionHeading>Accent</SectionHeading>
273
- <p className="text-sm text-muted-foreground">
274
- 프로젝트별 악센트 색상 주입. 아래 프리셋을 선택하면 모든 accent 토큰이 즉시 변경됩니다.
275
- </p>
276
- <AccentPicker />
277
- </section>
278
-
279
- {/* ════════════════════════════════════════════
280
- T43: Token Showcase
281
- ════════════════════════════════════════════ */}
282
-
283
- {/* Colors — Primitive */}
284
- <section className="flex flex-col gap-6">
285
- <SectionHeading>Colors — Primitive</SectionHeading>
286
- <ColorScale name="Gray" colors={GRAY_SCALE} />
287
- <ColorScale name="Accent (Blue default)" colors={ACCENT_SCALE} />
288
- <ColorScale name="Destructive" colors={DESTRUCTIVE_SCALE} />
289
- </section>
290
-
291
- {/* Colors — Semantic */}
292
- <section className="flex flex-col gap-4">
293
- <SectionHeading>Colors — Semantic</SectionHeading>
294
- <p className="text-sm text-muted-foreground">
295
- 현재 테마(다크/라이트)에 따라 매핑이 변경됩니다.
296
- </p>
297
- <SemanticTokenGrid />
298
- </section>
299
-
300
- {/* Colors — Project Accents */}
301
- <section className="flex flex-col gap-4">
302
- <SectionHeading>Colors — Project</SectionHeading>
303
- <p className="text-sm text-muted-foreground">
304
- 프로젝트별 악센트 색상. 라이트/다크 동일.
305
- </p>
306
- <div className="flex gap-4">
307
- {PROJECT_COLORS.map((c) => (
308
- <div key={c.name} className="flex flex-col items-center gap-2 flex-1">
309
- <div
310
- className="w-full aspect-square rounded-md border border-border"
311
- style={{ backgroundColor: c.oklch }}
312
- />
313
- <span className="text-[11px] text-muted-foreground font-mono text-center leading-tight">
314
- {c.name}
315
- </span>
316
- </div>
317
- ))}
318
- </div>
319
- </section>
320
-
321
- {/* Heading Primitives */}
322
- <section className="flex flex-col gap-4">
323
- <SectionHeading>Heading Primitives</SectionHeading>
324
- <p className="text-sm text-muted-foreground">
325
- 공통 헤딩 컴포넌트로 모든 페이지의 제목 스케일을 통합 관리.
326
- </p>
327
-
328
- <div className="grid gap-3 sm:grid-cols-2">
329
- <div className="rounded-xl border border-border-subtle bg-surface-subtle p-5">
330
- <p className="mb-2 text-xs font-mono text-muted-foreground">PageTitle</p>
331
- <p className={pageTitleClass}>System-level page heading</p>
332
- <p className="mt-2 text-xs text-muted-foreground">text-4xl → lg:text-5xl</p>
333
- </div>
334
-
335
- <div className="rounded-xl border border-border-subtle bg-surface-subtle p-5">
336
- <p className="mb-2 text-xs font-mono text-muted-foreground">SectionTitle</p>
337
- <p className={sectionTitleClass}>Section heading baseline</p>
338
- <p className="mt-2 text-xs text-muted-foreground">text-lg</p>
339
- </div>
340
- </div>
341
- </section>
342
-
343
- {/* Typography */}
344
- <section className="flex flex-col gap-6">
345
- <SectionHeading>Typography</SectionHeading>
346
-
347
- <div className="flex flex-col gap-1">
348
- <SubHeading>Sans (Pretendard)</SubHeading>
349
- <div className="flex flex-col gap-2">
350
- {TYPE_SIZES.map((t) => (
351
- <div key={t.name} className="flex items-baseline gap-4">
352
- <span className="text-xs text-muted-foreground font-mono w-10 shrink-0 text-right">
353
- {t.name}
354
- </span>
355
- <span className={`${t.class} font-normal`}>
356
- 가나다라 ABCabc 012
357
- </span>
358
- </div>
359
- ))}
360
- </div>
361
- </div>
362
-
363
- <div className="flex flex-col gap-1">
364
- <SubHeading>Mono (JetBrains Mono)</SubHeading>
365
- <div className="flex flex-col gap-2">
366
- {TYPE_SIZES.slice(0, 5).map((t) => (
367
- <div key={t.name} className="flex items-baseline gap-4">
368
- <span className="text-xs text-muted-foreground font-mono w-10 shrink-0 text-right">
369
- {t.name}
370
- </span>
371
- <span className={`${t.class} font-mono`}>
372
- const x = 42; // →
373
- </span>
374
- </div>
375
- ))}
376
- </div>
377
- </div>
378
-
379
- <div className="flex flex-col gap-1">
380
- <SubHeading>Weights</SubHeading>
381
- <div className="flex flex-col gap-2">
382
- <span className="text-lg font-normal">
383
- 400 Regular — 기본 텍스트 본문
384
- </span>
385
- <span className="text-lg font-medium">
386
- 500 Medium — 강조 라벨
387
- </span>
388
- <span className="text-lg font-bold">
389
- 700 Bold — 제목 헤딩
390
- </span>
391
- </div>
392
- </div>
393
- </section>
394
-
395
- {/* Spacing */}
396
- <section className="flex flex-col gap-4">
397
- <SectionHeading>Spacing</SectionHeading>
398
- <div className="flex flex-col gap-2">
399
- {SPACING_STEPS.map((s) => (
400
- <div key={s.name} className="flex items-center gap-3">
401
- <span className="text-xs text-muted-foreground font-mono w-8 text-right shrink-0">
402
- {s.name}
403
- </span>
404
- <div
405
- className="h-3 rounded-sm bg-primary"
406
- style={{ width: `${s.px}px` }}
407
- />
408
- <span className="text-xs text-muted-foreground font-mono">
409
- {s.px}px
410
- </span>
411
- </div>
412
- ))}
413
- </div>
414
- </section>
415
-
416
- {/* Radius */}
417
- <section className="flex flex-col gap-4">
418
- <SectionHeading>Radius</SectionHeading>
419
- <div className="flex gap-6">
420
- {[
421
- { name: "none", class: "rounded-none", px: "0px" },
422
- { name: "sm", class: "rounded-sm", px: "2px" },
423
- { name: "md", class: "rounded-md", px: "4px" },
424
- { name: "lg", class: "rounded-lg", px: "8px" },
425
- ].map((r) => (
426
- <div key={r.name} className="flex flex-col items-center gap-2">
427
- <div
428
- className={`size-16 bg-primary ${r.class}`}
429
- />
430
- <span className="text-xs text-muted-foreground font-mono">
431
- {r.name} ({r.px})
432
- </span>
433
- </div>
434
- ))}
435
- </div>
436
- </section>
437
-
438
- {/* Shadow */}
439
- <section className="flex flex-col gap-4">
440
- <SectionHeading>Shadow</SectionHeading>
441
- <div className="flex gap-6">
442
- <div className="flex flex-col items-center gap-2">
443
- <div className="size-24 rounded-md bg-card border border-border shadow-sm" />
444
- <span className="text-xs text-muted-foreground font-mono">
445
- shadow-sm
446
- </span>
447
- </div>
448
- <div className="flex flex-col items-center gap-2">
449
- <div className="size-24 rounded-md bg-card border border-border shadow-md" />
450
- <span className="text-xs text-muted-foreground font-mono">
451
- shadow-md
452
- </span>
453
- </div>
454
- </div>
455
- </section>
456
-
457
- {/* ════════════════════════════════════════════
458
- T44: Component Showcase
459
- ════════════════════════════════════════════ */}
460
-
461
- {/* Button */}
462
- <section className="flex flex-col gap-4">
463
- <SectionHeading>Button</SectionHeading>
464
- <SubHeading>Variants</SubHeading>
465
- <div className="flex flex-wrap gap-3">
466
- <Button>Default</Button>
467
- <Button variant="secondary">Secondary</Button>
468
- <Button variant="outline">Outline</Button>
469
- <Button variant="destructive">Destructive</Button>
470
- <Button variant="ghost">Ghost</Button>
471
- <Button variant="link">Link</Button>
472
- </div>
473
- <SubHeading>Sizes</SubHeading>
474
- <div className="flex flex-wrap items-center gap-3">
475
- <Button size="xs">XS</Button>
476
- <Button size="sm">SM</Button>
477
- <Button size="default">Default</Button>
478
- <Button size="lg">LG</Button>
479
- </div>
480
- <SubHeading>States</SubHeading>
481
- <div className="flex flex-wrap gap-3">
482
- <Button disabled>Disabled</Button>
483
- <Button variant="outline" disabled>
484
- Outline Disabled
485
- </Button>
486
- </div>
487
- </section>
488
-
489
- {/* Input */}
490
- <section className="flex flex-col gap-4">
491
- <SectionHeading>Input</SectionHeading>
492
- <div className="grid gap-3 sm:grid-cols-2">
493
- <Input placeholder="기본 입력" />
494
- <Input type="email" placeholder="이메일" />
495
- <Input disabled placeholder="비활성화" />
496
- <Input aria-invalid="true" placeholder="에러 상태" />
497
- </div>
498
- </section>
499
-
500
- {/* Card */}
501
- <section className="flex flex-col gap-4">
502
- <SectionHeading>Card</SectionHeading>
503
- <div className="grid gap-4 sm:grid-cols-2">
504
- <Card>
505
- <CardHeader>
506
- <CardTitle>시스템 상태</CardTitle>
507
- <CardDescription>현재 시스템 운영 정보</CardDescription>
508
- </CardHeader>
509
- <CardContent>
510
- <p className="text-sm">모든 서비스가 정상 운영 중입니다.</p>
511
- </CardContent>
512
- <CardFooter>
513
- <Button variant="outline" size="sm">
514
- 상세 보기
515
- </Button>
516
- </CardFooter>
517
- </Card>
518
- <Card>
519
- <CardHeader>
520
- <CardTitle>배포 로그</CardTitle>
521
- <CardDescription>최근 배포 히스토리</CardDescription>
522
- </CardHeader>
523
- <CardContent>
524
- <div className="flex flex-col gap-1">
525
- <p className="text-sm font-mono text-muted-foreground">
526
- v0.6.0 — Phase 6 Demo
527
- </p>
528
- <p className="text-sm font-mono text-muted-foreground">
529
- v0.5.0 — Core Components
530
- </p>
531
- </div>
532
- </CardContent>
533
- </Card>
534
- </div>
535
- <SubHeading>Elevated</SubHeading>
536
- <div className="grid gap-4 sm:grid-cols-2">
537
- <CardElevated>
538
- <CardHeader>
539
- <CardTitle>Elevated Card</CardTitle>
540
- <CardDescription>다크 모드에서 밝기 차이로 elevation 표현</CardDescription>
541
- </CardHeader>
542
- <CardContent>
543
- <p className="text-sm">shadow-sm + 다크 배경 밝기 상승</p>
544
- </CardContent>
545
- </CardElevated>
546
- </div>
547
- </section>
548
-
549
- {/* Dialog */}
550
- <section className="flex flex-col gap-4">
551
- <SectionHeading>Dialog</SectionHeading>
552
- <Dialog>
553
- <DialogTrigger asChild>
554
- <Button variant="outline">다이얼로그 열기</Button>
555
- </DialogTrigger>
556
- <DialogContent>
557
- <DialogHeader>
558
- <DialogTitle>확인</DialogTitle>
559
- <DialogDescription>
560
- 이 작업을 계속 진행하시겠습니까?
561
- </DialogDescription>
562
- </DialogHeader>
563
- <DialogFooter>
564
- <DialogClose asChild>
565
- <Button variant="outline">취소</Button>
566
- </DialogClose>
567
- <Button>확인</Button>
568
- </DialogFooter>
569
- </DialogContent>
570
- </Dialog>
571
- </section>
572
-
573
- {/* Dropdown Menu */}
574
- <section className="flex flex-col gap-4">
575
- <SectionHeading>Dropdown Menu</SectionHeading>
576
- <DropdownMenu>
577
- <DropdownMenuTrigger asChild>
578
- <Button variant="outline">메뉴 열기</Button>
579
- </DropdownMenuTrigger>
580
- <DropdownMenuContent>
581
- <DropdownMenuLabel>작업</DropdownMenuLabel>
582
- <DropdownMenuSeparator />
583
- <DropdownMenuItem>프로필</DropdownMenuItem>
584
- <DropdownMenuItem>설정</DropdownMenuItem>
585
- <DropdownMenuItem>팀 관리</DropdownMenuItem>
586
- <DropdownMenuSeparator />
587
- <DropdownMenuItem variant="destructive">
588
- 로그아웃
589
- </DropdownMenuItem>
590
- </DropdownMenuContent>
591
- </DropdownMenu>
592
- </section>
593
-
594
- {/* Sonner */}
595
- <section className="flex flex-col gap-4">
596
- <SectionHeading>Sonner (Toast)</SectionHeading>
597
- <div className="flex flex-wrap gap-3">
598
- <Button
599
- variant="outline"
600
- onClick={() => toast.success("배포가 완료되었습니다.")}
601
- >
602
- Success
603
- </Button>
604
- <Button
605
- variant="outline"
606
- onClick={() => toast.error("배포에 실패했습니다.")}
607
- >
608
- Error
609
- </Button>
610
- <Button
611
- variant="outline"
612
- onClick={() => toast.info("새로운 업데이트가 있습니다.")}
613
- >
614
- Info
615
- </Button>
616
- <Button
617
- variant="outline"
618
- onClick={() => toast.warning("디스크 용량이 부족합니다.")}
619
- >
620
- Warning
621
- </Button>
622
- </div>
623
- </section>
624
-
625
- {/* Badge */}
626
- <section className="flex flex-col gap-4">
627
- <SectionHeading>Badge</SectionHeading>
628
- <div className="flex flex-wrap gap-3">
629
- <Badge>Default</Badge>
630
- <Badge variant="secondary">Secondary</Badge>
631
- <Badge variant="outline">Outline</Badge>
632
- <Badge variant="destructive">Destructive</Badge>
633
- </div>
634
- </section>
635
-
636
- {/* Avatar */}
637
- <section className="flex flex-col gap-6">
638
- <SectionHeading>Avatar</SectionHeading>
639
-
640
- <div>
641
- <SubHeading>Sizes</SubHeading>
642
- <div className="flex items-center gap-4 mt-2">
643
- <Avatar size="sm">
644
- <AvatarFallback>S</AvatarFallback>
645
- </Avatar>
646
- <Avatar>
647
- <AvatarImage
648
- src="https://github.com/shadcn.png"
649
- alt="shadcn"
650
- />
651
- <AvatarFallback>SC</AvatarFallback>
652
- </Avatar>
653
- <Avatar size="lg">
654
- <AvatarFallback>LG</AvatarFallback>
655
- </Avatar>
656
- </div>
657
- </div>
658
-
659
- <div>
660
- <SubHeading>With Badge</SubHeading>
661
- <div className="flex items-center gap-4 mt-2">
662
- <Avatar>
663
- <AvatarImage
664
- src="https://github.com/shadcn.png"
665
- alt="shadcn"
666
- />
667
- <AvatarFallback>SC</AvatarFallback>
668
- <AvatarBadge />
669
- </Avatar>
670
- <Avatar size="lg">
671
- <AvatarFallback>JM</AvatarFallback>
672
- <AvatarBadge />
673
- </Avatar>
674
- </div>
675
- </div>
676
-
677
- <div>
678
- <SubHeading>Group</SubHeading>
679
- <div className="mt-2">
680
- <AvatarGroup>
681
- <Avatar>
682
- <AvatarImage
683
- src="https://github.com/shadcn.png"
684
- alt="1"
685
- />
686
- <AvatarFallback>A</AvatarFallback>
687
- </Avatar>
688
- <Avatar>
689
- <AvatarFallback>B</AvatarFallback>
690
- </Avatar>
691
- <Avatar>
692
- <AvatarFallback>C</AvatarFallback>
693
- </Avatar>
694
- <AvatarGroupCount>+5</AvatarGroupCount>
695
- </AvatarGroup>
696
- </div>
697
- </div>
698
- </section>
699
-
700
- </div>
701
- </>
702
- );
703
- }