Skip to content

Commit ea29cc4

Browse files
authored
Merge pull request #91 from karkarl/skills/design-guidance-update
Update skills/design.md with ReactorGallery design guidance
2 parents 0dca8aa + 77922e3 commit ea29cc4

1 file changed

Lines changed: 193 additions & 31 deletions

File tree

skills/design.md

Lines changed: 193 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,78 @@ Hardcoded colors are acceptable only for:
5656
- One-off decorative elements that intentionally ignore theming (e.g., brand logos)
5757
- Explicit hit-test targets (`Background("#00000000")` for transparent hit areas)
5858

59-
#### Common Theme Tokens
59+
#### Theme Token Reference
60+
61+
**Text:**
62+
63+
| Token | WinUI Resource | Purpose |
64+
|-------|---------------|---------|
65+
| `Theme.PrimaryText` | `TextFillColorPrimaryBrush` | Primary body text, titles, and labels |
66+
| `Theme.SecondaryText` | `TextFillColorSecondaryBrush` | Captions, subtitles, and supplementary info |
67+
| `Theme.TertiaryText` | `TextFillColorTertiaryBrush` | Placeholder text and disabled secondary content |
68+
| `Theme.DisabledText` | `TextFillColorDisabledBrush` | Text in disabled controls or inactive states |
69+
| `Theme.AccentText` | `AccentTextFillColorPrimaryBrush` | Hyperlinks, accent-colored labels, and interactive text |
70+
71+
**Accent fill:**
72+
73+
| Token | WinUI Resource | Purpose |
74+
|-------|---------------|---------|
75+
| `Theme.Accent` | `AccentFillColorDefaultBrush` | Primary accent buttons and controls at rest |
76+
| `Theme.AccentSecondary` | `AccentFillColorSecondaryBrush` | Accent button hover state |
77+
| `Theme.AccentTertiary` | `AccentFillColorTertiaryBrush` | Accent button pressed state |
78+
| `Theme.AccentDisabled` | `AccentFillColorDisabledBrush` | Disabled accent controls |
79+
80+
**Control fill:**
81+
82+
| Token | WinUI Resource | Purpose |
83+
|-------|---------------|---------|
84+
| `Theme.ControlFill` | `ControlFillColorDefaultBrush` | Default rest state for standard controls |
85+
| `Theme.ControlFillSecondary` | `ControlFillColorSecondaryBrush` | Hover state of standard controls |
86+
| `Theme.ControlFillTertiary` | `ControlFillColorTertiaryBrush` | Pressed state of standard controls |
87+
| `Theme.ControlFillDisabled` | `ControlFillColorDisabledBrush` | Disabled state of standard controls |
88+
| `Theme.ControlFillInputActive` | `ControlFillColorInputActiveBrush` | Active/focused text input field backgrounds |
89+
90+
**Surfaces & backgrounds:**
91+
92+
| Token | WinUI Resource | Purpose |
93+
|-------|---------------|---------|
94+
| `Theme.SolidBackground` | `SolidBackgroundFillColorBaseBrush` | App and page-level background (base layer) |
95+
| `Theme.CardBackground` | `CardBackgroundFillColorDefaultBrush` | Card and elevated surface backgrounds |
96+
| `Theme.LayerFill` | `LayerFillColorDefaultBrush` | Flyout, dialog, and pane backgrounds |
97+
| `Theme.SubtleFill` | `SubtleFillColorSecondaryBrush` | Subtle control highlights and section backgrounds |
98+
| `Theme.SmokeFill` | `SmokeFillColorDefaultBrush` | Semi-transparent overlay behind modal dialogs |
99+
100+
**Stroke & border:**
101+
102+
| Token | WinUI Resource | Purpose |
103+
|-------|---------------|---------|
104+
| `Theme.CardStroke` | `CardStrokeColorDefaultBrush` | Borders on cards and elevated containers |
105+
| `Theme.SurfaceStroke` | `SurfaceStrokeColorDefaultBrush` | Borders on flyouts, dialogs, and pane surfaces |
106+
| `Theme.DividerStroke` | `DividerStrokeColorDefaultBrush` | Horizontal or vertical dividers between content |
107+
| `Theme.ControlStroke` | `ControlStrokeColorDefaultBrush` | Borders on interactive controls at rest |
108+
| `Theme.ControlStrokeSecondary` | `ControlStrokeColorSecondaryBrush` | Bottom edge of controls for depth effect |
109+
110+
**System signal:**
111+
112+
| Token | WinUI Resource | Purpose |
113+
|-------|---------------|---------|
114+
| `Theme.SystemAttention` | `SystemFillColorAttentionBrush` | Informational indicators and badges |
115+
| `Theme.SystemSuccess` | `SystemFillColorSuccessBrush` | Success states and confirmations |
116+
| `Theme.SystemCaution` | `SystemFillColorCautionBrush` | Warning states and cautionary indicators |
117+
| `Theme.SystemCritical` | `SystemFillColorCriticalBrush` | Error states and critical alerts |
118+
| `Theme.SystemNeutral` | `SystemFillColorNeutralBrush` | Neutral status indicators |
119+
| `Theme.SystemSolidNeutral` | `SystemFillColorSolidNeutralBrush` | Solid neutral fill for icons and non-text indicators |
120+
121+
**System signal backgrounds:**
60122

