@mandujs/mcp 0.9.19 → 0.9.21

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 (122) hide show
  1. package/README.md +320 -0
  2. package/package.json +1 -1
  3. package/src/activity-monitor.ts +847 -231
  4. package/src/resources/handlers.ts +244 -0
  5. package/src/resources/skills/guides.ts +1136 -0
  6. package/src/resources/skills/index.ts +12 -0
  7. package/src/resources/skills/loader.ts +218 -0
  8. package/src/resources/skills/mandu-composition/SKILL.md +91 -0
  9. package/src/resources/skills/mandu-composition/metadata.json +13 -0
  10. package/src/resources/skills/mandu-composition/rules/_sections.md +26 -0
  11. package/src/resources/skills/mandu-composition/rules/_template.md +77 -0
  12. package/src/resources/skills/mandu-composition/rules/comp-arch-avoid-boolean-props.md +146 -0
  13. package/src/resources/skills/mandu-composition/rules/comp-arch-compound-components.md +164 -0
  14. package/src/resources/skills/mandu-composition/rules/comp-island-event.md +161 -0
  15. package/src/resources/skills/mandu-composition/rules/comp-island-slot-split.md +167 -0
  16. package/src/resources/skills/mandu-composition/rules/comp-pattern-children.md +149 -0
  17. package/src/resources/skills/mandu-composition/rules/comp-state-context-interface.md +148 -0
  18. package/src/resources/skills/mandu-composition/rules/comp-state-lift-state.md +150 -0
  19. package/src/resources/skills/mandu-deployment/SKILL.md +92 -0
  20. package/src/resources/skills/mandu-deployment/_sections.md +41 -0
  21. package/src/resources/skills/mandu-deployment/_template.md +38 -0
  22. package/src/resources/skills/mandu-deployment/metadata.json +13 -0
  23. package/src/resources/skills/mandu-deployment/rules/deploy-build-bun.md +109 -0
  24. package/src/resources/skills/mandu-deployment/rules/deploy-build-output.md +115 -0
  25. package/src/resources/skills/mandu-deployment/rules/deploy-cicd-github.md +219 -0
  26. package/src/resources/skills/mandu-deployment/rules/deploy-docker-bun.md +150 -0
  27. package/src/resources/skills/mandu-deployment/rules/deploy-docker-compose.md +223 -0
  28. package/src/resources/skills/mandu-deployment/rules/deploy-platform-fly.md +152 -0
  29. package/src/resources/skills/mandu-deployment/rules/deploy-platform-render.md +179 -0
  30. package/src/resources/skills/mandu-deployment/rules/deploy-platform-supabase.md +323 -0
  31. package/src/resources/skills/mandu-deployment/rules/deploy-platform-vercel.md +140 -0
  32. package/src/resources/skills/mandu-fs-routes/SKILL.md +82 -0
  33. package/src/resources/skills/mandu-fs-routes/metadata.json +12 -0
  34. package/src/resources/skills/mandu-fs-routes/rules/_sections.md +36 -0
  35. package/src/resources/skills/mandu-fs-routes/rules/_template.md +69 -0
  36. package/src/resources/skills/mandu-fs-routes/rules/routes-api-methods.md +65 -0
  37. package/src/resources/skills/mandu-fs-routes/rules/routes-dynamic-param.md +93 -0
  38. package/src/resources/skills/mandu-fs-routes/rules/routes-naming-page.md +55 -0
  39. package/src/resources/skills/mandu-guard/SKILL.md +129 -0
  40. package/src/resources/skills/mandu-guard/metadata.json +12 -0
  41. package/src/resources/skills/mandu-guard/rules/_sections.md +36 -0
  42. package/src/resources/skills/mandu-guard/rules/_template.md +82 -0
  43. package/src/resources/skills/mandu-guard/rules/guard-config-rules.md +100 -0
  44. package/src/resources/skills/mandu-guard/rules/guard-layer-direction.md +76 -0
  45. package/src/resources/skills/mandu-guard/rules/guard-preset-mandu.md +81 -0
  46. package/src/resources/skills/mandu-guard/rules/guard-validate-import.md +80 -0
  47. package/src/resources/skills/mandu-hydration/SKILL.md +91 -0
  48. package/src/resources/skills/mandu-hydration/metadata.json +12 -0
  49. package/src/resources/skills/mandu-hydration/rules/_sections.md +31 -0
  50. package/src/resources/skills/mandu-hydration/rules/_template.md +72 -0
  51. package/src/resources/skills/mandu-hydration/rules/hydration-data-event.md +109 -0
  52. package/src/resources/skills/mandu-hydration/rules/hydration-directive-use-client.md +55 -0
  53. package/src/resources/skills/mandu-hydration/rules/hydration-island-setup.md +113 -0
  54. package/src/resources/skills/mandu-hydration/rules/hydration-priority-visible.md +68 -0
  55. package/src/resources/skills/mandu-performance/SKILL.md +85 -0
  56. package/src/resources/skills/mandu-performance/metadata.json +14 -0
  57. package/src/resources/skills/mandu-performance/rules/_sections.md +31 -0
  58. package/src/resources/skills/mandu-performance/rules/_template.md +64 -0
  59. package/src/resources/skills/mandu-performance/rules/perf-async-defer-await.md +103 -0
  60. package/src/resources/skills/mandu-performance/rules/perf-async-parallel.md +95 -0
  61. package/src/resources/skills/mandu-performance/rules/perf-bun-file.md +124 -0
  62. package/src/resources/skills/mandu-performance/rules/perf-bun-serve.md +125 -0
  63. package/src/resources/skills/mandu-performance/rules/perf-bundle-imports.md +80 -0
  64. package/src/resources/skills/mandu-performance/rules/perf-bundle-island-lazy.md +145 -0
  65. package/src/resources/skills/mandu-performance/rules/perf-cache-react.md +98 -0
  66. package/src/resources/skills/mandu-performance/rules/perf-render-transitions.md +154 -0
  67. package/src/resources/skills/mandu-security/SKILL.md +87 -0
  68. package/src/resources/skills/mandu-security/metadata.json +13 -0
  69. package/src/resources/skills/mandu-security/rules/_sections.md +31 -0
  70. package/src/resources/skills/mandu-security/rules/_template.md +74 -0
  71. package/src/resources/skills/mandu-security/rules/sec-auth-guard.md +127 -0
  72. package/src/resources/skills/mandu-security/rules/sec-env-management.md +133 -0
  73. package/src/resources/skills/mandu-security/rules/sec-input-validate.md +148 -0
  74. package/src/resources/skills/mandu-security/rules/sec-protect-csrf.md +146 -0
  75. package/src/resources/skills/mandu-security/rules/sec-protect-headers.md +138 -0
  76. package/src/resources/skills/mandu-slot/SKILL.md +85 -0
  77. package/src/resources/skills/mandu-slot/metadata.json +12 -0
  78. package/src/resources/skills/mandu-slot/rules/_sections.md +36 -0
  79. package/src/resources/skills/mandu-slot/rules/_template.md +63 -0
  80. package/src/resources/skills/mandu-slot/rules/slot-basic-structure.md +38 -0
  81. package/src/resources/skills/mandu-slot/rules/slot-ctx-response.md +56 -0
  82. package/src/resources/skills/mandu-slot/rules/slot-guard-auth.md +59 -0
  83. package/src/resources/skills/mandu-slot/rules/slot-http-methods.md +64 -0
  84. package/src/resources/skills/mandu-styling/SKILL.md +118 -0
  85. package/src/resources/skills/mandu-styling/_sections.md +36 -0
  86. package/src/resources/skills/mandu-styling/_template.md +32 -0
  87. package/src/resources/skills/mandu-styling/metadata.json +13 -0
  88. package/src/resources/skills/mandu-styling/rules/style-component-compound.md +235 -0
  89. package/src/resources/skills/mandu-styling/rules/style-component-slots.md +255 -0
  90. package/src/resources/skills/mandu-styling/rules/style-component-tokens.md +205 -0
  91. package/src/resources/skills/mandu-styling/rules/style-island-animations.md +272 -0
  92. package/src/resources/skills/mandu-styling/rules/style-island-scoping.md +167 -0
  93. package/src/resources/skills/mandu-styling/rules/style-island-variants.md +221 -0
  94. package/src/resources/skills/mandu-styling/rules/style-perf-critical.md +209 -0
  95. package/src/resources/skills/mandu-styling/rules/style-perf-purge.md +192 -0
  96. package/src/resources/skills/mandu-styling/rules/style-setup-modules.md +162 -0
  97. package/src/resources/skills/mandu-styling/rules/style-setup-panda.md +164 -0
  98. package/src/resources/skills/mandu-styling/rules/style-setup-tailwind.md +161 -0
  99. package/src/resources/skills/mandu-styling/rules/style-theme-darkmode.md +229 -0
  100. package/src/resources/skills/mandu-testing/SKILL.md +99 -0
  101. package/src/resources/skills/mandu-testing/metadata.json +13 -0
  102. package/src/resources/skills/mandu-testing/rules/_sections.md +26 -0
  103. package/src/resources/skills/mandu-testing/rules/_template.md +65 -0
  104. package/src/resources/skills/mandu-testing/rules/test-component-island.md +195 -0
  105. package/src/resources/skills/mandu-testing/rules/test-e2e-playwright.md +196 -0
  106. package/src/resources/skills/mandu-testing/rules/test-mock-fetch.md +219 -0
  107. package/src/resources/skills/mandu-testing/rules/test-slot-unit.md +192 -0
  108. package/src/resources/skills/mandu-ui/SKILL.md +117 -0
  109. package/src/resources/skills/mandu-ui/_sections.md +23 -0
  110. package/src/resources/skills/mandu-ui/_template.md +32 -0
  111. package/src/resources/skills/mandu-ui/metadata.json +13 -0
  112. package/src/resources/skills/mandu-ui/rules/ui-accessibility-aria.md +232 -0
  113. package/src/resources/skills/mandu-ui/rules/ui-accessibility-focus.md +238 -0
  114. package/src/resources/skills/mandu-ui/rules/ui-composition-patterns.md +259 -0
  115. package/src/resources/skills/mandu-ui/rules/ui-island-integration.md +258 -0
  116. package/src/resources/skills/mandu-ui/rules/ui-radix-patterns.md +213 -0
  117. package/src/resources/skills/mandu-ui/rules/ui-shadcn-setup.md +209 -0
  118. package/src/resources/skills/recipes.ts +932 -0
  119. package/src/server.ts +3 -0
  120. package/src/tools/hydration.ts +8 -8
  121. package/src/tools/index.ts +1 -0
  122. package/src/tools/seo.ts +417 -0
