@patricio0312rev/skillset 0.1.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.
- package/CHANGELOG.md +29 -0
- package/LICENSE +21 -0
- package/README.md +176 -0
- package/bin/cli.js +37 -0
- package/package.json +55 -0
- package/src/commands/init.js +301 -0
- package/src/index.js +168 -0
- package/src/lib/config.js +200 -0
- package/src/lib/generator.js +166 -0
- package/src/utils/display.js +95 -0
- package/src/utils/readme.js +196 -0
- package/src/utils/tool-specific.js +233 -0
- package/templates/ai-engineering/agent-orchestration-planner/ SKILL.md +266 -0
- package/templates/ai-engineering/cost-latency-optimizer/ SKILL.md +270 -0
- package/templates/ai-engineering/doc-to-vector-dataset-generator/ SKILL.md +239 -0
- package/templates/ai-engineering/evaluation-harness/ SKILL.md +219 -0
- package/templates/ai-engineering/guardrails-safety-filter-builder/ SKILL.md +226 -0
- package/templates/ai-engineering/llm-debugger/ SKILL.md +283 -0
- package/templates/ai-engineering/prompt-regression-tester/ SKILL.md +216 -0
- package/templates/ai-engineering/prompt-template-builder/ SKILL.md +393 -0
- package/templates/ai-engineering/rag-pipeline-builder/ SKILL.md +244 -0
- package/templates/ai-engineering/tool-function-schema-designer/ SKILL.md +219 -0
- package/templates/architecture/adr-writer/ SKILL.md +250 -0
- package/templates/architecture/api-versioning-deprecation-planner/ SKILL.md +331 -0
- package/templates/architecture/domain-model-boundaries-mapper/ SKILL.md +300 -0
- package/templates/architecture/migration-planner/ SKILL.md +376 -0
- package/templates/architecture/performance-budget-setter/ SKILL.md +318 -0
- package/templates/architecture/reliability-strategy-builder/ SKILL.md +286 -0
- package/templates/architecture/rfc-generator/ SKILL.md +362 -0
- package/templates/architecture/scalability-playbook/ SKILL.md +279 -0
- package/templates/architecture/system-design-generator/ SKILL.md +339 -0
- package/templates/architecture/tech-debt-prioritizer/ SKILL.md +329 -0
- package/templates/backend/api-contract-normalizer/ SKILL.md +487 -0
- package/templates/backend/api-endpoint-generator/ SKILL.md +415 -0
- package/templates/backend/auth-module-builder/ SKILL.md +99 -0
- package/templates/backend/background-jobs-designer/ SKILL.md +166 -0
- package/templates/backend/caching-strategist/ SKILL.md +190 -0
- package/templates/backend/error-handling-standardizer/ SKILL.md +174 -0
- package/templates/backend/rate-limiting-abuse-protection/ SKILL.md +147 -0
- package/templates/backend/rbac-permissions-builder/ SKILL.md +158 -0
- package/templates/backend/service-layer-extractor/ SKILL.md +269 -0
- package/templates/backend/webhook-receiver-hardener/ SKILL.md +211 -0
- package/templates/ci-cd/artifact-sbom-publisher/ SKILL.md +236 -0
- package/templates/ci-cd/caching-strategy-optimizer/ SKILL.md +195 -0
- package/templates/ci-cd/deployment-checklist-generator/ SKILL.md +381 -0
- package/templates/ci-cd/github-actions-pipeline-creator/ SKILL.md +348 -0
- package/templates/ci-cd/monorepo-ci-optimizer/ SKILL.md +298 -0
- package/templates/ci-cd/preview-environments-builder/ SKILL.md +187 -0
- package/templates/ci-cd/quality-gates-enforcer/ SKILL.md +342 -0
- package/templates/ci-cd/release-automation-builder/ SKILL.md +281 -0
- package/templates/ci-cd/rollback-workflow-builder/ SKILL.md +372 -0
- package/templates/ci-cd/secrets-env-manager/ SKILL.md +242 -0
- package/templates/db-management/backup-restore-runbook-generator/ SKILL.md +505 -0
- package/templates/db-management/data-integrity-auditor/ SKILL.md +505 -0
- package/templates/db-management/data-retention-archiving-planner/ SKILL.md +430 -0
- package/templates/db-management/data-seeding-fixtures-builder/ SKILL.md +375 -0
- package/templates/db-management/db-performance-watchlist/ SKILL.md +425 -0
- package/templates/db-management/etl-sync-job-builder/ SKILL.md +457 -0
- package/templates/db-management/multi-tenant-safety-checker/ SKILL.md +398 -0
- package/templates/db-management/prisma-migration-assistant/ SKILL.md +379 -0
- package/templates/db-management/schema-consistency-checker/ SKILL.md +440 -0
- package/templates/db-management/sql-query-optimizer/ SKILL.md +324 -0
- package/templates/foundation/changelog-writer/ SKILL.md +431 -0
- package/templates/foundation/code-formatter-installer/ SKILL.md +320 -0
- package/templates/foundation/codebase-summarizer/ SKILL.md +360 -0
- package/templates/foundation/dependency-doctor/ SKILL.md +163 -0
- package/templates/foundation/dev-environment-bootstrapper/ SKILL.md +259 -0
- package/templates/foundation/dev-onboarding-builder/ SKILL.md +556 -0
- package/templates/foundation/docs-starter-kit/ SKILL.md +574 -0
- package/templates/foundation/explaining-code/SKILL.md +13 -0
- package/templates/foundation/git-hygiene-enforcer/ SKILL.md +455 -0
- package/templates/foundation/project-scaffolder/ SKILL.md +65 -0
- package/templates/foundation/project-scaffolder/references/templates.md +126 -0
- package/templates/foundation/repo-structure-linter/ SKILL.md +0 -0
- package/templates/foundation/repo-structure-linter/references/conventions.md +98 -0
- package/templates/frontend/animation-micro-interaction-pack/ SKILL.md +41 -0
- package/templates/frontend/component-scaffold-generator/ SKILL.md +562 -0
- package/templates/frontend/design-to-component-translator/ SKILL.md +547 -0
- package/templates/frontend/form-wizard-builder/ SKILL.md +553 -0
- package/templates/frontend/frontend-refactor-planner/ SKILL.md +37 -0
- package/templates/frontend/i18n-frontend-implementer/ SKILL.md +44 -0
- package/templates/frontend/modal-drawer-system/ SKILL.md +377 -0
- package/templates/frontend/page-layout-builder/ SKILL.md +630 -0
- package/templates/frontend/state-ux-flow-builder/ SKILL.md +23 -0
- package/templates/frontend/table-builder/ SKILL.md +350 -0
- package/templates/performance/alerting-dashboard-builder/ SKILL.md +162 -0
- package/templates/performance/backend-latency-profiler-helper/ SKILL.md +108 -0
- package/templates/performance/caching-cdn-strategy-planner/ SKILL.md +150 -0
- package/templates/performance/capacity-planning-helper/ SKILL.md +242 -0
- package/templates/performance/core-web-vitals-tuner/ SKILL.md +126 -0
- package/templates/performance/incident-runbook-generator/ SKILL.md +162 -0
- package/templates/performance/load-test-scenario-builder/ SKILL.md +256 -0
- package/templates/performance/observability-setup/ SKILL.md +232 -0
- package/templates/performance/postmortem-writer/ SKILL.md +203 -0
- package/templates/performance/structured-logging-standardizer/ SKILL.md +122 -0
- package/templates/security/auth-security-reviewer/ SKILL.md +428 -0
- package/templates/security/dependency-vulnerability-triage/ SKILL.md +495 -0
- package/templates/security/input-validation-sanitization-auditor/ SKILL.md +76 -0
- package/templates/security/pii-redaction-logging-policy-builder/ SKILL.md +65 -0
- package/templates/security/rbac-policy-tester/ SKILL.md +80 -0
- package/templates/security/secrets-scanner/ SKILL.md +462 -0
- package/templates/security/secure-headers-csp-builder/ SKILL.md +404 -0
- package/templates/security/security-incident-playbook-generator/ SKILL.md +76 -0
- package/templates/security/security-pr-checklist-skill/ SKILL.md +62 -0
- package/templates/security/threat-model-generator/ SKILL.md +394 -0
- package/templates/testing/contract-testing-builder/ SKILL.md +492 -0
- package/templates/testing/coverage-strategist/ SKILL.md +436 -0
- package/templates/testing/e2e-test-builder/ SKILL.md +382 -0
- package/templates/testing/flaky-test-detective/ SKILL.md +416 -0
- package/templates/testing/integration-test-builder/ SKILL.md +525 -0
- package/templates/testing/mocking-assistant/ SKILL.md +383 -0
- package/templates/testing/snapshot-test-refactorer/ SKILL.md +375 -0
- package/templates/testing/test-data-factory-builder/ SKILL.md +449 -0
- package/templates/testing/test-reporting-triage-skill/ SKILL.md +469 -0
- package/templates/testing/unit-test-generator/ SKILL.md +548 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design-to-component-translator
|
|
3
|
+
description: Converts Figma/design specifications into production-ready UI components with accurate spacing, typography, color tokens, responsive rules, and interaction states (hover, focus, disabled, active). Generates Tailwind/shadcn code with design system tokens mapping. Use when translating "Figma to code", "design specs to components", or "implement design system".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Design-to-Component Translator
|
|
7
|
+
|
|
8
|
+
Convert design specifications into pixel-perfect, production-ready React components.
|
|
9
|
+
|
|
10
|
+
## Core Workflow
|
|
11
|
+
|
|
12
|
+
1. **Analyze design specs**: Extract spacing, colors, typography, dimensions
|
|
13
|
+
2. **Map to tokens**: Convert design values to design system tokens
|
|
14
|
+
3. **Generate structure**: Create semantic HTML structure
|
|
15
|
+
4. **Apply styles**: Implement Tailwind/CSS with exact measurements
|
|
16
|
+
5. **Add states**: Include hover, focus, active, disabled states
|
|
17
|
+
6. **Handle responsive**: Implement breakpoint-specific rules
|
|
18
|
+
7. **Ensure accessibility**: Add ARIA labels, keyboard navigation
|
|
19
|
+
8. **Document variants**: List all visual states and props
|
|
20
|
+
|
|
21
|
+
## Design Spec Analysis
|
|
22
|
+
|
|
23
|
+
### Extract from Figma/Design
|
|
24
|
+
|
|
25
|
+
**Spacing & Layout:**
|
|
26
|
+
|
|
27
|
+
- Padding: `p-4` (16px), `px-6` (24px horizontal)
|
|
28
|
+
- Margin: `m-2` (8px), `mt-4` (16px top)
|
|
29
|
+
- Gap: `gap-3` (12px between flex items)
|
|
30
|
+
- Width/Height: `w-64` (256px), `h-10` (40px)
|
|
31
|
+
|
|
32
|
+
**Typography:**
|
|
33
|
+
|
|
34
|
+
- Font family: `font-sans`, `font-mono`
|
|
35
|
+
- Font size: `text-sm` (14px), `text-base` (16px), `text-lg` (18px)
|
|
36
|
+
- Font weight: `font-normal` (400), `font-medium` (500), `font-semibold` (600)
|
|
37
|
+
- Line height: `leading-tight`, `leading-normal`, `leading-relaxed`
|
|
38
|
+
- Letter spacing: `tracking-tight`, `tracking-normal`, `tracking-wide`
|
|
39
|
+
|
|
40
|
+
**Colors:**
|
|
41
|
+
|
|
42
|
+
- Background: `bg-blue-500`, `bg-gray-100`
|
|
43
|
+
- Text: `text-gray-900`, `text-white`
|
|
44
|
+
- Border: `border-gray-300`, `border-blue-600`
|
|
45
|
+
- Opacity: `bg-opacity-50`, `text-opacity-75`
|
|
46
|
+
|
|
47
|
+
**Borders & Radius:**
|
|
48
|
+
|
|
49
|
+
- Border width: `border`, `border-2`, `border-t-4`
|
|
50
|
+
- Border radius: `rounded` (4px), `rounded-md` (6px), `rounded-lg` (8px), `rounded-full`
|
|
51
|
+
|
|
52
|
+
**Shadows:**
|
|
53
|
+
|
|
54
|
+
- `shadow-sm`, `shadow`, `shadow-md`, `shadow-lg`, `shadow-xl`
|
|
55
|
+
|
|
56
|
+
## Design Token Mapping
|
|
57
|
+
|
|
58
|
+
### Create Token System
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// tokens.ts
|
|
62
|
+
export const tokens = {
|
|
63
|
+
colors: {
|
|
64
|
+
primary: {
|
|
65
|
+
50: "#eff6ff",
|
|
66
|
+
100: "#dbeafe",
|
|
67
|
+
500: "#3b82f6",
|
|
68
|
+
600: "#2563eb",
|
|
69
|
+
700: "#1d4ed8",
|
|
70
|
+
},
|
|
71
|
+
gray: {
|
|
72
|
+
100: "#f3f4f6",
|
|
73
|
+
300: "#d1d5db",
|
|
74
|
+
500: "#6b7280",
|
|
75
|
+
700: "#374151",
|
|
76
|
+
900: "#111827",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
spacing: {
|
|
80
|
+
xs: "0.25rem", // 4px
|
|
81
|
+
sm: "0.5rem", // 8px
|
|
82
|
+
md: "1rem", // 16px
|
|
83
|
+
lg: "1.5rem", // 24px
|
|
84
|
+
xl: "2rem", // 32px
|
|
85
|
+
},
|
|
86
|
+
fontSize: {
|
|
87
|
+
xs: ["0.75rem", { lineHeight: "1rem" }],
|
|
88
|
+
sm: ["0.875rem", { lineHeight: "1.25rem" }],
|
|
89
|
+
base: ["1rem", { lineHeight: "1.5rem" }],
|
|
90
|
+
lg: ["1.125rem", { lineHeight: "1.75rem" }],
|
|
91
|
+
xl: ["1.25rem", { lineHeight: "1.75rem" }],
|
|
92
|
+
},
|
|
93
|
+
borderRadius: {
|
|
94
|
+
sm: "0.25rem", // 4px
|
|
95
|
+
md: "0.375rem", // 6px
|
|
96
|
+
lg: "0.5rem", // 8px
|
|
97
|
+
full: "9999px",
|
|
98
|
+
},
|
|
99
|
+
shadows: {
|
|
100
|
+
sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
|
101
|
+
md: "0 4px 6px -1px rgb(0 0 0 / 0.1)",
|
|
102
|
+
lg: "0 10px 15px -3px rgb(0 0 0 / 0.1)",
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Tailwind Config
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
// tailwind.config.js
|
|
111
|
+
module.exports = {
|
|
112
|
+
theme: {
|
|
113
|
+
extend: {
|
|
114
|
+
colors: {
|
|
115
|
+
primary: {
|
|
116
|
+
50: "#eff6ff",
|
|
117
|
+
100: "#dbeafe",
|
|
118
|
+
500: "#3b82f6",
|
|
119
|
+
600: "#2563eb",
|
|
120
|
+
700: "#1d4ed8",
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
spacing: {
|
|
124
|
+
18: "4.5rem",
|
|
125
|
+
88: "22rem",
|
|
126
|
+
},
|
|
127
|
+
fontSize: {
|
|
128
|
+
"2xs": "0.625rem",
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Component Translation Examples
|
|
136
|
+
|
|
137
|
+
### Button from Figma Spec
|
|
138
|
+
|
|
139
|
+
**Figma Specs:**
|
|
140
|
+
|
|
141
|
+
- Height: 40px
|
|
142
|
+
- Padding: 12px 24px
|
|
143
|
+
- Border radius: 6px
|
|
144
|
+
- Font: Inter Medium 14px
|
|
145
|
+
- Background: #3B82F6
|
|
146
|
+
- Text: #FFFFFF
|
|
147
|
+
- Hover: #2563EB
|
|
148
|
+
- Shadow: 0 1px 3px rgba(0,0,0,0.1)
|
|
149
|
+
|
|
150
|
+
**Translated Component:**
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { cn } from "@/lib/utils";
|
|
154
|
+
|
|
155
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
156
|
+
variant?: "primary" | "secondary";
|
|
157
|
+
size?: "sm" | "md" | "lg";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const Button = ({
|
|
161
|
+
variant = "primary",
|
|
162
|
+
size = "md",
|
|
163
|
+
className,
|
|
164
|
+
children,
|
|
165
|
+
...props
|
|
166
|
+
}: ButtonProps) => {
|
|
167
|
+
return (
|
|
168
|
+
<button
|
|
169
|
+
className={cn(
|
|
170
|
+
// Base styles
|
|
171
|
+
"inline-flex items-center justify-center rounded-md font-medium",
|
|
172
|
+
"transition-colors duration-200",
|
|
173
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2",
|
|
174
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
175
|
+
// Variant: Primary (matches Figma)
|
|
176
|
+
variant === "primary" && [
|
|
177
|
+
"bg-primary-500 text-white shadow-sm",
|
|
178
|
+
"hover:bg-primary-600",
|
|
179
|
+
"active:bg-primary-700",
|
|
180
|
+
],
|
|
181
|
+
// Size: Medium (40px height, 12px 24px padding)
|
|
182
|
+
size === "md" && "h-10 px-6 text-sm",
|
|
183
|
+
className
|
|
184
|
+
)}
|
|
185
|
+
{...props}
|
|
186
|
+
>
|
|
187
|
+
{children}
|
|
188
|
+
</button>
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Card from Design Spec
|
|
194
|
+
|
|
195
|
+
**Figma Specs:**
|
|
196
|
+
|
|
197
|
+
- Padding: 24px
|
|
198
|
+
- Border radius: 12px
|
|
199
|
+
- Background: #FFFFFF
|
|
200
|
+
- Border: 1px solid #E5E7EB
|
|
201
|
+
- Shadow: 0 1px 3px rgba(0,0,0,0.1)
|
|
202
|
+
- Max width: 400px
|
|
203
|
+
|
|
204
|
+
**Translated Component:**
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
208
|
+
elevated?: boolean;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export const Card = ({
|
|
212
|
+
elevated = false,
|
|
213
|
+
className,
|
|
214
|
+
children,
|
|
215
|
+
...props
|
|
216
|
+
}: CardProps) => {
|
|
217
|
+
return (
|
|
218
|
+
<div
|
|
219
|
+
className={cn(
|
|
220
|
+
// Base from Figma
|
|
221
|
+
"max-w-sm rounded-xl bg-white p-6",
|
|
222
|
+
"border border-gray-200",
|
|
223
|
+
// Conditional shadow
|
|
224
|
+
elevated ? "shadow-lg" : "shadow-sm",
|
|
225
|
+
// Hover state (not in Figma, but good UX)
|
|
226
|
+
"transition-shadow duration-200 hover:shadow-md",
|
|
227
|
+
className
|
|
228
|
+
)}
|
|
229
|
+
{...props}
|
|
230
|
+
>
|
|
231
|
+
{children}
|
|
232
|
+
</div>
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Interaction States
|
|
238
|
+
|
|
239
|
+
### Hover States
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
// Figma: Background changes from #3B82F6 to #2563EB on hover
|
|
243
|
+
className={cn(
|
|
244
|
+
'bg-primary-500',
|
|
245
|
+
'hover:bg-primary-600',
|
|
246
|
+
'transition-colors duration-200'
|
|
247
|
+
)}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Focus States
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
// Accessible focus ring
|
|
254
|
+
className={cn(
|
|
255
|
+
'focus:outline-none',
|
|
256
|
+
'focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2'
|
|
257
|
+
)}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Active/Pressed States
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// Figma: Slightly darker on click
|
|
264
|
+
className={cn(
|
|
265
|
+
'active:bg-primary-700',
|
|
266
|
+
'active:scale-[0.98]', // Slight scale down
|
|
267
|
+
'transition-all duration-100'
|
|
268
|
+
)}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Disabled States
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
// Figma: 50% opacity, no interactions
|
|
275
|
+
className={cn(
|
|
276
|
+
'disabled:opacity-50',
|
|
277
|
+
'disabled:cursor-not-allowed',
|
|
278
|
+
'disabled:pointer-events-none'
|
|
279
|
+
)}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Responsive Design Translation
|
|
283
|
+
|
|
284
|
+
### Breakpoint Mapping
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
// Figma artboards → Tailwind breakpoints
|
|
288
|
+
// Mobile (375px): default (no prefix)
|
|
289
|
+
// Tablet (768px): md:
|
|
290
|
+
// Desktop (1024px): lg:
|
|
291
|
+
// Wide (1280px): xl:
|
|
292
|
+
|
|
293
|
+
<div
|
|
294
|
+
className={cn(
|
|
295
|
+
// Mobile: Stack vertically, full width
|
|
296
|
+
"flex flex-col gap-4 w-full",
|
|
297
|
+
// Tablet: Side by side, 50% each
|
|
298
|
+
"md:flex-row md:gap-6",
|
|
299
|
+
// Desktop: Max width container
|
|
300
|
+
"lg:max-w-6xl lg:mx-auto"
|
|
301
|
+
)}
|
|
302
|
+
/>
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Responsive Typography
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
// Figma mobile: 14px, desktop: 16px
|
|
309
|
+
<h1 className="text-sm md:text-base lg:text-lg font-semibold">
|
|
310
|
+
Responsive Heading
|
|
311
|
+
</h1>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Responsive Spacing
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
// Figma mobile: 16px padding, desktop: 24px
|
|
318
|
+
<div className="p-4 md:p-6 lg:p-8">Content</div>
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Design System Integration
|
|
322
|
+
|
|
323
|
+
### Using shadcn/ui Patterns
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
// Leveraging shadcn's composable approach
|
|
327
|
+
import { cn } from "@/lib/utils";
|
|
328
|
+
|
|
329
|
+
const buttonVariants = cva(
|
|
330
|
+
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background",
|
|
331
|
+
{
|
|
332
|
+
variants: {
|
|
333
|
+
variant: {
|
|
334
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
335
|
+
destructive:
|
|
336
|
+
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
337
|
+
outline:
|
|
338
|
+
"border border-input hover:bg-accent hover:text-accent-foreground",
|
|
339
|
+
secondary:
|
|
340
|
+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
341
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
342
|
+
link: "underline-offset-4 hover:underline text-primary",
|
|
343
|
+
},
|
|
344
|
+
size: {
|
|
345
|
+
default: "h-10 py-2 px-4",
|
|
346
|
+
sm: "h-9 px-3 rounded-md",
|
|
347
|
+
lg: "h-11 px-8 rounded-md",
|
|
348
|
+
icon: "h-10 w-10",
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
defaultVariants: {
|
|
352
|
+
variant: "default",
|
|
353
|
+
size: "default",
|
|
354
|
+
},
|
|
355
|
+
}
|
|
356
|
+
);
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Color System Translation
|
|
360
|
+
|
|
361
|
+
### From Figma to CSS Variables
|
|
362
|
+
|
|
363
|
+
```css
|
|
364
|
+
/* Figma colors → CSS variables */
|
|
365
|
+
:root {
|
|
366
|
+
/* Primary from Figma #3B82F6 */
|
|
367
|
+
--primary: 221 83% 60%;
|
|
368
|
+
--primary-foreground: 0 0% 100%;
|
|
369
|
+
|
|
370
|
+
/* Secondary from Figma #6B7280 */
|
|
371
|
+
--secondary: 220 9% 46%;
|
|
372
|
+
--secondary-foreground: 0 0% 100%;
|
|
373
|
+
|
|
374
|
+
/* Backgrounds */
|
|
375
|
+
--background: 0 0% 100%;
|
|
376
|
+
--foreground: 222 47% 11%;
|
|
377
|
+
|
|
378
|
+
/* Borders */
|
|
379
|
+
--border: 220 13% 91%;
|
|
380
|
+
--input: 220 13% 91%;
|
|
381
|
+
--ring: 221 83% 60%;
|
|
382
|
+
|
|
383
|
+
/* Radius from Figma */
|
|
384
|
+
--radius: 0.5rem;
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Using in Components
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
<div className="bg-background text-foreground border-border">
|
|
392
|
+
<button className="bg-primary text-primary-foreground">Button</button>
|
|
393
|
+
</div>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Animation & Transitions
|
|
397
|
+
|
|
398
|
+
### Micro-interactions from Figma
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// Figma: Button scales slightly on hover
|
|
402
|
+
<button className={cn(
|
|
403
|
+
'transition-all duration-200',
|
|
404
|
+
'hover:scale-105',
|
|
405
|
+
'active:scale-95'
|
|
406
|
+
)}>
|
|
407
|
+
Hover me
|
|
408
|
+
</button>
|
|
409
|
+
|
|
410
|
+
// Figma: Card lifts on hover
|
|
411
|
+
<div className={cn(
|
|
412
|
+
'transition-all duration-300',
|
|
413
|
+
'hover:-translate-y-1 hover:shadow-lg'
|
|
414
|
+
)}>
|
|
415
|
+
Card content
|
|
416
|
+
</div>
|
|
417
|
+
|
|
418
|
+
// Figma: Fade in on mount
|
|
419
|
+
<div className="animate-in fade-in duration-500">
|
|
420
|
+
Fading content
|
|
421
|
+
</div>
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Measurement Conversion
|
|
425
|
+
|
|
426
|
+
### Figma Pixels → Tailwind Classes
|
|
427
|
+
|
|
428
|
+
| Figma | Tailwind | Value |
|
|
429
|
+
| ----- | -------- | -------- |
|
|
430
|
+
| 2px | 0.5 | 0.125rem |
|
|
431
|
+
| 4px | 1 | 0.25rem |
|
|
432
|
+
| 8px | 2 | 0.5rem |
|
|
433
|
+
| 12px | 3 | 0.75rem |
|
|
434
|
+
| 16px | 4 | 1rem |
|
|
435
|
+
| 20px | 5 | 1.25rem |
|
|
436
|
+
| 24px | 6 | 1.5rem |
|
|
437
|
+
| 32px | 8 | 2rem |
|
|
438
|
+
| 40px | 10 | 2.5rem |
|
|
439
|
+
| 48px | 12 | 3rem |
|
|
440
|
+
|
|
441
|
+
### Custom Values
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
// Figma: 18px (not in default Tailwind)
|
|
445
|
+
<div className="w-[18px] h-[18px]">{/* or add to config */}</div>
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## Accessibility Mapping
|
|
449
|
+
|
|
450
|
+
### From Visual Design to A11y
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
// Figma shows disabled state
|
|
454
|
+
<button
|
|
455
|
+
disabled={isDisabled}
|
|
456
|
+
aria-disabled={isDisabled}
|
|
457
|
+
className={cn(
|
|
458
|
+
isDisabled && 'opacity-50 cursor-not-allowed'
|
|
459
|
+
)}
|
|
460
|
+
>
|
|
461
|
+
Submit
|
|
462
|
+
</button>
|
|
463
|
+
|
|
464
|
+
// Figma shows error state
|
|
465
|
+
<input
|
|
466
|
+
aria-invalid={hasError}
|
|
467
|
+
aria-describedby={hasError ? 'error-message' : undefined}
|
|
468
|
+
className={cn(
|
|
469
|
+
hasError && 'border-red-500 focus:ring-red-500'
|
|
470
|
+
)}
|
|
471
|
+
/>
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
## Common Patterns
|
|
475
|
+
|
|
476
|
+
### Form Input Translation
|
|
477
|
+
|
|
478
|
+
**Figma Specs:**
|
|
479
|
+
|
|
480
|
+
- Height: 44px
|
|
481
|
+
- Padding: 12px 16px
|
|
482
|
+
- Border: 1px #D1D5DB
|
|
483
|
+
- Border radius: 8px
|
|
484
|
+
- Focus border: 2px #3B82F6
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
<input
|
|
488
|
+
className={cn(
|
|
489
|
+
"h-11 w-full rounded-lg border border-gray-300 px-4",
|
|
490
|
+
"text-base text-gray-900 placeholder:text-gray-500",
|
|
491
|
+
"focus:border-primary-500 focus:ring-2 focus:ring-primary-500 focus:ring-offset-0",
|
|
492
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
493
|
+
)}
|
|
494
|
+
/>
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### Icon Button Translation
|
|
498
|
+
|
|
499
|
+
**Figma Specs:**
|
|
500
|
+
|
|
501
|
+
- Size: 40x40px
|
|
502
|
+
- Icon: 20x20px centered
|
|
503
|
+
- Border radius: 8px
|
|
504
|
+
- Background hover: #F3F4F6
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
<button
|
|
508
|
+
className={cn(
|
|
509
|
+
"flex h-10 w-10 items-center justify-center rounded-lg",
|
|
510
|
+
"text-gray-700 transition-colors",
|
|
511
|
+
"hover:bg-gray-100",
|
|
512
|
+
"focus-visible:ring-2 focus-visible:ring-primary-500"
|
|
513
|
+
)}
|
|
514
|
+
>
|
|
515
|
+
<Icon className="h-5 w-5" />
|
|
516
|
+
</button>
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
## Best Practices
|
|
520
|
+
|
|
521
|
+
1. **Measure twice**: Verify all measurements match Figma exactly
|
|
522
|
+
2. **Use design tokens**: Map to tokens, not hardcoded values
|
|
523
|
+
3. **All states**: Include hover, focus, active, disabled, error
|
|
524
|
+
4. **Responsive**: Implement all breakpoints from design
|
|
525
|
+
5. **Accessibility**: Add ARIA where Figma shows states
|
|
526
|
+
6. **Animations**: Match transition timings to design
|
|
527
|
+
7. **Dark mode**: If designs exist, implement with class variants
|
|
528
|
+
8. **Component variants**: Create reusable variant props
|
|
529
|
+
9. **Documentation**: Note any deviations from design
|
|
530
|
+
10. **Review**: Get designer approval on implementation
|
|
531
|
+
|
|
532
|
+
## Output Checklist
|
|
533
|
+
|
|
534
|
+
Every design-to-component translation should include:
|
|
535
|
+
|
|
536
|
+
- [ ] Exact spacing matching Figma measurements
|
|
537
|
+
- [ ] Typography scales and weights
|
|
538
|
+
- [ ] All color values from design system
|
|
539
|
+
- [ ] Border radius and shadows
|
|
540
|
+
- [ ] Hover state styling
|
|
541
|
+
- [ ] Focus state styling (accessible)
|
|
542
|
+
- [ ] Active/pressed state styling
|
|
543
|
+
- [ ] Disabled state styling
|
|
544
|
+
- [ ] Responsive breakpoint rules
|
|
545
|
+
- [ ] Design token mapping documented
|
|
546
|
+
- [ ] Accessibility attributes
|
|
547
|
+
- [ ] Component variants for states
|