61123
| Token | WinUI Resource | Purpose |
62124
|-------|---------------|---------|
63-
| `Theme.PrimaryText` | `TextFillColorPrimaryBrush` | Primary text |
64-
| `Theme.SecondaryText` | `TextFillColorSecondaryBrush` | Secondary text |
65-
| `Theme.TertiaryText` | `TextFillColorTertiaryBrush` | Placeholder text |
66-
| `Theme.DisabledText` | `TextFillColorDisabledBrush` | Disabled text |
67-
| `Theme.Accent` | `AccentFillColorDefaultBrush` | Accent fills |
68-
| `Theme.AccentSecondary` | `AccentFillColorSecondaryBrush` | Accent hover |
69-
| `Theme.AccentTertiary` | `AccentFillColorTertiaryBrush` | Accent pressed |
70-
| `Theme.ControlFill` | `ControlFillColorDefaultBrush` | Control backgrounds |
71-
| `Theme.CardBackground` | `CardBackgroundFillColorDefaultBrush` | Card backgrounds |
72-
| `Theme.LayerFill` | `LayerFillColorDefaultBrush` | Layer backgrounds |
73-
| `Theme.SolidBackground` | `SolidBackgroundFillColorBaseBrush` | Solid backgrounds |
74-
| `Theme.SubtleFill` | `SubtleFillColorTransparentBrush` | Subtle/transparent fills |
125+
| `Theme.SystemAttentionBackground` | `SystemFillColorAttentionBackgroundBrush` | Background for attention/info banners |
126+
| `Theme.SystemSuccessBackground` | `SystemFillColorSuccessBackgroundBrush` | Background for success banners and info bars |
127+
| `Theme.SystemCautionBackground` | `SystemFillColorCautionBackgroundBrush` | Background for warning banners and info bars |
128+
| `Theme.SystemCriticalBackground` | `SystemFillColorCriticalBackgroundBrush` | Background for error banners and info bars |
129+
| `Theme.SystemNeutralBackground` | `SystemFillColorNeutralBackgroundBrush` | Background for neutral status banners |
130+
| `Theme.SystemSolidAttention` | `SystemFillColorSolidAttentionBackgroundBrush` | Solid background for high-contrast attention surfaces |
75131

76132
For any WinUI resource not exposed as a named token, use `Theme.Ref("ResourceKeyBrush")`.
77133

@@ -178,31 +234,49 @@ Use the predefined text factories or WinUI style tokens. Never set `FontSize` an
178234
| `SubHeading("text")` | 20px | 600 | Section headers, card titles |
179235
| `Heading("text")` | 28px | 700 | Page titles |
180236

181-
**WinUI type ramp (via `.Set()`):**
237+
**Font weight helpers:**
238+
239+
| Helper | Weight | Use Case |
240+
|--------|--------|----------|
241+
| `.SemiBold()` | 600 | Emphasized body text, inline labels, field headers |
242+
| `.Bold()` | 700 | Reserved for `Heading()` page titles — avoid elsewhere |
243+
244+
```csharp
245+
TextBlock("Important label").SemiBold()
246+
TextBlock("Page Title").Bold()
247+
```
248+
249+
**WinUI type ramp (via `.ApplyStyle()`):**
182250

