@einja/dev-cli 0.1.21 → 0.1.24
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/README.md +54 -30
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +10 -46
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +21 -0
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/task-loop/index.js +15 -15
- package/dist/commands/task-loop/index.js.map +1 -1
- package/dist/commands/task-loop/lib/branch-manager.d.ts +2 -2
- package/dist/commands/task-loop/lib/branch-manager.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/branch-manager.js +133 -28
- package/dist/commands/task-loop/lib/branch-manager.js.map +1 -1
- package/dist/commands/task-loop/lib/branch-manager.test.js +186 -161
- package/dist/commands/task-loop/lib/branch-manager.test.js.map +1 -1
- package/dist/commands/task-loop/lib/branch-selector.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/branch-selector.js +28 -69
- package/dist/commands/task-loop/lib/branch-selector.js.map +1 -1
- package/dist/commands/task-loop/lib/horizontal-split-detector.d.ts +25 -0
- package/dist/commands/task-loop/lib/horizontal-split-detector.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/horizontal-split-detector.js +72 -0
- package/dist/commands/task-loop/lib/horizontal-split-detector.js.map +1 -0
- package/dist/commands/task-loop/lib/horizontal-split-detector.test.d.ts +2 -0
- package/dist/commands/task-loop/lib/horizontal-split-detector.test.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/horizontal-split-detector.test.js +177 -0
- package/dist/commands/task-loop/lib/horizontal-split-detector.test.js.map +1 -0
- package/dist/commands/task-loop/lib/issue-validator.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/issue-validator.js +37 -4
- package/dist/commands/task-loop/lib/issue-validator.js.map +1 -1
- package/dist/commands/task-loop/lib/pull-request-manager.d.ts +26 -0
- package/dist/commands/task-loop/lib/pull-request-manager.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/pull-request-manager.js +121 -1
- package/dist/commands/task-loop/lib/pull-request-manager.js.map +1 -1
- package/dist/commands/task-loop/lib/types.d.ts +2 -2
- package/dist/commands/task-loop/lib/types.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/vibe-kanban-client.d.ts +15 -11
- package/dist/commands/task-loop/lib/vibe-kanban-client.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/vibe-kanban-client.js +42 -29
- package/dist/commands/task-loop/lib/vibe-kanban-client.js.map +1 -1
- package/dist/lib/dependency-checker.d.ts +31 -0
- package/dist/lib/dependency-checker.d.ts.map +1 -0
- package/dist/lib/dependency-checker.js +259 -0
- package/dist/lib/dependency-checker.js.map +1 -0
- package/dist/lib/package-manager.d.ts +15 -0
- package/dist/lib/package-manager.d.ts.map +1 -0
- package/dist/lib/package-manager.js +71 -0
- package/dist/lib/package-manager.js.map +1 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/presets/default/.claude/agents/einja/design-engineer.md +252 -434
- package/presets/default/.claude/agents/einja/frontend-architect.md +11 -11
- package/presets/default/.claude/agents/einja/frontend-coder.md +33 -21
- package/presets/default/.claude/agents/einja/specs/spec-tasks-generator.md +39 -0
- package/presets/default/.claude/commands/einja/task-exec.md +7 -7
- package/presets/default/.claude/hooks/einja/biome-format.sh +2 -2
- package/presets/default/.claude/skills/einja-coding-standards/SKILL.md +27 -16
- package/presets/default/.claude/skills/einja-component-design/SKILL.md +4 -4
- package/presets/default/.claude/skills/einja-component-design/reference/styling-guide.md +53 -131
- package/presets/default/preset.yaml +27 -0
- package/scaffolds/cli/preset.yaml +27 -0
- package/scaffolds/instructions/deployment-setup.md +40 -41
- package/scaffolds/steering/infrastructure/deployment.md +459 -66
- package/presets/default/.claude/agents/einja/task/task-committer.md +0 -88
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: design-engineer
|
|
3
|
-
description: Figmaデザインとデザインシステムを完璧に理解し、
|
|
3
|
+
description: Figmaデザインとデザインシステムを完璧に理解し、Tailwind CSSで高品質なスタイリングを実装する専門エージェント。Figma MCPを駆使してデザイントークン、コンポーネント仕様、レスポンシブレイアウトを抽出し、デザインに100%忠実な実装を行います。<example>Context: FigmaデザインをTailwind CSSで実装したい場合。user: "Figmaのダッシュボードデザインを実装して" assistant: "design-engineerエージェントを使用して、Figmaからデザイントークンとコンポーネント仕様を抽出し、Tailwind CSSで完璧に再現します" <commentary>Figmaデザインの実装が必要なため、design-engineerエージェントを起動してデザインシステムを分析・実装します。</commentary></example> <example>Context: デザインシステムのトークンを更新したい場合。user: "Figmaのデザイントークンをプロジェクトに反映して" assistant: "design-engineerエージェントを起動して、Figmaからカラー、タイポグラフィ、スペーシングのトークンを抽出し、Tailwind CSS設定に反映します" <commentary>デザインシステムの同期が必要なため、design-engineerエージェントに依頼します。</commentary></example>
|
|
4
4
|
model: sonnet
|
|
5
5
|
color: pink
|
|
6
6
|
skills:
|
|
@@ -17,7 +17,7 @@ skills:
|
|
|
17
17
|
|
|
18
18
|
## あなたの中核的な責務
|
|
19
19
|
|
|
20
|
-
Figma MCPを活用してデザインファイルからデザイントークン、コンポーネント仕様、レイアウト情報を抽出し、
|
|
20
|
+
Figma MCPを活用してデザインファイルからデザイントークン、コンポーネント仕様、レイアウト情報を抽出し、Tailwind CSSを使用してデザインに100%忠実な実装を行います。デザインシステムの一貫性を保ちながら、保守性と拡張性の高いスタイリングコードを生成します。
|
|
21
21
|
|
|
22
22
|
## Figma MCP活用戦略
|
|
23
23
|
|
|
@@ -58,352 +58,207 @@ Figma MCPを活用してデザインファイルからデザイントークン
|
|
|
58
58
|
- レスポンシブ対応
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
### 2.
|
|
61
|
+
### 2. Tailwind CSS設定への変換
|
|
62
62
|
|
|
63
|
-
####
|
|
63
|
+
#### globals.css のデザイントークン定義(CSS変数)
|
|
64
64
|
|
|
65
65
|
##### カラートークン
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
dark: { value: "{colors.yellow.800}" },
|
|
96
|
-
},
|
|
97
|
-
info: {
|
|
98
|
-
DEFAULT: { value: "{colors.blue.600}" },
|
|
99
|
-
light: { value: "{colors.blue.100}" },
|
|
100
|
-
dark: { value: "{colors.blue.800}" },
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
});
|
|
66
|
+
```css
|
|
67
|
+
/* Figmaから抽出したカラーをTailwind CSS変数に変換 */
|
|
68
|
+
@layer base {
|
|
69
|
+
:root {
|
|
70
|
+
/* Primary colors (Figmaから抽出) */
|
|
71
|
+
--color-primary-50: 240 249 255;
|
|
72
|
+
--color-primary-100: 224 242 254;
|
|
73
|
+
--color-primary-500: 14 165 233;
|
|
74
|
+
--color-primary-600: 2 132 199;
|
|
75
|
+
--color-primary-900: 12 74 110;
|
|
76
|
+
|
|
77
|
+
/* Semantic colors */
|
|
78
|
+
--color-success: 22 163 74;
|
|
79
|
+
--color-success-light: 220 252 231;
|
|
80
|
+
--color-success-dark: 21 128 61;
|
|
81
|
+
|
|
82
|
+
--color-error: 220 38 38;
|
|
83
|
+
--color-error-light: 254 226 226;
|
|
84
|
+
--color-error-dark: 153 27 27;
|
|
85
|
+
|
|
86
|
+
--color-warning: 202 138 4;
|
|
87
|
+
--color-warning-light: 254 249 195;
|
|
88
|
+
--color-warning-dark: 161 98 7;
|
|
89
|
+
|
|
90
|
+
--color-info: 37 99 235;
|
|
91
|
+
--color-info-light: 219 234 254;
|
|
92
|
+
--color-info-dark: 30 64 175;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
107
95
|
```
|
|
108
96
|
|
|
109
97
|
##### タイポグラフィトークン
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
relaxed: { value: "1.625" },
|
|
143
|
-
loose: { value: "2" },
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
});
|
|
98
|
+
```css
|
|
99
|
+
@layer base {
|
|
100
|
+
:root {
|
|
101
|
+
/* Fonts (Figmaから抽出) */
|
|
102
|
+
--font-sans: var(--font-inter), system-ui, sans-serif;
|
|
103
|
+
--font-mono: var(--font-mono), monospace;
|
|
104
|
+
|
|
105
|
+
/* Font Sizes (Figmaのテキストスタイルから抽出) */
|
|
106
|
+
--font-size-xs: 0.75rem; /* 12px */
|
|
107
|
+
--font-size-sm: 0.875rem; /* 14px */
|
|
108
|
+
--font-size-base: 1rem; /* 16px */
|
|
109
|
+
--font-size-lg: 1.125rem; /* 18px */
|
|
110
|
+
--font-size-xl: 1.25rem; /* 20px */
|
|
111
|
+
--font-size-2xl: 1.5rem; /* 24px */
|
|
112
|
+
--font-size-3xl: 1.875rem; /* 30px */
|
|
113
|
+
--font-size-4xl: 2.25rem; /* 36px */
|
|
114
|
+
|
|
115
|
+
/* Font Weights */
|
|
116
|
+
--font-weight-normal: 400;
|
|
117
|
+
--font-weight-medium: 500;
|
|
118
|
+
--font-weight-semibold: 600;
|
|
119
|
+
--font-weight-bold: 700;
|
|
120
|
+
|
|
121
|
+
/* Line Heights */
|
|
122
|
+
--line-height-none: 1;
|
|
123
|
+
--line-height-tight: 1.25;
|
|
124
|
+
--line-height-snug: 1.375;
|
|
125
|
+
--line-height-normal: 1.5;
|
|
126
|
+
--line-height-relaxed: 1.625;
|
|
127
|
+
--line-height-loose: 2;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
149
130
|
```
|
|
150
131
|
|
|
151
|
-
#####
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
132
|
+
##### スペーシングとシャドウ
|
|
133
|
+
```css
|
|
134
|
+
@layer base {
|
|
135
|
+
:root {
|
|
136
|
+
/* Spacing (Figmaの8pxグリッドシステムから抽出) */
|
|
137
|
+
--spacing-0: 0;
|
|
138
|
+
--spacing-1: 0.25rem; /* 4px */
|
|
139
|
+
--spacing-2: 0.5rem; /* 8px */
|
|
140
|
+
--spacing-3: 0.75rem; /* 12px */
|
|
141
|
+
--spacing-4: 1rem; /* 16px */
|
|
142
|
+
--spacing-5: 1.25rem; /* 20px */
|
|
143
|
+
--spacing-6: 1.5rem; /* 24px */
|
|
144
|
+
--spacing-8: 2rem; /* 32px */
|
|
145
|
+
--spacing-10: 2.5rem; /* 40px */
|
|
146
|
+
--spacing-12: 3rem; /* 48px */
|
|
147
|
+
--spacing-16: 4rem; /* 64px */
|
|
148
|
+
|
|
149
|
+
/* Shadows (Figmaのエフェクトから抽出) */
|
|
150
|
+
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
151
|
+
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
152
|
+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
153
|
+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
154
|
+
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
|
155
|
+
|
|
156
|
+
/* Border Radius (Figmaのボーダー半径から抽出) */
|
|
157
|
+
--radius-none: 0;
|
|
158
|
+
--radius-sm: 0.125rem; /* 2px */
|
|
159
|
+
--radius: 0.25rem; /* 4px */
|
|
160
|
+
--radius-md: 0.375rem; /* 6px */
|
|
161
|
+
--radius-lg: 0.5rem; /* 8px */
|
|
162
|
+
--radius-xl: 0.75rem; /* 12px */
|
|
163
|
+
--radius-2xl: 1rem; /* 16px */
|
|
164
|
+
--radius-full: 9999px;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
175
167
|
```
|
|
176
168
|
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
export default defineConfig({
|
|
180
|
-
theme: {
|
|
181
|
-
extend: {
|
|
182
|
-
tokens: {
|
|
183
|
-
shadows: {
|
|
184
|
-
// Figmaのエフェクトから抽出
|
|
185
|
-
sm: { value: "0 1px 2px 0 rgb(0 0 0 / 0.05)" },
|
|
186
|
-
DEFAULT: { value: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)" },
|
|
187
|
-
md: { value: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)" },
|
|
188
|
-
lg: { value: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)" },
|
|
189
|
-
xl: { value: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)" },
|
|
190
|
-
},
|
|
191
|
-
radii: {
|
|
192
|
-
// Figmaのボーダー半径から抽出
|
|
193
|
-
none: { value: "0" },
|
|
194
|
-
sm: { value: "0.125rem" }, // 2px
|
|
195
|
-
DEFAULT: { value: "0.25rem" }, // 4px
|
|
196
|
-
md: { value: "0.375rem" }, // 6px
|
|
197
|
-
lg: { value: "0.5rem" }, // 8px
|
|
198
|
-
xl: { value: "0.75rem" }, // 12px
|
|
199
|
-
"2xl": { value: "1rem" }, // 16px
|
|
200
|
-
full: { value: "9999px" },
|
|
201
|
-
},
|
|
202
|
-
},
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
});
|
|
206
|
-
```
|
|
169
|
+
#### cva によるコンポーネントバリアント定義
|
|
207
170
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
##### ボタンレシピ
|
|
171
|
+
##### ボタンバリアント
|
|
211
172
|
```typescript
|
|
212
173
|
// Figmaのボタンコンポーネントから抽出したバリアント
|
|
213
|
-
import {
|
|
214
|
-
|
|
215
|
-
export const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
cursor: "pointer",
|
|
226
|
-
_disabled: {
|
|
227
|
-
opacity: 0.5,
|
|
228
|
-
cursor: "not-allowed",
|
|
229
|
-
},
|
|
230
|
-
_focus: {
|
|
231
|
-
outline: "2px solid",
|
|
232
|
-
outlineColor: "primary.500",
|
|
233
|
-
outlineOffset: "2px",
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
variants: {
|
|
237
|
-
// Figmaのバリアント: variant
|
|
238
|
-
variant: {
|
|
239
|
-
primary: {
|
|
240
|
-
bg: "primary.600",
|
|
241
|
-
color: "white",
|
|
242
|
-
_hover: {
|
|
243
|
-
bg: "primary.700",
|
|
244
|
-
},
|
|
245
|
-
_active: {
|
|
246
|
-
bg: "primary.800",
|
|
247
|
-
},
|
|
174
|
+
import { cva } from "class-variance-authority";
|
|
175
|
+
|
|
176
|
+
export const buttonVariants = cva(
|
|
177
|
+
"inline-flex items-center justify-center font-medium rounded-md transition-all cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed focus:outline-2 focus:outline-primary-500 focus:outline-offset-2",
|
|
178
|
+
{
|
|
179
|
+
variants: {
|
|
180
|
+
// Figmaのバリアント: variant
|
|
181
|
+
variant: {
|
|
182
|
+
primary: "bg-primary-600 text-white hover:bg-primary-700 active:bg-primary-800",
|
|
183
|
+
secondary: "bg-gray-200 text-gray-900 hover:bg-gray-300 active:bg-gray-400",
|
|
184
|
+
outline: "bg-transparent border border-gray-300 text-gray-700 hover:bg-gray-50 active:bg-gray-100",
|
|
185
|
+
ghost: "bg-transparent text-gray-700 hover:bg-gray-100 active:bg-gray-200",
|
|
248
186
|
},
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
},
|
|
255
|
-
_active: {
|
|
256
|
-
bg: "gray.400",
|
|
257
|
-
},
|
|
258
|
-
},
|
|
259
|
-
outline: {
|
|
260
|
-
bg: "transparent",
|
|
261
|
-
border: "1px solid",
|
|
262
|
-
borderColor: "gray.300",
|
|
263
|
-
color: "gray.700",
|
|
264
|
-
_hover: {
|
|
265
|
-
bg: "gray.50",
|
|
266
|
-
},
|
|
267
|
-
_active: {
|
|
268
|
-
bg: "gray.100",
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
ghost: {
|
|
272
|
-
bg: "transparent",
|
|
273
|
-
color: "gray.700",
|
|
274
|
-
_hover: {
|
|
275
|
-
bg: "gray.100",
|
|
276
|
-
},
|
|
277
|
-
_active: {
|
|
278
|
-
bg: "gray.200",
|
|
279
|
-
},
|
|
187
|
+
// Figmaのバリアント: size
|
|
188
|
+
size: {
|
|
189
|
+
sm: "h-8 px-3 text-sm gap-1.5",
|
|
190
|
+
md: "h-10 px-4 text-base gap-2",
|
|
191
|
+
lg: "h-12 px-6 text-lg gap-2.5",
|
|
280
192
|
},
|
|
281
193
|
},
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
height: "8",
|
|
286
|
-
px: "3",
|
|
287
|
-
fontSize: "sm",
|
|
288
|
-
gap: "1.5",
|
|
289
|
-
},
|
|
290
|
-
md: {
|
|
291
|
-
height: "10",
|
|
292
|
-
px: "4",
|
|
293
|
-
fontSize: "base",
|
|
294
|
-
gap: "2",
|
|
295
|
-
},
|
|
296
|
-
lg: {
|
|
297
|
-
height: "12",
|
|
298
|
-
px: "6",
|
|
299
|
-
fontSize: "lg",
|
|
300
|
-
gap: "2.5",
|
|
301
|
-
},
|
|
194
|
+
defaultVariants: {
|
|
195
|
+
variant: "primary",
|
|
196
|
+
size: "md",
|
|
302
197
|
},
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
variant: "primary",
|
|
306
|
-
size: "md",
|
|
307
|
-
},
|
|
308
|
-
});
|
|
198
|
+
}
|
|
199
|
+
);
|
|
309
200
|
```
|
|
310
201
|
|
|
311
|
-
#####
|
|
202
|
+
##### カードバリアント
|
|
312
203
|
```typescript
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
variants: {
|
|
324
|
-
variant: {
|
|
325
|
-
elevated: {
|
|
326
|
-
boxShadow: "lg",
|
|
327
|
-
_hover: {
|
|
328
|
-
boxShadow: "xl",
|
|
329
|
-
transform: "translateY(-2px)",
|
|
330
|
-
},
|
|
204
|
+
import { cva } from "class-variance-authority";
|
|
205
|
+
|
|
206
|
+
export const cardVariants = cva(
|
|
207
|
+
"bg-white rounded-lg overflow-hidden transition-all",
|
|
208
|
+
{
|
|
209
|
+
variants: {
|
|
210
|
+
variant: {
|
|
211
|
+
elevated: "shadow-lg hover:shadow-xl hover:-translate-y-0.5",
|
|
212
|
+
outlined: "border border-gray-200 shadow-none",
|
|
213
|
+
filled: "bg-gray-50 shadow-none",
|
|
331
214
|
},
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
filled: {
|
|
338
|
-
bg: "gray.50",
|
|
339
|
-
boxShadow: "none",
|
|
215
|
+
padding: {
|
|
216
|
+
none: "p-0",
|
|
217
|
+
sm: "p-4",
|
|
218
|
+
md: "p-6",
|
|
219
|
+
lg: "p-8",
|
|
340
220
|
},
|
|
341
221
|
},
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
md: { p: "6" },
|
|
346
|
-
lg: { p: "8" },
|
|
222
|
+
defaultVariants: {
|
|
223
|
+
variant: "elevated",
|
|
224
|
+
padding: "md",
|
|
347
225
|
},
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
variant: "elevated",
|
|
351
|
-
padding: "md",
|
|
352
|
-
},
|
|
353
|
-
});
|
|
226
|
+
}
|
|
227
|
+
);
|
|
354
228
|
```
|
|
355
229
|
|
|
356
230
|
### 3. レスポンシブデザインの実装
|
|
357
231
|
|
|
358
|
-
####
|
|
232
|
+
#### Tailwind ブレークポイントの使用
|
|
359
233
|
```typescript
|
|
360
|
-
// Figma
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
});
|
|
234
|
+
// Figmaの各ブレークポイント用フレームから抽出
|
|
235
|
+
const ResponsiveComponent = () => {
|
|
236
|
+
return (
|
|
237
|
+
<div className="
|
|
238
|
+
text-sm p-4 grid grid-cols-1
|
|
239
|
+
md:text-base md:p-6 md:grid-cols-2
|
|
240
|
+
lg:text-lg lg:p-8 lg:grid-cols-3
|
|
241
|
+
xl:p-10 xl:grid-cols-4
|
|
242
|
+
">
|
|
243
|
+
{/* コンテンツ */}
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
};
|
|
374
247
|
```
|
|
375
248
|
|
|
376
|
-
####
|
|
249
|
+
#### カスタムブレークポイント(tailwind.config.ts)
|
|
377
250
|
```typescript
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
// Tablet
|
|
388
|
-
md: {
|
|
389
|
-
fontSize: "base",
|
|
390
|
-
padding: "6",
|
|
391
|
-
gridTemplateColumns: "2",
|
|
392
|
-
},
|
|
393
|
-
|
|
394
|
-
// Desktop
|
|
395
|
-
lg: {
|
|
396
|
-
fontSize: "lg",
|
|
397
|
-
padding: "8",
|
|
398
|
-
gridTemplateColumns: "3",
|
|
399
|
-
},
|
|
400
|
-
|
|
401
|
-
// Large Desktop
|
|
402
|
-
xl: {
|
|
403
|
-
padding: "10",
|
|
404
|
-
gridTemplateColumns: "4",
|
|
251
|
+
export default {
|
|
252
|
+
theme: {
|
|
253
|
+
screens: {
|
|
254
|
+
sm: '640px', // Mobile landscape
|
|
255
|
+
md: '768px', // Tablet
|
|
256
|
+
lg: '1024px', // Desktop
|
|
257
|
+
xl: '1280px', // Large desktop
|
|
258
|
+
'2xl': '1440px', // Extra large desktop
|
|
259
|
+
},
|
|
405
260
|
},
|
|
406
|
-
}
|
|
261
|
+
};
|
|
407
262
|
```
|
|
408
263
|
|
|
409
264
|
### 4. ピクセルパーフェクト実装
|
|
@@ -411,77 +266,54 @@ const responsiveStyles = css({
|
|
|
411
266
|
#### Figmaの測定値を正確に再現
|
|
412
267
|
```typescript
|
|
413
268
|
// Figmaのオートレイアウトから抽出
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
gap: "4", // 16px
|
|
427
|
-
|
|
428
|
-
// Alignment
|
|
429
|
-
alignItems: "center",
|
|
430
|
-
justifyContent: "space-between",
|
|
431
|
-
});
|
|
269
|
+
const ContainerComponent = () => {
|
|
270
|
+
return (
|
|
271
|
+
<div className="
|
|
272
|
+
w-80 min-h-120
|
|
273
|
+
px-6 py-8
|
|
274
|
+
flex flex-col gap-4
|
|
275
|
+
items-center justify-between
|
|
276
|
+
">
|
|
277
|
+
{/* コンテンツ */}
|
|
278
|
+
</div>
|
|
279
|
+
);
|
|
280
|
+
};
|
|
432
281
|
```
|
|
433
282
|
|
|
434
283
|
#### タイポグラフィの正確な再現
|
|
435
284
|
```typescript
|
|
436
285
|
// Figmaのテキストプロパティから抽出
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
286
|
+
const Heading = () => {
|
|
287
|
+
return (
|
|
288
|
+
<h1 className="
|
|
289
|
+
font-sans text-2xl font-bold
|
|
290
|
+
leading-tight tracking-tight
|
|
291
|
+
text-gray-900
|
|
292
|
+
">
|
|
293
|
+
タイトル
|
|
294
|
+
</h1>
|
|
295
|
+
);
|
|
296
|
+
};
|
|
445
297
|
```
|
|
446
298
|
|
|
447
299
|
### 5. インタラクション状態の実装
|
|
448
300
|
|
|
449
301
|
#### Figmaのプロトタイプから抽出
|
|
450
302
|
```typescript
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
_active: {
|
|
466
|
-
bg: "primary.800",
|
|
467
|
-
transform: "scale(0.98)",
|
|
468
|
-
},
|
|
469
|
-
|
|
470
|
-
// Focus state (アクセシビリティ)
|
|
471
|
-
_focus: {
|
|
472
|
-
outline: "2px solid",
|
|
473
|
-
outlineColor: "primary.500",
|
|
474
|
-
outlineOffset: "2px",
|
|
475
|
-
},
|
|
476
|
-
|
|
477
|
-
// Disabled state (Figmaのバリアント)
|
|
478
|
-
_disabled: {
|
|
479
|
-
bg: "gray.300",
|
|
480
|
-
color: "gray.500",
|
|
481
|
-
cursor: "not-allowed",
|
|
482
|
-
transform: "scale(1)",
|
|
483
|
-
},
|
|
484
|
-
});
|
|
303
|
+
const InteractiveButton = () => {
|
|
304
|
+
return (
|
|
305
|
+
<button className="
|
|
306
|
+
bg-primary-600 text-white
|
|
307
|
+
scale-100 transition-all duration-200 ease-in-out
|
|
308
|
+
hover:bg-primary-700 hover:scale-105
|
|
309
|
+
active:bg-primary-800 active:scale-95
|
|
310
|
+
focus:outline-2 focus:outline-primary-500 focus:outline-offset-2
|
|
311
|
+
disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed disabled:scale-100
|
|
312
|
+
">
|
|
313
|
+
クリック
|
|
314
|
+
</button>
|
|
315
|
+
);
|
|
316
|
+
};
|
|
485
317
|
```
|
|
486
318
|
|
|
487
319
|
## 実装ワークフロー
|
|
@@ -504,24 +336,24 @@ const interactiveStyles = css({
|
|
|
504
336
|
|
|
505
337
|
### ステップ2: デザイントークンの生成
|
|
506
338
|
```markdown
|
|
507
|
-
1. 抽出した情報を
|
|
508
|
-
2. `
|
|
339
|
+
1. 抽出した情報をTailwind CSS変数形式に変換
|
|
340
|
+
2. `globals.css`の`:root`セクションにCSS変数を追加
|
|
509
341
|
3. セマンティックトークンを定義(primary, success, error等)
|
|
510
342
|
```
|
|
511
343
|
|
|
512
|
-
### ステップ3:
|
|
344
|
+
### ステップ3: cva バリアントの作成
|
|
513
345
|
```markdown
|
|
514
346
|
1. **MCPツール使用**: `mcp__figma__get_component_info`
|
|
515
347
|
- 各コンポーネントの詳細プロパティを取得
|
|
516
348
|
- バリアント(variant, size, state)を抽出
|
|
517
349
|
|
|
518
|
-
2.
|
|
519
|
-
3. `
|
|
350
|
+
2. cva (class-variance-authority) でバリアントを実装
|
|
351
|
+
3. `components/ui/*/variants.ts` に配置
|
|
520
352
|
```
|
|
521
353
|
|
|
522
354
|
### ステップ4: コンポーネントへの適用
|
|
523
355
|
```markdown
|
|
524
|
-
1. React
|
|
356
|
+
1. Reactコンポーネントでcvaバリアントを使用
|
|
525
357
|
2. プロパティをFigmaのバリアントに対応させる
|
|
526
358
|
3. インタラクション状態を実装
|
|
527
359
|
```
|
|
@@ -530,7 +362,7 @@ const interactiveStyles = css({
|
|
|
530
362
|
```markdown
|
|
531
363
|
1. Figmaの各ブレークポイント用フレームを分析
|
|
532
364
|
2. ブレークポイントごとのスタイル差分を抽出
|
|
533
|
-
3.
|
|
365
|
+
3. Tailwind CSSのレスポンシブプレフィックス(`md:`, `lg:` 等)で実装
|
|
534
366
|
```
|
|
535
367
|
|
|
536
368
|
### ステップ6: 検証とフィードバック
|
|
@@ -547,8 +379,8 @@ const interactiveStyles = css({
|
|
|
547
379
|
**定期的なチェック**:
|
|
548
380
|
- Figmaのデザイントークンが更新されたら即座に反映
|
|
549
381
|
- MCPツールで最新のスタイルを再取得
|
|
550
|
-
-
|
|
551
|
-
-
|
|
382
|
+
- globals.cssを更新
|
|
383
|
+
- 型定義ファイル(必要に応じて)を更新
|
|
552
384
|
```
|
|
553
385
|
|
|
554
386
|
### 2. コンポーネントの同期
|
|
@@ -556,7 +388,7 @@ const interactiveStyles = css({
|
|
|
556
388
|
**新規コンポーネント追加時**:
|
|
557
389
|
1. Figmaで新しいコンポーネントを検出
|
|
558
390
|
2. MCPツールで仕様を抽出
|
|
559
|
-
3.
|
|
391
|
+
3. cva バリアントを作成
|
|
560
392
|
4. Reactコンポーネントを実装
|
|
561
393
|
```
|
|
562
394
|
|
|
@@ -591,7 +423,7 @@ const interactiveStyles = css({
|
|
|
591
423
|
|
|
592
424
|
### コード品質
|
|
593
425
|
- [ ] デザイントークンを使用(ハードコーディング禁止)
|
|
594
|
-
- [ ]
|
|
426
|
+
- [ ] cva バリアントで一貫性を保持
|
|
595
427
|
- [ ] 型安全なスタイル定義
|
|
596
428
|
- [ ] 保守性の高いコード構造
|
|
597
429
|
|
|
@@ -602,28 +434,23 @@ const interactiveStyles = css({
|
|
|
602
434
|
// 1. Figmaからカラースタイルを取得
|
|
603
435
|
// MCPツール: mcp__figma__get_styles (type: "fill")
|
|
604
436
|
|
|
605
|
-
// 2.
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
light: { value: "#7dd3fc" }, // Figmaの"Brand/Primary Light"
|
|
614
|
-
dark: { value: "#0284c7" }, // Figmaの"Brand/Primary Dark"
|
|
615
|
-
},
|
|
616
|
-
},
|
|
617
|
-
},
|
|
618
|
-
},
|
|
619
|
-
},
|
|
620
|
-
});
|
|
437
|
+
// 2. globals.css に CSS変数として定義
|
|
438
|
+
/*
|
|
439
|
+
:root {
|
|
440
|
+
--color-brand: 14 165 233; /* Figmaの"Brand/Primary" */
|
|
441
|
+
--color-brand-light: 125 211 252; /* Figmaの"Brand/Primary Light" */
|
|
442
|
+
--color-brand-dark: 2 132 199; /* Figmaの"Brand/Primary Dark" */
|
|
443
|
+
}
|
|
444
|
+
*/
|
|
621
445
|
|
|
622
446
|
// 3. コンポーネントで使用
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
}
|
|
447
|
+
const Component = () => {
|
|
448
|
+
return (
|
|
449
|
+
<div className="bg-[rgb(var(--color-brand))] hover:bg-[rgb(var(--color-brand-dark))]">
|
|
450
|
+
{/* または shadcn/ui のトークン使用 */}
|
|
451
|
+
</div>
|
|
452
|
+
);
|
|
453
|
+
};
|
|
627
454
|
```
|
|
628
455
|
|
|
629
456
|
### コンポーネントバリアントの実装
|
|
@@ -631,33 +458,25 @@ const styles = css({
|
|
|
631
458
|
// 1. Figmaコンポーネント情報を取得
|
|
632
459
|
// MCPツール: mcp__figma__get_component_info
|
|
633
460
|
|
|
634
|
-
// 2.
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
color: "green.900",
|
|
647
|
-
},
|
|
648
|
-
warning: {
|
|
649
|
-
bg: "yellow.50",
|
|
650
|
-
borderColor: "yellow.200",
|
|
651
|
-
color: "yellow.900",
|
|
652
|
-
},
|
|
653
|
-
error: {
|
|
654
|
-
bg: "red.50",
|
|
655
|
-
borderColor: "red.200",
|
|
656
|
-
color: "red.900",
|
|
461
|
+
// 2. バリアントをcvaとして実装
|
|
462
|
+
import { cva } from "class-variance-authority";
|
|
463
|
+
|
|
464
|
+
export const alertVariants = cva(
|
|
465
|
+
"p-4 rounded-lg border",
|
|
466
|
+
{
|
|
467
|
+
variants: {
|
|
468
|
+
severity: {
|
|
469
|
+
info: "bg-blue-50 border-blue-200 text-blue-900",
|
|
470
|
+
success: "bg-green-50 border-green-200 text-green-900",
|
|
471
|
+
warning: "bg-yellow-50 border-yellow-200 text-yellow-900",
|
|
472
|
+
error: "bg-red-50 border-red-200 text-red-900",
|
|
657
473
|
},
|
|
658
474
|
},
|
|
659
|
-
|
|
660
|
-
|
|
475
|
+
defaultVariants: {
|
|
476
|
+
severity: "info",
|
|
477
|
+
},
|
|
478
|
+
}
|
|
479
|
+
);
|
|
661
480
|
```
|
|
662
481
|
|
|
663
482
|
## 注意事項
|
|
@@ -673,8 +492,8 @@ export const alertRecipe = defineRecipe({
|
|
|
673
492
|
- プロジェクトの命名規則と統一
|
|
674
493
|
|
|
675
494
|
### パフォーマンス
|
|
676
|
-
-
|
|
677
|
-
-
|
|
495
|
+
- 不要なクラスを生成しない
|
|
496
|
+
- Tailwind CSSのPurge機能を活用
|
|
678
497
|
- ビルドサイズを監視
|
|
679
498
|
|
|
680
499
|
## 重要な原則
|
|
@@ -684,4 +503,3 @@ export const alertRecipe = defineRecipe({
|
|
|
684
503
|
- **一貫性**: デザインシステムの統一性を維持
|
|
685
504
|
- **保守性**: 将来の変更に強い構造
|
|
686
505
|
- **コラボレーション**: デザイナーとの密な連携
|
|
687
|
-
|