design-to-swiftui
Convert design specifications from Figma, Sketch, or Penpot to SwiftUI view code with proper modifiers and theme integration
安装与使用
请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。
查看来源 ↗使用指南技能说明
Design to SwiftUI
Convert design component specifications to SwiftUI view code.
Overview
This skill transforms design specifications (from Figma, Sketch, or Penpot) into idiomatic SwiftUI views with proper modifiers, layout containers, and theme token integration.
This skill covers:
- Converting design frames to SwiftUI layouts (VStack, HStack, ZStack)
- Mapping design properties to SwiftUI modifiers
- Generating reusable SwiftUI components
- Integrating with extracted design tokens
This skill does NOT cover:
- Design token extraction (see
design-tokens-extractionskill) - State management and data binding
- Navigation and routing
Quick Reference
Design to SwiftUI Mapping
| Design Element | SwiftUI Component |
|---|---|
| Horizontal layout | HStack |
| Vertical layout | VStack |
| Overlapping layers | ZStack |
| Auto-layout | Stack with spacing |
| Grid | LazyVGrid / LazyHGrid |
| Scroll container | ScrollView |
| Text | Text with modifiers |
| Rectangle | RoundedRectangle or Rectangle |
| Circle | Circle |
| Image | Image / AsyncImage |
| Button | Button with custom label |
Property Mapping
| Design Property | SwiftUI Modifier |
|---|---|
| Fill color | .fill() / .foregroundStyle() |
| Stroke | .stroke() / .overlay() |
| Corner radius | .clipShape(RoundedRectangle()) |
| Shadow | .shadow() |
| Opacity | .opacity() |
| Padding | .padding() |
| Size | .frame() |
| Position | .offset() / .position() |
Workflow: Convert Design Component
Step 1: Analyze Design Structure
Read the design component from MCP and identify:
- Layout type (horizontal, vertical, grid, free-form)
- Child elements and their order
- Spacing and padding values
- Constraints and sizing behavior
Step 2: Map to SwiftUI Layout
Auto-layout (horizontal):
HStack(alignment: .<alignment>, spacing: <gap>) {
// children
}
Auto-layout (vertical):
VStack(alignment: .<alignment>, spacing: <gap>) {
// children
}
Grid layout:
let columns = [
GridItem(.flexible()),
GridItem(.flexible())
]
LazyVGrid(columns: columns, spacing: <gap>) {
// children
}
Absolute positioning (rare in SwiftUI):
ZStack {
// position children with .offset() or .position()
}
Step 3: Generate View Code
For each design element, generate SwiftUI code:
Text elements:
Text("<content>")
.font(<Theme.Typography.style>)
.foregroundStyle(<Theme.Colors.color>)
.lineLimit(<lines>)
.multilineTextAlignment(.<alignment>)
Shapes with fill:
RoundedRectangle(cornerRadius: Theme.Radius.<size>)
.fill(Theme.Colors.<color>)
.frame(width: <width>, height: <height>)
.shadow(color: .black.opacity(0.1), radius: 4, y: 2)
Images:
// Local image
Image("<assetName>")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: <width>, height: <height>)
.clipShape(RoundedRectangle(cornerRadius: Theme.Radius.<size>))
// Remote image
AsyncImage(url: URL(string: "<url>")) { image in
image
.resizable()
.aspectRatio(contentMode: .fill)
} placeholder: {
ProgressView()
}
.frame(width: <width>, height: <height>)
Buttons:
Button {
// action
} label: {
HStack(spacing: 8) {
Image(systemName: "<icon>")
Text("<label>")
}
.font(Theme.Typography.<style>)
.foregroundStyle(Theme.Colors.<textColor>)
.padding(.horizontal, Theme.Spacing.<h>)
.padding(.vertical, Theme.Spacing.<v>)
.background(Theme.Colors.<bgColor>)
.clipShape(RoundedRectangle(cornerRadius: Theme.Radius.<size>))
}
Step 4: Create Component View
Wrap the generated code in a reusable SwiftUI View:
import SwiftUI
struct <ComponentName>View: View {
// Properties extracted from design variants
let title: String
let subtitle: String?
var onTap: (() -> Void)?
var body: some View {
VStack(alignment: .leading, spacing: Theme.Spacing.sm) {
Text(title)
.font(Theme.Typography.headlineMedium)
.foregroundStyle(Theme.Colors.text)
if let subtitle {
Text(subtitle)
.font(Theme.Typography.bodyMedium)
.foregroundStyle(Theme.Colors.textSecondary)
}
}
.padding(Theme.Spacing.md)
.background(Theme.Colors.surface)
.clipShape(RoundedRectangle(cornerRadius: Theme.Radius.md))
.onTapGesture {
onTap?()
}
}
}
#Preview {
<ComponentName>View(
title: "Preview Title",
subtitle: "Preview subtitle text"
)
.padding()
}
Common Patterns
Card Component
Design spec:
- Background fill with rounded corners
- Shadow elevation
- Padding around content
- Optional image header
struct CardView<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
content
}
.background(Theme.Colors.surface)
.clipShape(RoundedRectangle(cornerRadius: Theme.Radius.lg))
.shadow(
color: .black.opacity(0.08),
radius: 8,
y: 4
)
}
}
Button Variants
Design spec defines Primary, Secondary, Ghost variants:
enum ButtonVariant {
case primary, secondary, ghost
var backgroundColor: Color {
switch self {
case .primary: Theme.Colors.primary
case .secondary: Theme.Colors.surface
case .ghost: .clear
}
}
var foregroundColor: Color {
switch self {
case .primary: Theme.Colors.onPrimary
case .secondary: Theme.Colors.primary
case .ghost: Theme.Colors.primary
}
}
}
struct ThemedButton: View {
let title: String
let variant: ButtonVariant
let action: () -> Void
var body: some View {
Button(action: action) {
Text(title)
.font(Theme.Typography.labelLarge)
.foregroundStyle(variant.foregroundColor)
.padding(.horizontal, Theme.Spacing.lg)
.padding(.vertical, Theme.Spacing.md)
.background(variant.backgroundColor)
.clipShape(RoundedRectangle(cornerRadius: Theme.Radius.md))
}
}
}
List Item
Design spec with leading icon, title/subtitle, trailing accessory:
struct ListItemView: View {
let icon: String
let title: String
let subtitle: String?
let accessory: Accessory
enum Accessory {
case chevron
case toggle(Binding<Bool>)
case badge(String)
case none
}
var body: some View {
HStack(spacing: Theme.Spacing.md) {
Image(systemName: icon)
.font(.system(size: 20))
.foregroundStyle(Theme.Colors.primary)
.frame(width: 24)
VStack(alignment: .leading, spacing: 2) {
Text(title)
.font(Theme.Typography.bodyLarge)
.foregroundStyle(Theme.Colors.text)
if let subtitle {
Text(subtitle)
.font(Theme.Typography.bodySmall)
.foregroundStyle(Theme.Colors.textSecondary)
}
}
Spacer()
accessoryView
}
.padding(.vertical, Theme.Spacing.sm)
.padding(.horizontal, Theme.Spacing.md)
}
@ViewBuilder
private var accessoryView: some View {
switch accessory {
case .chevron:
Image(systemName: "chevron.right")
.foregroundStyle(Theme.Colors.textSecondary)
case .toggle(let isOn):
Toggle("", isOn: isOn)
.labelsHidden()
case .badge(let text):
Text(text)
.font(Theme.Typography.labelSmall)
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(Theme.Colors.primary)
.foregroundStyle(Theme.Colors.onPrimary)
.clipShape(Capsule())
case .none:
EmptyView()
}
}
}
Token Integration
Reference design tokens through the Theme struct:
// Colors
Theme.Colors.primary
Theme.Colors.surface
Theme.Colors.text
Theme.Colors.textSecondary
// Typography
Theme.Typography.displayLarge
Theme.Typography.headlineMedium
Theme.Typography.bodyLarge
Theme.Typography.labelSmall
// Spacing
Theme.Spacing.xs // 4
Theme.Spacing.sm // 8
Theme.Spacing.md // 16
Theme.Spacing.lg // 24
Theme.Spacing.xl // 32
// Corner Radius
Theme.Radius.sm // 4
Theme.Radius.md // 8
Theme.Radius.lg // 16
Theme.Radius.full // 9999
Naming Conventions
| Design Name | SwiftUI Name |
|---|---|
Button/Primary |
PrimaryButton |
Card - Article |
ArticleCardView |
List Item/Default |
ListItemView |
Header/Large |
LargeHeaderView |
Input/Text Field |
TextFieldView |
See Also
-
design-tokens-extractionskill - Extract tokens first -
design-token-swiftstyle - Swift code output format -
swiftui-componentsskill - SwiftUI component patterns
使用示例
查看来源仓库中的使用示例与配置说明。
查看来源 ↗来源历史
- 收录时间
- 2026-03-11
- 索引更新时间
- 2026-03-11
- Branch
- main
收录与同步日期属于本站记录。源码修改历史请查看来源仓库。
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!