183-
| Style | Size | Weight |
184-
|-------|------|--------|
185-
| `CaptionTextBlockStyle` | 12px | Regular |
186-
| `BodyTextBlockStyle` | 14px | Regular |
187-
| `BodyStrongTextBlockStyle` | 14px | Semibold |
188-
| `BodyLargeTextBlockStyle` | 18px | Regular |
189-
| `SubtitleTextBlockStyle` | 20px | Semibold |
190-
| `TitleTextBlockStyle` | 28px | Semibold |
191-
| `TitleLargeTextBlockStyle` | 40px | Semibold |
192-
| `DisplayTextBlockStyle` | 68px | Semibold |
251+
| Style | Size | Weight | Recommendation |
252+
|-------|------|--------|----------------|
253+
| `CaptionTextBlockStyle` | 12px | Regular | Secondary labels, timestamps, footnotes |
254+
| `BodyTextBlockStyle` | 14px | Regular | Default body text, paragraphs, descriptions |
255+
| `BodyStrongTextBlockStyle` | 14px | Semibold | Emphasized body text, inline labels |
256+
| `BodyLargeTextBlockStyle` | 18px | Regular | Prominent body text |
257+
| `SubtitleTextBlockStyle` | 20px | Semibold | Section headings, card group labels |
258+
| `TitleTextBlockStyle` | 28px | Semibold | Page titles, dialog headings |
259+
| `TitleLargeTextBlockStyle` | 40px | Semibold | Primary page titles on feature pages |
260+
| `DisplayTextBlockStyle` | 68px | Semibold | Hero banners — one per page at most |
193261

194-
For sizes not covered by the factories, apply a WinUI style:
262+
For sizes not covered by the factories, use `.ApplyStyle()` to apply WinUI text block styles. This sets size, weight, line height, and optical sizing in one call:
195263

196264
```csharp
197-
// Correct: apply WinUI style for BodyLarge
198-
TextBlock("Prominent text").Set(tb => tb.Style =
199-
(Style)Application.Current.Resources["BodyLargeTextBlockStyle"])
265+
// Preferred: .ApplyStyle() for WinUI styles
266+
TextBlock("Title").ApplyStyle("TitleTextBlockStyle")
267+
TextBlock("Subtitle").ApplyStyle("SubtitleTextBlockStyle")
268+
TextBlock("Body Strong").ApplyStyle("BodyStrongTextBlockStyle")
269+
TextBlock("Caption").ApplyStyle("CaptionTextBlockStyle")
200270

201271
// Also correct: use the Reactor factories for common sizes
202272
Heading("Page Title")
203273
SubHeading("Section")
204274
Caption("Fine print")
205275

276+
// Escape hatch: .Set() for styles not exposed via .ApplyStyle()
277+
TextBlock("Prominent text").Set(tb => tb.Style =
278+
(Style)Application.Current.Resources["BodyLargeTextBlockStyle"])
279+
206280
// Wrong: raw font properties for standard UI text
207281
TextBlock("Title").FontSize(28).FontWeight(new FontWeight(700))
208282
```
@@ -230,7 +304,19 @@ See [typography-and-colors.md](design-docs/typography-and-colors.md) for the ful
230304

231305
#### 4px Grid
232306

233-
Use multiples of 4 for all margins, padding, and sizing values.
307+
Use multiples of 4 for all margins, padding, and sizing values. The spacing scale is built on a 4px base unit:
308+
309+
| Value | Name | Usage |
310+
|-------|------|-------|
311+
| 0px | Flush | No gap between elements |
312+
| 2px | Hairline | Tight spacing between related inline items |
313+
| 4px | Compact | Icon-to-label gaps and small control internals |
314+
| 8px | Standard | Default gap between sibling controls |
315+
| 12px | Relaxed | Padding inside cards and grouped sections |
316+
| 16px | Spacious | Between distinct content sections |
317+
| 24px | Section | Major section boundaries and card padding |
318+
| 36px | Page | Page-level margins around content |
319+
| 48px | Hero | Large spacing for hero areas and visual breaks |
234320