@@ -0,0 +1,56 @@
1
+ ---
2
+ title: Use Context Response Methods
3
+ impact: HIGH
4
+ impactDescription: Consistent API responses
5
+ tags: slot, context, response
6
+ ---
7
+
8
+ ## Use Context Response Methods
9
+
10
+ Use `ctx.ok()`, `ctx.created()`, `ctx.error()` instead of manual Response objects.
11
+ These methods ensure consistent response format across your API.
12
+
13
+ **Incorrect (manual Response):**
14
+
15
+ ```typescript
16
+ export default Mandu.filling()
17
+ .get((ctx) => {
18
+ return new Response(JSON.stringify({ data: [] }), {
19
+ headers: { "Content-Type": "application/json" }
20
+ });
21
+ })
22
+ .post(async (ctx) => {
23
+ return new Response(JSON.stringify({ error: "Bad request" }), {
24
+ status: 400
25
+ });
26
+ });
27
+ ```
28
+
29
+ **Correct (context methods):**
30
+
31
+ ```typescript
32
+ export default Mandu.filling()
33
+ .get((ctx) => {
34
+ return ctx.ok({ data: [] });
35
+ })
36
+ .post(async (ctx) => {
37
+ const body = await ctx.body();
38
+ if (!body.name) {
39
+ return ctx.error("name is required");
40
+ }
41
+ return ctx.created({ data: body });
42
+ });
43
+ ```
44
+
45
+ ## Response Methods
46
+
47
+ | Method | Status | Use Case |
48
+ |--------|--------|----------|
49
+ | `ctx.ok(data)` | 200 | Success |
50
+ | `ctx.created(data)` | 201 | Resource created |
51
+ | `ctx.noContent()` | 204 | Success, no body |
52
+ | `ctx.error(msg)` | 400 | Bad request |
53
+ | `ctx.unauthorized(msg)` | 401 | Auth required |
54
+ | `ctx.forbidden(msg)` | 403 | Permission denied |
55
+ | `ctx.notFound(msg)` | 404 | Not found |
56
+ | `ctx.fail(msg)` | 500 | Server error |
@@ -0,0 +1,59 @@
1
+ ---
2
+ title: Use .guard() for Authentication
3
+ impact: MEDIUM
4
+ impactDescription: Clean auth separation
5
+ tags: slot, guard, authentication
6
+ ---
7
+
8
+ ## Use .guard() for Authentication
9
+
10
+ Use `.guard()` to check authentication before handlers run. Return a response
11
+ to block the request, or return void/undefined to continue.
12
+
13
+ **Incorrect (auth check in every handler):**
14
+
15
+ ```typescript
16
+ export default Mandu.filling()
17
+ .get((ctx) => {
18
+ const user = ctx.get("user");
19
+ if (!user) {
20
+ return ctx.unauthorized("Login required");
21
+ }
22
+ return ctx.ok({ data: [] });
23
+ })
24
+ .post(async (ctx) => {
25
+ const user = ctx.get("user");
26
+ if (!user) {
27
+ return ctx.unauthorized("Login required");
28
+ }
29
+ // ... create logic
30
+ });
31
+ ```
32
+
33
+ **Correct (single guard):**
34
+
35
+ ```typescript
36
+ export default Mandu.filling()
37
+ .guard((ctx) => {
38
+ const user = ctx.get("user");
39
+ if (!user) {
40
+ return ctx.unauthorized("Login required");
41
+ }
42
+ // void return = continue to handlers
43
+ })
44
+ .get((ctx) => {
45
+ const user = ctx.get("user");
46
+ return ctx.ok({ data: [], user });
47
+ })
48
+ .post(async (ctx) => {
49
+ const body = await ctx.body();
50
+ return ctx.created({ data: body });
51
+ });
52
+ ```
53
+
54
+ ## Guard Rules
55
+
56
+ 1. Return response → Request blocked
57
+ 2. Return void → Continue to handler
58
+ 3. Guard runs before ALL HTTP method handlers
59
+ 4. Use `.onRequest()` to set user before guard runs
@@ -0,0 +1,64 @@
1
+ ---
2
+ title: Use Appropriate HTTP Methods
3
+ impact: HIGH
4
+ impactDescription: RESTful API design
5
+ tags: slot, http, methods, rest
6
+ ---
7
+
8
+ ## Use Appropriate HTTP Methods
9
+
10
+ Chain HTTP methods on Mandu.filling() for RESTful API design.
11
+
12
+ **Incorrect (single handler for all):**
13
+
14
+ ```typescript
15
+ export default Mandu.filling()
16
+ .get(async (ctx) => {
17
+ const method = ctx.req.method;
18
+ if (method === "GET") {
19
+ return ctx.ok({ data: [] });
20
+ } else if (method === "POST") {
21
+ const body = await ctx.body();
22
+ return ctx.created({ data: body });
23
+ }
24
+ });
25
+ ```
26
+
27
+ **Correct (separate methods):**
28
+
29
+ ```typescript
30
+ export default Mandu.filling()
31
+ .get((ctx) => {
32
+ // GET /api/users - List users
33
+ return ctx.ok({ data: [] });
34
+ })
35
+ .post(async (ctx) => {
36
+ // POST /api/users - Create user
37
+ const body = await ctx.body<{ name: string }>();
38
+ return ctx.created({ data: { id: 1, ...body } });
39
+ })
40
+ .put(async (ctx) => {
41
+ // PUT /api/users/:id - Replace user
42
+ const body = await ctx.body();
43
+ return ctx.ok({ data: body });
44
+ })
45
+ .patch(async (ctx) => {
46
+ // PATCH /api/users/:id - Update user
47
+ const body = await ctx.body();
48
+ return ctx.ok({ data: body });
49
+ })
50
+ .delete((ctx) => {
51
+ // DELETE /api/users/:id - Delete user
52
+ return ctx.noContent();
53
+ });
54
+ ```
55
+
56
+ ## HTTP Method Semantics
57
+
58
+ | Method | Idempotent | Use Case |
59
+ |--------|------------|----------|
60
+ | GET | Yes | Read resource |
61
+ | POST | No | Create resource |
62
+ | PUT | Yes | Replace resource |
63
+ | PATCH | No | Partial update |
64
+ | DELETE | Yes | Remove resource |
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: Mandu Styling
3
+ description: CSS framework integration and Island styling patterns
4
+ metadata:
5
+ version: "1.0.0"
6
+ author: mandu
7
+ globs:
8
+ - "tailwind.config.{js,ts}"
9
+ - "panda.config.{js,ts}"
10
+ - "postcss.config.{js,ts}"
11
+ - "**/*.css"
12
+ - "**/*.module.css"
13
+ ---
14
+
15
+ # Mandu Styling Skill
16
+
17
+ Mandu Island 아키텍처에 최적화된 CSS 스타일링 가이드입니다.
18
+
19
+ ## 핵심 원칙
20
+
21
+ 1. **Zero-Runtime**: 빌드 타임 CSS 생성 (SSR 호환)
22
+ 2. **Island 격리**: 컴포넌트 간 스타일 충돌 방지
23
+ 3. **Composition**: Tailwind utility + 컴포넌트 패턴
24
+ 4. **Performance**: Critical CSS, Tree-shaking
25
+
26
+ ## 권장 스택
27
+
28
+ ```
29
+ Primary: Tailwind CSS + clsx/tailwind-merge
30
+ Alternative: Panda CSS (type-safe 선호 시)
31
+ Fallback: CSS Modules (최소 의존성)
32
+ ```
33
+
34
+ ## 빠른 시작
35
+
36
+ ### Tailwind CSS 설정
37
+
38
+ ```bash
39
+ bun add -d tailwindcss postcss autoprefixer
40
+ bunx tailwindcss init -p
41
+ ```
42
+
43
+ ```typescript
44
+ // tailwind.config.ts
45
+ import type { Config } from "tailwindcss";
46
+
47
+ export default {
48
+ content: ["./app/**/*.{ts,tsx}"],
49
+ theme: {
50
+ extend: {
51
+ colors: {
52
+ mandu: {
53
+ primary: "#3b82f6",
54
+ secondary: "#64748b",
55
+ },
56
+ },
57
+ },
58
+ },
59
+ plugins: [],
60
+ } satisfies Config;
61
+ ```
62
+
63
+ ```css
64
+ /* app/globals.css */
65
+ @tailwind base;
66
+ @tailwind components;
67
+ @tailwind utilities;
68
+ ```
69
+
70
+ ### Island 스타일링
71
+
72
+ ```tsx
73
+ // app/counter/client.tsx
74
+ "use client";
75
+
76
+ import { cn } from "@/lib/utils";
77
+
78
+ interface CounterProps {
79
+ variant?: "default" | "outline";
80
+ }
81
+
82
+ export function CounterIsland({ variant = "default" }: CounterProps) {
83
+ const variants = {
84
+ default: "bg-mandu-primary text-white",
85
+ outline: "border-2 border-mandu-primary text-mandu-primary",
86
+ };
87
+
88
+ return (
89
+ <button className={cn("px-4 py-2 rounded-lg", variants[variant])}>
90
+ Count: 0
91
+ </button>
92
+ );
93
+ }
94
+ ```
95
+
96
+ ## cn 유틸리티
97
+
98
+ ```typescript
99
+ // lib/utils.ts
100
+ import { clsx, type ClassValue } from "clsx";
101
+ import { twMerge } from "tailwind-merge";
102
+
103
+ export function cn(...inputs: ClassValue[]) {
104
+ return twMerge(clsx(inputs));
105
+ }
106
+ ```
107
+
108
+ ## 규칙 카테고리
109
+
110
+ | Category | Description | Rules |
111
+ |----------|-------------|-------|
112
+ | Setup | 프레임워크 설정 | 3 |
113
+ | Island | Island 스타일 패턴 | 3 |
114
+ | Component | 컴포넌트 스타일 | 3 |
115
+ | Performance | 최적화 | 2 |
116
+ | Theme | 테마/다크모드 | 1 |
117
+
118
+ → 세부 규칙은 `rules/` 폴더 참조
@@ -0,0 +1,36 @@
1
+ # Mandu Styling - Rule Categories
2
+
3
+ ## Setup
4
+ CSS 프레임워크 초기 설정 및 Bun 통합
5
+
6
+ | Impact | Description |
7
+ |--------|-------------|
8
+ | CRITICAL | 프레임워크 설정 없이 스타일링 불가 |
9
+
10
+ ## Island
11
+ Island 컴포넌트 특화 스타일링 패턴
12
+
13
+ | Impact | Description |
14
+ |--------|-------------|
15
+ | HIGH | 스타일 충돌 방지, 독립적 hydration 지원 |
16
+
17
+ ## Component
18
+ 컴포넌트 레벨 스타일링 패턴
19
+
20
+ | Impact | Description |
21
+ |--------|-------------|
22
+ | HIGH | 재사용성, 일관성, 유지보수성 향상 |
23
+
24
+ ## Performance
25
+ CSS 빌드 및 로딩 최적화
26
+
27
+ | Impact | Description |
28
+ |--------|-------------|
29
+ | MEDIUM | 번들 크기, 초기 로딩 성능 개선 |
30
+
31
+ ## Theme
32
+ 다크모드 및 테마 시스템
33
+
34
+ | Impact | Description |
35
+ |--------|-------------|
36
+ | MEDIUM | 사용자 경험, 접근성 향상 |
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Rule Title Here
3
+ impact: CRITICAL | HIGH | MEDIUM | LOW
4
+ impactDescription: One-line description of why this matters
5
+ tags: styling, tag2, tag3
6
+ ---
7
+
8
+ ## Rule Title Here
9
+
10
+ **Impact: LEVEL (Impact description)**
11
+
12
+ 규칙에 대한 간단한 설명.
13
+
14
+ **설정:**
15
+
16
+ ```typescript
17
+ // 설정 예시
18
+ ```
19
+
20
+ **사용 예시:**
21
+
22
+ ```tsx
23
+ // 컴포넌트 예시
24
+ ```
25
+
26
+ ## 추가 패턴
27
+
28
+ ```tsx
29
+ // 추가 패턴
30
+ ```
31
+
32
+ Reference: [문서 링크](https://example.com)
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": "mandu-styling",
3
+ "name": "Mandu Styling",
4
+ "version": "1.0.0",
5
+ "description": "CSS framework integration and Island styling patterns",
6
+ "author": "mandu",
7
+ "references": [
8
+ "https://tailwindcss.com/docs",
9
+ "https://panda-css.com/docs",
10
+ "https://lightningcss.dev/"
11
+ ],
12
+ "abstract": "Mandu Island 아키텍처에 최적화된 CSS 스타일링 패턴. Tailwind CSS를 primary로, Panda CSS와 CSS Modules를 대안으로 제공합니다."
13
+ }
@@ -0,0 +1,235 @@
1
+ ---
2
+ title: Compound Component Styling
3
+ impact: HIGH
4
+ impactDescription: Consistent styling for compound component patterns
5
+ tags: styling, compound, composition, patterns
6
+ ---
7
+
8
+ ## Compound Component Styling
9
+
10
+ **Impact: HIGH (Consistent styling for compound component patterns)**
11
+
12
+ Mandu의 compound component 패턴에 맞는 스타일링 방법입니다.
13
+
14
+ ## 기본 패턴
15
+
16
+ ```tsx
17
+ // app/card/client.tsx
18
+ "use client";
19
+
20
+ import { createContext, useContext } from "react";
21
+ import { cn } from "@/lib/utils";
22
+ import { cva, type VariantProps } from "class-variance-authority";
23
+
24
+ // 1. Variants 정의
25
+ const cardVariants = cva("rounded-lg border", {
26
+ variants: {
27
+ variant: {
28
+ default: "bg-card text-card-foreground",
29
+ elevated: "bg-card shadow-lg",
30
+ ghost: "border-transparent",
31
+ },
32
+ },
33
+ defaultVariants: {
34
+ variant: "default",
35
+ },
36
+ });
37
+
38
+ // 2. Context로 variant 공유
39
+ type CardContextValue = VariantProps<typeof cardVariants>;
40
+ const CardContext = createContext<CardContextValue>({});
41
+
42
+ // 3. Compound 컴포넌트
43
+ export const Card = {
44
+ Root: ({
45
+ variant,
46
+ className,
47
+ children,
48
+ ...props
49
+ }: React.HTMLAttributes<HTMLDivElement> & CardContextValue) => (
50
+ <CardContext.Provider value={{ variant }}>
51
+ <div className={cn(cardVariants({ variant }), className)} {...props}>
52
+ {children}
53
+ </div>
54
+ </CardContext.Provider>
55
+ ),
56
+
57
+ Header: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
58
+ <div className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
59
+ ),
60
+
61
+ Title: ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
62
+ <h3 className={cn("text-2xl font-semibold leading-none tracking-tight", className)} {...props} />
63
+ ),
64
+
65
+ Description: ({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) => (
66
+ <p className={cn("text-sm text-muted-foreground", className)} {...props} />
67
+ ),
68
+
69
+ Content: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
70
+ <div className={cn("p-6 pt-0", className)} {...props} />
71
+ ),
72
+
73
+ Footer: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
74
+ <div className={cn("flex items-center p-6 pt-0", className)} {...props} />
75
+ ),
76
+ };
77
+ ```
78
+
79
+ ## 사용 예시
80
+
81
+ ```tsx
82
+ <Card.Root variant="elevated">
83
+ <Card.Header>
84
+ <Card.Title>Card Title</Card.Title>
85
+ <Card.Description>Card description</Card.Description>
86
+ </Card.Header>
87
+ <Card.Content>
88
+ Content here
89
+ </Card.Content>
90
+ <Card.Footer>
91
+ <button>Action</button>
92
+ </Card.Footer>
93
+ </Card.Root>
94
+ ```
95
+
96
+ ## Context 기반 스타일 상속
97
+
98
+ ```tsx
99
+ // app/alert/client.tsx
100
+ "use client";
101
+
102
+ import { createContext, useContext } from "react";
103
+
104
+ type AlertVariant = "default" | "info" | "success" | "warning" | "error";
105
+
106
+ const AlertContext = createContext<{ variant: AlertVariant }>({
107
+ variant: "default",
108
+ });
109
+
110
+ const alertStyles = {
111
+ default: {
112
+ root: "bg-background text-foreground",
113
+ icon: "text-foreground",
114
+ },
115
+ info: {
116
+ root: "bg-blue-50 text-blue-900 border-blue-200",
117
+ icon: "text-blue-600",
118
+ },
119
+ success: {
120
+ root: "bg-green-50 text-green-900 border-green-200",
121
+ icon: "text-green-600",
122
+ },
123
+ warning: {
124
+ root: "bg-yellow-50 text-yellow-900 border-yellow-200",
125
+ icon: "text-yellow-600",
126
+ },
127
+ error: {
128
+ root: "bg-red-50 text-red-900 border-red-200",
129
+ icon: "text-red-600",
130
+ },
131
+ };
132
+
133
+ export const Alert = {
134
+ Root: ({ variant = "default", className, ...props }) => (
135
+ <AlertContext.Provider value={{ variant }}>
136
+ <div
137
+ role="alert"
138
+ className={cn(
139
+ "relative w-full rounded-lg border p-4",
140
+ alertStyles[variant].root,
141
+ className
142
+ )}
143
+ {...props}
144
+ />
145
+ </AlertContext.Provider>
146
+ ),
147
+
148
+ Icon: ({ className, children, ...props }) => {
149
+ const { variant } = useContext(AlertContext);
150
+ return (
151
+ <span
152
+ className={cn("h-5 w-5", alertStyles[variant].icon, className)}
153
+ {...props}
154
+ >
155
+ {children}
156
+ </span>
157
+ );
158
+ },
159
+
160
+ Title: ({ className, ...props }) => (
161
+ <h5
162
+ className={cn("mb-1 font-medium leading-none tracking-tight", className)}
163
+ {...props}
164
+ />
165
+ ),
166
+
167
+ Description: ({ className, ...props }) => (
168
+ <div className={cn("text-sm [&_p]:leading-relaxed", className)} {...props} />
169
+ ),
170
+ };
171
+ ```
172
+
173
+ ## Slot 기반 커스터마이징
174
+
175
+ ```tsx
176
+ // asChild 패턴으로 스타일 전달
177
+ import { Slot } from "@radix-ui/react-slot";
178
+
179
+ export const Button = ({
180
+ asChild,
181
+ className,
182
+ variant,
183
+ size,
184
+ ...props
185
+ }) => {
186
+ const Comp = asChild ? Slot : "button";
187
+
188
+ return (
189
+ <Comp
190
+ className={cn(buttonVariants({ variant, size }), className)}
191
+ {...props}
192
+ />
193
+ );
194
+ };
195
+
196
+ // 사용: Link에 Button 스타일 적용
197
+ <Button asChild variant="outline">
198
+ <a href="/about">About</a>
199
+ </Button>
200
+ ```
201
+
202
+ ## CSS Modules와 조합
203
+
204
+ ```css
205
+ /* card.module.css */
206
+ .root {
207
+ @apply rounded-lg border;
208
+ }
209
+
210
+ .root[data-variant="elevated"] {
211
+ @apply shadow-lg;
212
+ }
213
+
214
+ .header {
215
+ @apply p-6;
216
+ }
217
+
218
+ .content {
219
+ @apply p-6 pt-0;
220
+ }
221
+ ```
222
+
223
+ ```tsx
224
+ import styles from "./card.module.css";
225
+
226
+ export const Card = {
227
+ Root: ({ variant, ...props }) => (
228
+ <div className={styles.root} data-variant={variant} {...props} />
229
+ ),
230
+ Header: (props) => <div className={styles.header} {...props} />,
231
+ Content: (props) => <div className={styles.content} {...props} />,
232
+ };
233
+ ```
234
+
235
+ Reference: [Radix UI Primitives](https://www.radix-ui.com/primitives)