design to code
19
总安装量
0
周安装量
#18543
全站排名
安装命令
npx skills add https://github.com/gyejoon/pencil-plugin --skill Design to Code
Skill 文档
Design to Code
Pencil .pen íì¼ì ëìì¸ì React + Tailwind CSS ì½ëë¡ ë³ííë ê°ì´ëë¼ì¸ì ì ê³µíë¤.
Conversion Workflow
1. ëìì¸ ë¶ì
ëì ë ¸ëì 구조를 íì íë¤:
mcp__pencil__batch_get(
filePath: "design.pen",
nodeIds: ["targetNodeId"],
readDepth: 5,
resolveInstances: true,
resolveVariables: true
)
resolveInstances: trueë¡ ì»´í¬ëí¸ ì¸ì¤í´ì¤ë¥¼ íì´ì íì¸íê³ , resolveVariables: trueë¡ ë³ìê°ì ì¤ì ê°ì¼ë¡ íì¸íë¤.
2. ë³ì ì¶ì¶
ëìì¸ í í°ì Tailwind ì¤ì ì¼ë¡ ë³ííë¤:
mcp__pencil__get_variables(filePath: "design.pen")
3. ì½ë ìì±
ë ¸ë íì ì ë°ë¼ ì ì í React ì»´í¬ëí¸ë¡ ë³ííë¤.
4. ì¤í¬ë¦°ì· ë¹êµ
ìì±ë ì½ë를 ìê°ì ì¼ë¡ ê²ì¦íë¤.
Node to Component Mapping
| Pencil Node | React/HTML | Tailwind Classes |
|---|---|---|
| frame (layout: vertical) | <div> |
flex flex-col |
| frame (layout: horizontal) | <div> |
flex flex-row |
| frame (layout: grid) | <div> |
grid grid-cols-N |
| text | <p>, <span>, <h1-6> |
text-*, font-* |
| rectangle | <div> |
rounded-*, bg-* |
| ref (Button) | <button> or <Button> |
ì»´í¬ëí¸ë³ |
Property to Tailwind Mapping
Layout
| Pencil Property | Tailwind |
|---|---|
layout: "horizontal" |
flex flex-row |
layout: "vertical" |
flex flex-col |
layout: "grid" |
grid |
gap: 16 |
gap-4 |
padding: 16 |
p-4 |
padding: [16, 24, 16, 24] |
py-4 px-6 |
alignItems: "center" |
items-center |
justifyContent: "center" |
justify-center |
justifyContent: "space-between" |
justify-between |
Sizing
| Pencil Property | Tailwind |
|---|---|
width: "fill_container" |
w-full |
height: "fill_container" |
h-full |
width: "hug_contents" |
w-fit |
width: 320 |
w-80 or w-[320px] |
Typography
| Pencil Property | Tailwind |
|---|---|
fontSize: 16 |
text-base |
fontSize: 24 |
text-2xl |
fontWeight: "bold" |
font-bold |
fontWeight: "semibold" |
font-semibold |
textAlign: "center" |
text-center |
textColor: "#3B82F6" |
text-blue-500 |
Colors
| Pencil Color | Tailwind |
|---|---|
#3B82F6 |
blue-500 |
#EF4444 |
red-500 |
#22C55E |
green-500 |
#F8FAFC |
slate-50 |
#0F172A |
slate-900 |
Border Radius
| Pencil Property | Tailwind |
|---|---|
cornerRadius: 4 |
rounded-sm |
cornerRadius: 8 |
rounded-lg |
cornerRadius: 12 |
rounded-xl |
cornerRadius: 9999 |
rounded-full |
Effects
| Pencil Property | Tailwind |
|---|---|
opacity: 0.5 |
opacity-50 |
overflow: "hidden" |
overflow-hidden |
| Shadow (small) | shadow-sm |
| Shadow (medium) | shadow-md |
Code Generation Patterns
Basic Component
Pencil ë ¸ë:
{
"type": "frame",
"layout": "vertical",
"padding": 24,
"gap": 16,
"fill": "#FFFFFF",
"cornerRadius": 12,
"children": [
{ "type": "text", "content": "Title", "fontSize": 24, "fontWeight": "bold" },
{ "type": "text", "content": "Description", "textColor": "#64748B" }
]
}
React + Tailwind:
function Card() {
return (
<div className="flex flex-col p-6 gap-4 bg-white rounded-xl">
<h2 className="text-2xl font-bold">Title</h2>
<p className="text-slate-500">Description</p>
</div>
)
}
Interactive Component
ë²í¼ ì»´í¬ëí¸:
interface ButtonProps {
children: React.ReactNode
variant?: 'primary' | 'secondary'
onClick?: () => void
}
function Button({ children, variant = 'primary', onClick }: ButtonProps) {
const baseClasses = "flex items-center justify-center px-6 py-3 gap-2 rounded-lg font-medium transition-colors"
const variantClasses = {
primary: "bg-blue-500 text-white hover:bg-blue-600",
secondary: "bg-transparent border border-blue-500 text-blue-500 hover:bg-blue-50"
}
return (
<button
className={`${baseClasses} ${variantClasses[variant]}`}
onClick={onClick}
>
{children}
</button>
)
}
Layout Component
íì´ì§ ë ì´ìì:
function PageLayout({ children }: { children: React.ReactNode }) {
return (
<div className="flex min-h-screen">
{/* Sidebar */}
<aside className="flex flex-col w-64 p-6 gap-4 bg-slate-50 border-r border-slate-200">
<h1 className="text-xl font-bold">Logo</h1>
<nav className="flex flex-col gap-2">
<a href="#" className="px-4 py-2 rounded-lg hover:bg-slate-100">Dashboard</a>
<a href="#" className="px-4 py-2 rounded-lg hover:bg-slate-100">Settings</a>
</nav>
</aside>
{/* Main Content */}
<main className="flex-1 p-8">
{children}
</main>
</div>
)
}
Variable to Tailwind Config
Pencil ë³ì를 tailwind.config.jsë¡ ë³í:
Input (Pencil Variables)
{
"colors": {
"primary": { "500": "#3B82F6", "600": "#2563EB" },
"neutral": { "50": "#F8FAFC", "900": "#0F172A" }
},
"spacing": { "4": 16, "6": 24, "8": 32 },
"radii": { "md": 8, "lg": 12 }
}
Output (Tailwind Config)
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: {
500: '#3B82F6',
600: '#2563EB',
},
neutral: {
50: '#F8FAFC',
900: '#0F172A',
},
},
spacing: {
4: '16px',
6: '24px',
8: '32px',
},
borderRadius: {
md: '8px',
lg: '12px',
},
},
},
}
Best Practices
Component Naming
- ì미 ìë ì´ë¦ ì¬ì© (Card, Button, Header)
- PascalCase ì¬ì©
- íì¼ëª ì ì»´í¬ëí¸ëª ê³¼ ì¼ì¹
Props Design
- íì propsì ì í props 구ë¶
- í©ë¦¬ì ì¸ ê¸°ë³¸ê° ì ê³µ
- TypeScript ì¸í°íì´ì¤ ì ì
Tailwind Usage
- ì í¸ë¦¬í° í´ëì¤ ì°ì
- ë°ë³µëë í¨í´ì ì»´í¬ëí¸ë¡ ì¶ì¶
- ë³µì¡í ê°ì arbitrary values ì¬ì©
w-[320px] @applyë ìµìí
Accessibility
- ìë§¨í± HTML ìì ì¬ì©
- ARIA ìì± ì ì í ì¶ê°
- í¤ë³´ë ë¤ë¹ê²ì´ì ì§ì
- ìì ëë¹ íì¸
Output Format
ë¨ì¼ TSX íì¼ íì:
// ComponentName.tsx
import { useState } from 'react'
interface ComponentNameProps {
// props ì ì
}
export function ComponentName({ ...props }: ComponentNameProps) {
// ìí ë° ë¡ì§
return (
// JSX
)
}
Additional Resources
Reference Files
references/tailwind-mapping.md– ì ì²´ Pencil-Tailwind 매í í ì´ë¸references/component-templates.md– ê³µíµ ì»´í¬ëí¸ í í릿