Design System Patterns
Installation
SKILL.md
Design System Patterns
Pencil에서 디자인 시스템을 구축하고 관리하는 패턴과 모범 사례를 제공한다.
Core Concepts
디자인 토큰
디자인 토큰은 디자인 시스템의 기본 단위로, 변수로 정의하여 일관성을 유지한다.
| Token Type | 예시 | 용도 |
|---|---|---|
| Colors | primary, secondary, neutral | 브랜드 색상, UI 색상 |
| Typography | heading, body, caption | 폰트 크기, 굵기, 행간 |
| Spacing | xs, sm, md, lg, xl | 여백, 간격 |
| Radii | sm, md, lg, full | 모서리 둥글기 |
| Shadows | sm, md, lg | 그림자 효과 |
컴포넌트 계층
Primitives (기본 요소)
└── Atoms (원자: Button, Input, Badge)
└── Molecules (분자: SearchBar, Card, MenuItem)
└── Organisms (유기체: Header, Sidebar, Form)
└── Templates (템플릿: PageLayout, DashboardLayout)
Variables Management
get_variables로 조회
mcp__pencil__get_variables(filePath: string)
현재 정의된 모든 변수와 테마를 반환한다.
set_variables로 설정
mcp__pencil__set_variables(
filePath: string,
variables: object,
replace?: boolean
)
변수 구조 예시
{
"colors": {
"primary": {
"50": "#EFF6FF",
"100": "#DBEAFE",
"500": "#3B82F6",
"600": "#2563EB",
"700": "#1D4ED8"
},
"neutral": {
"50": "#F8FAFC",
"100": "#F1F5F9",
"500": "#64748B",
"900": "#0F172A"
}
},
"typography": {
"fontFamily": "Inter, sans-serif",
"fontSize": {
"xs": 12,
"sm": 14,
"base": 16,
"lg": 18,
"xl": 20,
"2xl": 24,
"3xl": 30
},
"fontWeight": {
"normal": 400,
"medium": 500,
"semibold": 600,
"bold": 700
}
},
"spacing": {
"0": 0,
"1": 4,
"2": 8,
"3": 12,
"4": 16,
"5": 20,
"6": 24,
"8": 32,
"10": 40,
"12": 48
},
"radii": {
"none": 0,
"sm": 4,
"md": 8,
"lg": 12,
"xl": 16,
"full": 9999
}
}
변수 참조
노드 속성에서 변수 참조:
button=I("parentId", {
type: "frame",
fill: "var(colors/primary/500)",
padding: "var(spacing/4)",
cornerRadius: "var(radii/md)"
})
label=I(button, {
type: "text",
content: "Button",
fontSize: "var(typography/fontSize/base)",
fontWeight: "var(typography/fontWeight/medium)",
textColor: "#FFFFFF"
})
Creating Reusable Components
컴포넌트 정의
reusable: true 속성으로 컴포넌트 등록:
// Button 컴포넌트 정의
buttonComp=I(document, {
type: "frame",
name: "Button",
reusable: true,
layout: "horizontal",
padding: [12, 24, 12, 24],
alignItems: "center",
justifyContent: "center",
gap: 8,
fill: "var(colors/primary/500)",
cornerRadius: "var(radii/md)"
})
btnLabel=I(buttonComp, {
type: "text",
name: "label",
content: "Button",
textColor: "#FFFFFF",
fontWeight: "var(typography/fontWeight/medium)"
})
컴포넌트 인스턴스 사용
// 컴포넌트 인스턴스 생성
btn1=I("formId", { type: "ref", ref: "buttonCompId" })
// 인스턴스 내부 수정
U(btn1+"/label", { content: "Submit" })
컴포넌트 Variants
상태별 변형을 별도 컴포넌트로 정의:
// Primary Button
primaryBtn=I(document, {
type: "frame",
name: "Button/Primary",
reusable: true,
fill: "var(colors/primary/500)"
// ... rest
})
// Secondary Button
secondaryBtn=I(document, {
type: "frame",
name: "Button/Secondary",
reusable: true,
fill: "transparent",
stroke: "var(colors/primary/500)",
strokeWidth: 1
// ... rest
})
// Ghost Button
ghostBtn=I(document, {
type: "frame",
name: "Button/Ghost",
reusable: true,
fill: "transparent"
// ... rest
})
Common Component Patterns
Button
button=I(document, {
type: "frame",
name: "Button",
reusable: true,
layout: "horizontal",
padding: [12, 24, 12, 24],
alignItems: "center",
justifyContent: "center",
gap: 8,
fill: "var(colors/primary/500)",
cornerRadius: "var(radii/md)"
})
icon=I(button, {
type: "frame",
name: "iconSlot",
width: 20,
height: 20,
placeholder: true
})
label=I(button, {
type: "text",
name: "label",
content: "Button",
fontSize: "var(typography/fontSize/base)",
fontWeight: "var(typography/fontWeight/medium)",
textColor: "#FFFFFF"
})
Input Field
inputField=I(document, {
type: "frame",
name: "InputField",
reusable: true,
layout: "vertical",
gap: 8,
width: "fill_container"
})
label=I(inputField, {
type: "text",
name: "label",
content: "Label",
fontSize: "var(typography/fontSize/sm)",
fontWeight: "var(typography/fontWeight/medium)"
})
input=I(inputField, {
type: "frame",
name: "input",
layout: "horizontal",
width: "fill_container",
height: 44,
padding: [0, 16, 0, 16],
alignItems: "center",
fill: "#FFFFFF",
stroke: "var(colors/neutral/200)",
strokeWidth: 1,
cornerRadius: "var(radii/md)"
})
placeholder=I(input, {
type: "text",
name: "placeholder",
content: "Enter value...",
textColor: "var(colors/neutral/400)"
})
helper=I(inputField, {
type: "text",
name: "helperText",
content: "",
fontSize: "var(typography/fontSize/xs)",
textColor: "var(colors/neutral/500)"
})
Card
card=I(document, {
type: "frame",
name: "Card",
reusable: true,
layout: "vertical",
width: 320,
fill: "#FFFFFF",
cornerRadius: "var(radii/lg)",
clipContent: true
})
media=I(card, {
type: "frame",
name: "mediaSlot",
width: "fill_container",
height: 180,
placeholder: true
})
content=I(card, {
type: "frame",
name: "content",
layout: "vertical",
padding: 24,
gap: 12
})
title=I(content, {
type: "text",
name: "title",
content: "Card Title",
fontSize: "var(typography/fontSize/lg)",
fontWeight: "var(typography/fontWeight/semibold)"
})
description=I(content, {
type: "text",
name: "description",
content: "Card description...",
textColor: "var(colors/neutral/600)"
})
actions=I(card, {
type: "frame",
name: "actionsSlot",
layout: "horizontal",
padding: [0, 24, 24, 24],
gap: 12,
placeholder: true
})
Theming
테마 축 정의
라이트/다크 모드 지원:
{
"themeAxes": {
"mode": ["light", "dark"]
},
"colors": {
"background": {
"mode:light": "#FFFFFF",
"mode:dark": "#0F172A"
},
"text": {
"primary": {
"mode:light": "#0F172A",
"mode:dark": "#F8FAFC"
},
"secondary": {
"mode:light": "#64748B",
"mode:dark": "#94A3B8"
}
}
}
}
테마 적용
// 변수 참조 시 현재 테마 값 자동 적용
container=I("parentId", {
type: "frame",
fill: "var(colors/background)"
})
title=I(container, {
type: "text",
content: "Title",
textColor: "var(colors/text/primary)"
})
Best Practices
Naming Conventions
- 컴포넌트: PascalCase (
Button,InputField,Card) - Variants: Slash 구분 (
Button/Primary,Button/Secondary) - 내부 노드: camelCase (
label,iconSlot,contentArea) - 변수: lowercase/슬래시 (
colors/primary/500,spacing/4)
Component Organization
- Primitives first: 기본 요소부터 정의
- Compose up: 작은 컴포넌트로 큰 컴포넌트 구성
- Single responsibility: 하나의 역할만 담당
- Prop slots: placeholder로 커스터마이징 지점 제공
Variable Usage
- Consistent tokens: 하드코딩 대신 변수 참조
- Semantic names: 용도 기반 이름 (primary, danger, not blue, red)
- Scale systems: 일관된 스케일 (4px 단위 스페이싱)
Additional Resources
Reference Files
references/token-scales.md- 표준 토큰 스케일 정의references/component-catalog.md- 공통 컴포넌트 카탈로그
Related skills
More from gyejoon/pencil-plugin
pencil basics
This skill should be used when the user asks about "pencil 사용법", ".pen 파일", "노드 타입", "레이아웃 시스템", "pencil mcp", "batch_design", "batch_get", or wants to understand how to work with Pencil design files. Provides comprehensive guidance for using Pencil MCP tools effectively.
43design to code
This skill should be used when the user asks to "코드 변환", "React 생성", "Tailwind 코드", "컴포넌트 코드", "디자인을 코드로", ".pen 파일에서 코드", or wants to convert Pencil designs into React + Tailwind CSS code.
39