You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: skills/figma.md
+25-13Lines changed: 25 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,8 @@ description: >
12
12
13
13
Translate Figma designs built with the [Windows UI Kit (Community)](https://www.figma.com/design/t7yLwpMUOWJSYt5ahz3ROC/Windows-UI-kit--Community-) into Reactor C# code. This skill provides the mapping tables and rules the agent applies during code generation.
14
14
15
+
**Goal: Pixel-accurate reproduction.** Every dimension, gap, margin, padding, and position value from Figma must be used exactly as specified — no rounding, no substitution. The generated app should match the Figma design pixel-for-pixel. Where `design.md` recommends flexible sizing (MinWidth) or 4px grid rounding for hand-written code, those rules are overridden here — Figma translation uses exact values.
16
+
15
17
**Prerequisites:**
16
18
- A Figma MCP server must be configured (e.g., `figma-developer-mcp`) for URL-based extraction. See [spec 033](../docs/specs/033-figma-to-reactor.md) for the full workflow architecture.
17
19
@@ -75,21 +77,30 @@ Pass the full URL to the Figma MCP tool — the server handles node scoping.
|`itemSpacing`|`N`| Gap parameter: `VStack(N, ...)` or `HStack(N, ...)`|
78
-
|`paddingTop/Right/Bottom/Left`| uniform `P`| Wrap in `Border(VStack(...)).Padding(P)`|
79
-
|`paddingTop/Right/Bottom/Left`| mixed | Wrap in `Border(VStack(...)).Padding(left, top, right, bottom)`|
80
+
|`paddingTop/Right/Bottom/Left`| all equal `P`|`.Padding(P)` on the wrapping `Border`|
81
+
|`paddingTop/Right/Bottom/Left`| symmetric (h≠v) |`.Padding(vertical, horizontal)` on the wrapping `Border`|
82
+
|`paddingTop/Right/Bottom/Left`| mixed |`.Padding(left: L, top: T, right: R, bottom: B)` on the wrapping `Border`|
80
83
81
84
**Important:**`VStack` and `HStack` do not support `.Padding()` — only `Border` and control-based elements do. Always wrap the stack in a `Border` when padding is needed. Use `.Margin()` when the spacing is between the element and its siblings rather than internal padding.
82
85
86
+
**Margin overloads:**
87
+
-`.Margin(uniform)` — all four sides equal
88
+
-`.Margin(vertical, horizontal)` — top/bottom share one value, left/right share another
89
+
-`.Margin(left: L, top: T, right: R, bottom: B)` — use named args for per-side values
90
+
83
91
### Sizing
84
92
85
93
| Figma Sizing Mode | Reactor Output |
86
94
|---|---|
87
-
| Fixed width/height |`.MinWidth(N)` / `.MinHeight(N)` (prefer over fixed `.Width(N)` / `.Height(N)` for text scaling) |
95
+
| Fixed width |`.Width(N)` — use the **exact** pixel value from Figma |
96
+
| Fixed height |`.Height(N)` — use the **exact** pixel value from Figma |
97
+
| Fixed width + height |`.Size(W, H)` — shorthand for both |
88
98
| Hug contents | No explicit size (natural sizing) |
89
99
| Fill container |`.HAlign(HorizontalAlignment.Stretch)`|
Prefer `MinWidth`/`MinHeight` over fixed `Width`/`Height` on controls and text containers — fixed sizes clip content at larger text scales.
103
+
**Pixel-accuracy rule:** When Figma specifies a fixed width or height, always use the **exact** value via `.Width(N)` / `.Height(N)` / `.Size(W, H)`. Do NOT substitute `MinWidth`/`MinHeight` for fixed dimensions — that produces different layout behavior. Only use `MinWidth`/`MinHeight` when the Figma node explicitly has min/max constraints.
93
104
94
105
### Alignment
95
106
@@ -117,15 +128,16 @@ Prefer `MinWidth`/`MinHeight` over fixed `Width`/`Height` on controls and text c
117
128
118
129
Always set `HorizontalContentAlignment = Stretch` on vertical scroll regions to prevent content from collapsing. Place headers and footers outside the ScrollView so they remain fixed.
119
130
120
-
### Spacing Grid Rule
131
+
### Spacing Rule
121
132
122
-
Round all spacing values to the **4px grid**: 4, 8, 12, 16, 20, 24, 32, 40, 48.
123
-
124
-
If a Figma value is not on the grid (e.g., 15px), round to nearest grid value (16px) and add a comment:
133
+
Use the **exact** pixel values from Figma for all spacing, gaps, margins, and padding. Do NOT round to a grid. Pixel-accurate reproduction is the goal.
125
134
126
135
```csharp
127
-
// Note: Figma spacing was 15px, rounded to 16px (4px grid)
128
-
VStack(16, children)
136
+
// Figma says itemSpacing = 13 → use 13, not 12 or 16
137
+
VStack(13, children)
138
+
139
+
// Figma says padding top=18, left=24 → use exact values
140
+
Border(content).Padding(left: 24, top: 18)
129
141
```
130
142
131
143
## Control Mapping
@@ -444,7 +456,7 @@ Note: `dotnet watch` does not maintain MCP/devtools sessions across rebuilds. Us
444
456
3.**Follow design.md best practices** — all generated code must comply with the `design.md` skill rules. Key requirements:
445
457
- Use `.ApplyStyle()` or Reactor text factories (`Caption()`, `SubHeading()`, `Heading()`) for typography — not raw `FontSize`/`FontWeight` (§4).
446
458
-`VStack`/`HStack` do not support `.Padding()` — wrap in `Border` (§5).
447
-
-Prefer `MinWidth`/`MinHeight` over fixed `Width`/`Height` on controls and text containers (§5).
459
+
-Use `.Width(N)` / `.Height(N)` / `.Size(W, H)` for fixed Figma dimensions. Only use `MinWidth`/`MinHeight` when Figma explicitly sets min/max constraints (§5).
448
460
- Use `.HAlign()` / `.VAlign()` for alignment — not `.HorizontalAlignment()` / `.VerticalAlignment()` (§5).
449
461
- Set `HorizontalContentAlignment = Stretch` on vertical `ScrollView` (§5).
450
462
- Add `.AutomationName()` on icon-only interactive controls; use `.AccessibilityHidden()` on decorative icons (§7).
@@ -453,7 +465,7 @@ Note: `dotnet watch` does not maintain MCP/devtools sessions across rebuilds. Us
453
465
- Use `SymbolThemeFontFamily` for icon font glyphs (§4).
454
466
- For circular elements, derive radius from size (`size / 2`) instead of hardcoded values (§5).
455
467
4.**Use Theme tokens first** — follow the token resolution ladder strictly. No hex on themed surfaces.
456
-
5.**Round to 4px grid** — all spacingvalues must be multiples of 4.
468
+
5.**Use exact pixel values** — do NOT round spacing, margins, padding, gaps, widths, or heights. Use the exact values from Figma for pixel-accurate output.
457
469
6.**Use theme resources for corner radii** — `ControlCornerRadius` (4px) and `OverlayCornerRadius` (8px). Do not hardcode number values.
458
470
7.**Emit TODO for unknowns** — never silently skip or guess. Every unmapped element gets a placeholder with the Figma node ID.
459
471
8.**One Component per top-level frame** — each major Figma frame becomes a Reactor Component class.
Copy file name to clipboardExpand all lines: tools/figma-plugin/dist/ui.html
+9-6Lines changed: 9 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -207,12 +207,16 @@
207
207
varcsproj=getCsprojPath();
208
208
varname=getProjectName();
209
209
210
-
varskillRef='Read skills/figma.md for Figma-to-Reactor control mapping, theme tokens, typography, and layout rules. Read skills/design.md for WinUI design best practices. Match every dimension, gap, and padding value exactly from the Figma design for pixel-accurate output.';
210
+
varskillRef='Read skills/figma.md for Figma-to-Reactor control mapping, theme tokens, typography, and layout rules. Read skills/design.md for WinUI design best practices. Use exact pixel values from Figma for all widths, heights, gaps, margins, and padding — do NOT round to a grid or substitute MinWidth/MinHeight for fixed dimensions. The goal is pixel-to-pixel accuracy with the Figma design.';
211
211
varwatchCmd='dotnet run --project src/Reactor.Cli -- figma watch "'+url+'" --interval 10';
212
-
varwatchLoop=' After the initial sync, start a live watch loop: run `'+watchCmd+
213
-
'` in a background shell. It emits JSON events to stdout when the Figma file changes.'+
212
+
varrunCmd='dotnet run --project '+csproj;
213
+
varwatchLoop=' After the initial sync, start the app with `'+runCmd+
214
+
'` in a background shell. Then start a live watch loop: run `'+watchCmd+
215
+
'` in another background shell. It emits JSON events to stdout when the Figma file changes.'+
214
216
' When you see an event with "event":"changed", re-fetch the design via get_figma_data MCP tool for file key '+(frameInfo.fileKey||'')+' node '+(frameInfo.nodeId||'')+
215
217
', diff it against the current code, and apply only the changes needed.'+
218
+
' After editing the code, stop the running app process and relaunch it with `'+runCmd+'` so the changes are visible.'+
219
+
' Do NOT rely on dotnet watch hot reload — always restart the app after edits.'+
216
220
' Keep this loop running — do NOT exit after the first sync. You are a live sync agent.';
217
221
218
222
varprompt;
@@ -221,7 +225,7 @@
221
225
' using mur --create '+name+
222
226
', then translate this Figma design into it: '+url+
223
227
'. '+skillRef+
224
-
' After generating the code, run: dotnet watch run --project '+csproj+'.'+
228
+
' After generating the code, launch the app with `'+runCmd+'`.'+
225
229
watchLoop;
226
230
}else{
227
231
if(!csproj){
@@ -234,7 +238,6 @@
234
238
' Apply only the changes needed to bring the code in sync with the design — update text, spacing, sizing, colors, and layout to match.'+
235
239
' Do not regenerate from scratch unless the structure has fundamentally changed.'+
236
240
' '+skillRef+
237
-
' Make sure dotnet watch run --project '+csproj+' is running.'+
238
241
watchLoop;
239
242
}
240
243
@@ -253,7 +256,7 @@
253
256
functioncopyRunCmd(){
254
257
varcsproj=getCsprojPath();
255
258
if(csproj){
256
-
copyToClipboard('dotnet watch run --project '+csproj);
259
+
copyToClipboard('dotnet watch --non-interactive run --project '+csproj);
Copy file name to clipboardExpand all lines: tools/figma-plugin/src/ui.html
+9-6Lines changed: 9 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -207,12 +207,16 @@
207
207
varcsproj=getCsprojPath();
208
208
varname=getProjectName();
209
209
210
-
varskillRef='Read skills/figma.md for Figma-to-Reactor control mapping, theme tokens, typography, and layout rules. Read skills/design.md for WinUI design best practices. Match every dimension, gap, and padding value exactly from the Figma design for pixel-accurate output.';
210
+
varskillRef='Read skills/figma.md for Figma-to-Reactor control mapping, theme tokens, typography, and layout rules. Read skills/design.md for WinUI design best practices. Use exact pixel values from Figma for all widths, heights, gaps, margins, and padding — do NOT round to a grid or substitute MinWidth/MinHeight for fixed dimensions. The goal is pixel-to-pixel accuracy with the Figma design.';
211
211
varwatchCmd='dotnet run --project src/Reactor.Cli -- figma watch "'+url+'" --interval 10';
212
-
varwatchLoop=' After the initial sync, start a live watch loop: run `'+watchCmd+
213
-
'` in a background shell. It emits JSON events to stdout when the Figma file changes.'+
212
+
varrunCmd='dotnet run --project '+csproj;
213
+
varwatchLoop=' After the initial sync, start the app with `'+runCmd+
214
+
'` in a background shell. Then start a live watch loop: run `'+watchCmd+
215
+
'` in another background shell. It emits JSON events to stdout when the Figma file changes.'+
214
216
' When you see an event with "event":"changed", re-fetch the design via get_figma_data MCP tool for file key '+(frameInfo.fileKey||'')+' node '+(frameInfo.nodeId||'')+
215
217
', diff it against the current code, and apply only the changes needed.'+
218
+
' After editing the code, stop the running app process and relaunch it with `'+runCmd+'` so the changes are visible.'+
219
+
' Do NOT rely on dotnet watch hot reload — always restart the app after edits.'+
216
220
' Keep this loop running — do NOT exit after the first sync. You are a live sync agent.';
217
221
218
222
varprompt;
@@ -221,7 +225,7 @@
221
225
' using mur --create '+name+
222
226
', then translate this Figma design into it: '+url+
223
227
'. '+skillRef+
224
-
' After generating the code, run: dotnet watch run --project '+csproj+'.'+
228
+
' After generating the code, launch the app with `'+runCmd+'`.'+
225
229
watchLoop;
226
230
}else{
227
231
if(!csproj){
@@ -234,7 +238,6 @@
234
238
' Apply only the changes needed to bring the code in sync with the design — update text, spacing, sizing, colors, and layout to match.'+
235
239
' Do not regenerate from scratch unless the structure has fundamentally changed.'+
236
240
' '+skillRef+
237
-
' Make sure dotnet watch run --project '+csproj+' is running.'+
238
241
watchLoop;
239
242
}
240
243
@@ -253,7 +256,7 @@
253
256
functioncopyRunCmd(){
254
257
varcsproj=getCsprojPath();
255
258
if(csproj){
256
-
copyToClipboard('dotnet watch run --project '+csproj);
259
+
copyToClipboard('dotnet watch --non-interactive run --project '+csproj);
0 commit comments