235321
```csharp
236322
// Correct: multiples of 4
@@ -243,12 +329,68 @@ VStack(5, children).Padding(15)
243329
Border(child).Margin(3)
244330
```
245331

332+
#### Margin vs Padding
333+
334+
**Margin** pushes an element away from its neighbors. It works on every Reactor element.
335+
336+
**Padding** adds space between a container's edge and its content. It only works on `Border` and `Control`-based elements (`Button`, `TextField`, etc.). Layout panels like `VStack`, `HStack`, and `Grid` do not support `.Padding()` — wrap content in a `Border` if you need inner padding on a stack.
337+
338+
| Element | `.Margin()` | `.Padding()` |
339+
|---------|-------------|-------------|
340+
| `Border` |||
341+
| `Button` |||
342+
| `TextField` |||
343+
| `TextBlock` |||
344+
| `VStack` |||
345+
| `HStack` |||
346+
| `Grid` |||
347+
| `Image` |||
348+
349+
```csharp
350+
// Margin — works on ALL elements
351+
TextBlock("Hello").Margin(8)
352+
VStack(children).Margin(16)
353+
Border(child).Margin(12)
354+
355+
// Padding — only on Border and Control (Button, TextField, etc.)
356+
Border(child).Padding(16) // ✓ works
357+
Button("Go").Padding(12) // ✓ works
358+
359+
// VStack/HStack don't support Padding — wrap in Border instead:
360+
Border(
361+
VStack(8, items)
362+
).Padding(16) // ✓ padding applied to the Border
363+
```
364+
365+
Both `.Margin()` and `.Padding()` accept three overloads:
366+
367+
```csharp
368+
// Uniform — same on all sides
369+
element.Margin(16)
370+
371+
// Horizontal, Vertical
372+
element.Margin(24, 8)
373+
374+
// Per-side: left, top, right, bottom
375+
element.Margin(4, 8, 16, 24)
376+
```
377+
246378
#### Corner Radius
247379

248-
Use system values — `ControlCornerRadius` (4px) for controls and `OverlayCornerRadius` (8px) for overlays:
380+
Use system values — `ControlCornerRadius` (4px) for controls and `OverlayCornerRadius` (8px) for overlays.
381+
382+
WinUI provides two corner radius theme resources. Use `ThemeResource.CornerRadius()` to resolve the system values at render time, ensuring your UI adapts if these values are customized:
249383

250384
```csharp
251-
// Correct: system corner radius values
385+
// Preferred: resolve system values at render time
386+
var controlRadius = ThemeResource.CornerRadius("ControlCornerRadius");
387+
var overlayRadius = ThemeResource.CornerRadius("OverlayCornerRadius");
388+
389+
// Apply to elements
390+
Border(child).CornerRadius(controlRadius.TopLeft) // controls, buttons, cards
391+
Border(dialog).CornerRadius(overlayRadius.TopLeft) // dialogs, flyouts, menus
392+
393+
// Also acceptable: hardcoded system values
252394
Border(child).CornerRadius(4) // ControlCornerRadius equivalent
253395
Border(child).CornerRadius(8) // OverlayCornerRadius equivalent
254396
@@ -260,6 +402,26 @@ Border(child).CornerRadius(3)
260402
Border(child).CornerRadius(6)
261403
```
262404

405+
**Mixed radii for nested surfaces:** When nesting controls inside overlay containers, the outer container uses `OverlayCornerRadius` while inner controls use `ControlCornerRadius`:
406+
407+
```csharp
408+
var cr = ThemeResource.CornerRadius("ControlCornerRadius");
409+
var or = ThemeResource.CornerRadius("OverlayCornerRadius");
410+
411+
// Dialog with control-radius inner elements
412+
Border(
413+
VStack(12,
414+
TextField("", placeholder: "Username").CornerRadius(cr.TopLeft),
415+
Button("Sign In", onClick)
416+
.Background(Theme.Accent)
417+
.CornerRadius(cr.TopLeft)
418+
).Margin(24)
419+
)
420+
.Background(Theme.LayerFill)
421+
.WithBorder(Theme.SurfaceStroke)
422+
.CornerRadius(or.TopLeft) // outer overlay radius
423+
```
424+
263425
#### Sizing
264426

265427
```csharp

0 commit comments

Comments
 (0)