
Winui Design
- 157 installs
- 373 repo stars
- Updated August 3, 2026
- microsoft/win-dev-skills
winui-design is an agent skill for WinUI 3 UI planning, winui-search.exe control lookup, and Fluent XAML theming and correctness.
About
The winui-design skill guides WinUI 3 UI planning and XAML correctness for Fluent Design apps. Before writing XAML, agents batch-search features with the bundled winui-search.exe tool indexing WinUI Gallery controls, Windows Community Toolkit scenarios, and platform patterns, then fetch canonical samples with get before coding. UI planning maps app types to anchor controls like NavigationView, TabView, or TreeView, selects inputs and feedback controls, sizes windows with a rubric because WinUI 3 lacks SizeToContent, and avoids anti-patterns such as floating cards or hardcoded colors. XAML correctness covers ThemeResource and StaticResource brush rules, high contrast system color limits, typography styles instead of raw FontSize, 4px spacing grid, acrylic pairings, and data binding with x:Bind plus UpdateSourceTrigger=PropertyChanged on TextBox two-way binds. Accessibility requires AutomationProperties on icon-only controls and correct attached property setters in code-behind. Reference files point to approved brushes, theme resources, and review checklists. Use when designing new WinUI pages, converting from WPF or web, reviewing XAML, or fixing theme issues.
- Requires winui-search.exe lookups before writing any XAML.
- Maps app types to anchor controls and Fluent layout patterns.
- Window sizing rubric with DPI-aware AppWindow.Resize examples.
- Enforces ThemeResource brushes, typography styles, and 4px spacing grid.
- Covers x:Bind binding rules, accessibility, and high contrast constraints.
Winui Design by the numbers
- 157 all-time installs (skills.sh)
- +26 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #999 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
winui-design capabilities & compatibility
- Capabilities
- winui search.exe control catalogue lookup · app type to anchor control mapping · dpi aware window sizing rubric · themeresource and high contrast brush rules · x:bind and accessibility xaml patterns
- Use cases
- ui design · frontend
What winui-design says it does
Before picking controls, search the catalogue.
npx skills add https://github.com/microsoft/win-dev-skills --skill winui-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 157 |
|---|---|
| repo stars | ★ 373 |
| Last updated | August 3, 2026 |
| Repository | microsoft/win-dev-skills ↗ |
How do I design a WinUI 3 page with correct controls, theming, spacing, and XAML patterns?
Plan WinUI 3 layouts, select controls via winui-search.exe, and enforce Fluent theming, typography, spacing, and XAML correctness.
Who is it for?
Developers designing or reviewing WinUI 3 XAML who need Fluent control selection and correctness rules.
Skip if: Skip for non-WinUI platforms, backend logic, or runtime UI testing without design review needs.
When should I use this skill?
User designs WinUI pages, reviews XAML, fixes theme issues, or converts from WPF or web UI.
What you get
A Fluent-aligned WinUI layout with canonical control samples, correct brushes, typography, and accessible XAML.
Files
UI Planning
Before picking controls, search the catalogue. This skill shipswinui-search.exealongside thisSKILL.md. It indexes 100+ WinUI Gallery controls, every Windows Community Toolkit scenario, and a curated set of platform integration patterns (JumpList, Share, file pickers, drag-drop). Use it to ground every control choice in a real shipping sample before writing any XAML — this is the difference between guessing property names and copying canonical code.
>
```powershell
.\winui-search.exe search "<feature 1>" "<feature 2>" ... # batch one focused query per feature
.\winui-search.exe get <id 1> <id 2> ... # batch up to 3 IDs — full XAML + C# + pitfall notes
.\winui-search.exe list # browse all patterns (heavy — prefer search)
.\winui-search.exe update # force refresh now
```
>
Workflow: in onesearchcall, list every feature you need for the current page (one focused query per feature, not a bag of keywords) → from each shortlist pick the best ID → grab full code withget(batch up to 3 IDs per call) → then write XAML using those samples as reference. Do NOT interleave searching with coding — front-load all lookups, then code. BM25 rewards focused per-query phrasing, so keep each query about one control or pattern.
Step 1: Identify App Type and Anchor Control
| App Type | Anchor Control | Reference App |
|---|---|---|
| Settings / config tool | NavigationView Left + SettingsCard | Windows Settings |
| Document / session editor | TabView + full-width content | Windows Terminal, Notepad |
| Hierarchical browser | TreeView + ListView + BreadcrumbBar | File Explorer |
| Developer tool / dashboard | NavigationView + card layout | Dev Home |
| Single-purpose utility | Mode switcher + compact grid | Calculator |
Step 2: Map Requirements to Controls
Navigation: 2-7 sections → NavigationView; document tabs → TabView; breadcrumb trail → BreadcrumbBar; 2-3 modes → SelectorBar.
Data display: Vertical list → ListView; tiles/grid → GridView or ItemsRepeater + UniformGridLayout; hierarchy → TreeView; tabular → ListView with Grid column headers; master-detail → ListView + detail Grid.
Input: Text → TextBox; number → NumberBox; search → AutoSuggestBox; date → CalendarDatePicker; boolean → ToggleSwitch; pick one from 2-3 → RadioButtons; pick one from 4+ → ComboBox.
Feedback: Blocking decision → ContentDialog; contextual action → Flyout/MenuFlyout; onboarding → TeachingTip; inline status → InfoBar; system notification → AppNotification.
Step 3: Plan Layout
- Content fills the window — no floating cards on empty backgrounds
Gridfor structure,StackPanelonly for simple stacking of few items- Sidebar: fixed 300-360px width; main content:
Width="*"with 24px padding - Status bar:
Gridrow at bottom; toolbar:CommandBaror title bar buttons
Step 4: Size the Window to the App
WinUI 3 has no `SizeToContent`. Without an explicit size, Windows defaults the main window to ~1024×768 — oversized for most utilities. Size the window in `MainWindow`'s constructor; derive from the layout, not a generic.
Rubric. Width = widest row + 48 padding (24 each side), rounded up to nearest 20. Height = 32 (titlebar) + Σ(row heights) + Σ(spacing) + 48 padding, rounded up to 20. Round up — clipped content is a worse failure than a slightly-wide window.
Sanity check (ranges, not targets — derive yours from the rubric):
- Single-purpose utility → ~440–560 wide
- Form / single-page tool → ~600–800 wide, ~640–800 tall
- Multi-pane (nav + content) → ~1100–1300 wide, ~720–840 tall
- Document / canvas / media editor → 1280+ wide
If your derived number is well below its range, you missed a row — re-check.
AppWindow.Resize takes physical pixels, not DIPs — multiply by the monitor's DPI scale:
using Microsoft.UI;
using Microsoft.UI.Windowing;
using System.Runtime.InteropServices;
using Windows.Graphics;
public sealed partial class MainWindow : Window
{
[DllImport("user32.dll")]
private static extern uint GetDpiForWindow(IntPtr hWnd);
public MainWindow()
{
InitializeComponent();
var hwnd = Win32Interop.GetWindowFromWindowId(AppWindow.Id);
var scale = GetDpiForWindow(hwnd) / 96.0;
AppWindow.Resize(new SizeInt32((int)(460 * scale), (int)(860 * scale)));
}
}XamlRoot.RasterizationScale is null in the ctor and stale after AppWindow.Move, so [DllImport] is the cleanest path. Don't try to size the window by setting Width/Height on the root Grid — that clips content, not the window.
If the user asks for UI validation, see winui-ui-testing Step 3.5 to verify the rubric against the visual checklist.
Step 5: Design Anti-Patterns
| ❌ Don't | ✅ Do Instead |
|---|---|
| Centered floating card on background | Content fills window with padding |
| Custom pill/segment tab switcher | NavigationView Top or SelectorBar |
| Equal-width 50/50 column split | Fixed sidebar (300-360px) + flexible main |
Hardcoded colors (#FF0000) | {ThemeResource} brushes |
ScrollViewer around ListView | ListView has built-in scrolling |
| Custom ControlTemplate for standard controls | Built-in controls with style overrides |
XAML Correctness
Theming Rules
- `{ThemeResource BrushName}` at usage sites — updates on theme change
- `{StaticResource}` with
ResourceKeyredirects inside theme dictionaries — zero allocation - `ResourceKey` must end in `Brush` (target the
SolidColorBrush, not theColor) - Always define all three variants:
x:Key="Light",x:Key="Dark",x:Key="HighContrast"— never usex:Key="Default" - Verify runtime theme switching:
{ThemeResource}updates;{StaticResource}does not
<!-- Correct: StaticResource redirect in theme dictionary -->
<StaticResource x:Key="MyBrush" ResourceKey="ControlFillColorDefaultBrush" />
<!-- Wrong: inline SolidColorBrush allocates new object -->
<SolidColorBrush x:Key="MyBrush" Color="{StaticResource ControlFillColorDefault}" />High Contrast
Only 8 system color brushes allowed in HC dictionaries:
| Background | Foreground | Use Case |
|---|---|---|
SystemColorWindowColorBrush | SystemColorWindowTextColorBrush | General content |
SystemColorHighlightColorBrush | SystemColorHighlightTextColorBrush | Selected/hover |
SystemColorButtonFaceColorBrush | SystemColorButtonTextColorBrush | Buttons |
SystemColorWindowColorBrush | SystemColorHotlightColorBrush | Hyperlinks |
SystemColorWindowColorBrush | SystemColorGrayTextColorBrush | Disabled content |
HC prohibitions: No hardcoded colors, no opacity, no accent colors, no regular WinUI brushes, no SystemColor* in Light/Dark dicts. Use empty HC dict when WinUI defaults suffice. Set HighContrastAdjustment = None at app level.
Typography — Use Styles, Not Raw FontSize
| Style | Size | Weight | Use For |
|---|---|---|---|
CaptionTextBlockStyle | 12px | Regular | Small labels, timestamps |
BodyTextBlockStyle | 14px | Regular | Body text (default — don't set explicitly) |
BodyStrongTextBlockStyle | 14px | Semibold | Emphasized body text |
SubtitleTextBlockStyle | 20px | Semibold | Section headers, card titles |
TitleTextBlockStyle | 28px | Semibold | Page titles |
TitleLargeTextBlockStyle | 40px | Semibold | Large feature titles |
DisplayTextBlockStyle | 68px | Semibold | Hero text |
Use SemiBold, never Bold. Minimum 12px. BasedOn styles must not re-declare inherited properties.
Spacing and Layout
- 4px grid: margins, padding, sizes must be multiples of 4 (4, 8, 12, 16, 24, 32, 48)
ControlCornerRadius(4px) for controls,OverlayCornerRadius(8px) for overlays — never hardcodeRowSpacing/ColumnSpacinginstead of spacer elementsMinHeight/MinWidthinstead of fixed sizing- No negative margins
Remove Defaults
Don't set WinUI default values — blocks future updates:
BodyTextBlockStyleon TextBlock,TextFillColorPrimaryBrushforeground,TextWrapping="NoWrap",Padding="0",Margin="0"
Acrylic Pairings
| Surface | Background | Border |
|---|---|---|
| Flyouts, tooltips | AcrylicBackgroundFillColorDefaultBrush | SurfaceStrokeColorFlyoutBrush |
| UI surfaces | AcrylicBackgroundFillColorBaseBrush | SurfaceStrokeColorDefaultBrush |
Use BackgroundSizing="InnerBorderEdge" on bordered acrylic. ThemeShadow requires Translation="0,0,32" and 12px parent padding.
Data Binding
{x:Bind}over{Binding}, explicitMode=OneWay/TwoWay,x:DataTypeonDataTemplate- TextBox `x:Bind TwoWay` — always add `UpdateSourceTrigger=PropertyChanged` so the ViewModel updates on each keystroke instead of waiting for
LostFocus. Without it, UIA automation (set-value) and programmatic changes won't commit to the ViewModel.
<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />- Commands over Click/Tapped handlers (MVVM)
VisualStateManagerfor visual property changes, not code-behind- No
IValueConverter— preferx:Bindwith functions
Bool negation and Visibility functions — define static methods in code-behind:
// In code-behind (e.g., MainPage.xaml.cs)
public static Visibility BoolToVisibility(bool value) =>
value ? Visibility.Visible : Visibility.Collapsed;
public static Visibility InvertBoolToVisibility(bool value) =>
value ? Visibility.Collapsed : Visibility.Visible;
public static bool IsNotBusy(bool isLoading) => !isLoading;<!-- Usage in XAML -->
Visibility="{x:Bind local:MainPage.BoolToVisibility(ViewModel.IsLoading), Mode=OneWay}"
IsEnabled="{x:Bind local:MainPage.IsNotBusy(ViewModel.IsLoading), Mode=OneWay}"❌ NEVER use Converter={x:Null} — it crashes at runtime.
Accessibility
AutomationProperties.Nameon icon-only controlsAutomationProperties.AutomationIdon all interactive controls- Semantic controls (
Button,HyperlinkButton) — not clickableBorder/TextBlock DividerStrokeColorDefaultBrushfor dividers
Setting attached properties in code-behind — WinUI attached properties use static methods, NOT object initializer syntax:
using Microsoft.UI.Xaml.Automation; // required for AutomationProperties
// ❌ WRONG — object initializer doesn't work for attached properties
var btn = new Button { AutomationProperties = { AutomationId = "BtnSave" } };
// ✅ CORRECT — static setter method
var btn = new Button { Content = "Save" };
AutomationProperties.SetAutomationId(btn, "BtnSave");
AutomationProperties.SetName(btn, "Save button");
Grid.SetRow(btn, 1);
Grid.SetColumn(btn, 0);
ToolTipService.SetToolTip(btn, "Save the current document");Formatting
- Self-closing tags for childless elements
- Styles referenced with
{StaticResource}not{ThemeResource} - No
pxsuffix on numeric values, no commented-out XAML - Consistent attribute order: x:Name, AutomationProperties, layout, content, style
References
| File | Read when... |
|---|---|
references/approved-brushes.md | Looking up correct WinUI brush names and usage rules |
references/theme-aware-resources.md | Implementing ThemeResource/StaticResource, High Contrast, acrylic pairings |
references/code-review-checklist.md | Reviewing XAML changes for correctness |
references/pr-review-patterns.md | Applying concrete review fixes and patterns |
references/control-styles.md | Customizing built-in control styles |
references/typography-and-spacing.md | Detailed type ramp, spacing grid, and sizing examples |
references/colors-and-materials.md | Theme brush catalog, Mica/Acrylic surface pairings, material usage |
references/iconography-and-motion.md | Icon guidelines, animation patterns, connected animations |
Approved Brushes
When reviewing XAML, verify that every brush is either: 1. A custom brush with explicit Light, Dark, and HighContrast theme dictionaries, OR 2. One of the approved brushes listed below.
If neither, request the author to switch to an approved brush or provide the complete theme-aware resource set.
Usage
{ThemeResource BrushName}at usage sites (updates on theme change){StaticResource BrushName}inside theme dictionaries- Names ending in
BrushareSolidColorBrushresources; names without areColorresources - Prefer the
Brushkey when assigning to Foreground/Background
Common System Brushes (Quick Reference)
| Resource | Purpose |
|---|---|
TextFillColorPrimaryBrush | Primary text |
TextFillColorSecondaryBrush | Secondary text |
TextFillColorTertiaryBrush | Tertiary / placeholder text |
TextFillColorDisabledBrush | Disabled text |
AccentFillColorDefaultBrush | Accent color fills |
ControlFillColorDefaultBrush | Control backgrounds |
CardBackgroundFillColorDefaultBrush | Card backgrounds |
LayerFillColorDefaultBrush | Layer backgrounds |
Text Fill
TextFillColorPrimary / TextFillColorPrimaryBrush TextFillColorSecondary / TextFillColorSecondaryBrush TextFillColorTertiary / TextFillColorTertiaryBrush TextFillColorDisabled / TextFillColorDisabledBrush TextFillColorInverse / TextFillColorInverseBrush AccentTextFillColorPrimary / AccentTextFillColorPrimaryBrush AccentTextFillColorSecondary / AccentTextFillColorSecondaryBrush AccentTextFillColorTertiary / AccentTextFillColorTertiaryBrush AccentTextFillColorDisabled / AccentTextFillColorDisabledBrush TextOnAccentFillColorSelectedText / TextOnAccentFillColorSelectedTextBrush TextOnAccentFillColorPrimary / TextOnAccentFillColorPrimaryBrush TextOnAccentFillColorSecondary / TextOnAccentFillColorSecondaryBrush TextOnAccentFillColorDisabled / TextOnAccentFillColorDisabledBrush
Control Fill
ControlFillColorDefault / ControlFillColorDefaultBrush ControlFillColorSecondary / ControlFillColorSecondaryBrush ControlFillColorTertiary / ControlFillColorTertiaryBrush ControlFillColorQuarternary / ControlFillColorQuarternaryBrush ControlFillColorDisabled / ControlFillColorDisabledBrush ControlFillColorTransparent / ControlFillColorTransparentBrush ControlFillColorInputActive / ControlFillColorInputActiveBrush ControlStrongFillColorDefault / ControlStrongFillColorDefaultBrush ControlStrongFillColorDisabled / ControlStrongFillColorDisabledBrush ControlSolidFillColorDefault / ControlSolidFillColorDefaultBrush
Subtle Fill
SubtleFillColorTransparent / SubtleFillColorTransparentBrush SubtleFillColorSecondary / SubtleFillColorSecondaryBrush SubtleFillColorTertiary / SubtleFillColorTertiaryBrush SubtleFillColorDisabled / SubtleFillColorDisabledBrush
Control Alt Fill
ControlAltFillColorTransparent / ControlAltFillColorTransparentBrush ControlAltFillColorSecondary / ControlAltFillColorSecondaryBrush ControlAltFillColorTertiary / ControlAltFillColorTertiaryBrush ControlAltFillColorQuarternary / ControlAltFillColorQuarternaryBrush ControlAltFillColorDisabled / ControlAltFillColorDisabledBrush
Control On Image Fill
ControlOnImageFillColorDefault / ControlOnImageFillColorDefaultBrush ControlOnImageFillColorSecondary / ControlOnImageFillColorSecondaryBrush ControlOnImageFillColorTertiary / ControlOnImageFillColorTertiaryBrush ControlOnImageFillColorDisabled / ControlOnImageFillColorDisabledBrush
Accent Fill
AccentFillColorSelectedTextBackground / AccentFillColorSelectedTextBackgroundBrush AccentFillColorDefault / AccentFillColorDefaultBrush AccentFillColorSecondary / AccentFillColorSecondaryBrush AccentFillColorTertiary / AccentFillColorTertiaryBrush AccentFillColorDisabled / AccentFillColorDisabledBrush
Stroke
ControlStrokeColorDefault / ControlStrokeColorDefaultBrush ControlStrokeColorSecondary / ControlStrokeColorSecondaryBrush ControlStrokeColorOnAccentDefault / ControlStrokeColorOnAccentDefaultBrush ControlStrokeColorOnAccentSecondary / ControlStrokeColorOnAccentSecondaryBrush ControlStrokeColorOnAccentTertiary / ControlStrokeColorOnAccentTertiaryBrush ControlStrokeColorOnAccentDisabled / ControlStrokeColorOnAccentDisabledBrush ControlStrokeColorForStrongFillWhenOnImage / ControlStrokeColorForStrongFillWhenOnImageBrush CardStrokeColorDefault / CardStrokeColorDefaultBrush CardStrokeColorDefaultSolid / CardStrokeColorDefaultSolidBrush ControlStrongStrokeColorDefault / ControlStrongStrokeColorDefaultBrush ControlStrongStrokeColorDisabled / ControlStrongStrokeColorDisabledBrush SurfaceStrokeColorDefault / SurfaceStrokeColorDefaultBrush SurfaceStrokeColorFlyout / SurfaceStrokeColorFlyoutBrush SurfaceStrokeColorInverse / SurfaceStrokeColorInverseBrush DividerStrokeColorDefault / DividerStrokeColorDefaultBrush FocusStrokeColorOuter / FocusStrokeColorOuterBrush FocusStrokeColorInner / FocusStrokeColorInnerBrush
Background Fill
CardBackgroundFillColorDefault / CardBackgroundFillColorDefaultBrush CardBackgroundFillColorSecondary / CardBackgroundFillColorSecondaryBrush CardBackgroundFillColorTertiary / CardBackgroundFillColorTertiaryBrush SmokeFillColorDefault / SmokeFillColorDefaultBrush LayerFillColorDefault / LayerFillColorDefaultBrush LayerFillColorAlt / LayerFillColorAltBrush LayerOnAcrylicFillColorDefault / LayerOnAcrylicFillColorDefaultBrush LayerOnAccentAcrylicFillColorDefault / LayerOnAccentAcrylicFillColorDefaultBrush LayerOnMicaBaseAltFillColorDefault / LayerOnMicaBaseAltFillColorDefaultBrush LayerOnMicaBaseAltFillColorSecondary / LayerOnMicaBaseAltFillColorSecondaryBrush LayerOnMicaBaseAltFillColorTertiary / LayerOnMicaBaseAltFillColorTertiaryBrush LayerOnMicaBaseAltFillColorTransparent / LayerOnMicaBaseAltFillColorTransparentBrush
Solid Background Fill
SolidBackgroundFillColorBase / SolidBackgroundFillColorBaseBrush SolidBackgroundFillColorSecondary / SolidBackgroundFillColorSecondaryBrush SolidBackgroundFillColorTertiary / SolidBackgroundFillColorTertiaryBrush SolidBackgroundFillColorQuarternary / SolidBackgroundFillColorQuarternaryBrush SolidBackgroundFillColorQuinary / SolidBackgroundFillColorQuinaryBrush SolidBackgroundFillColorSenary / SolidBackgroundFillColorSenaryBrush SolidBackgroundFillColorTransparent / SolidBackgroundFillColorTransparentBrush SolidBackgroundFillColorBaseAlt / SolidBackgroundFillColorBaseAltBrush
System Fill
SystemFillColorSuccess / SystemFillColorSuccessBrush SystemFillColorCaution / SystemFillColorCautionBrush SystemFillColorCritical / SystemFillColorCriticalBrush SystemFillColorNeutral / SystemFillColorNeutralBrush SystemFillColorSolidNeutral / SystemFillColorSolidNeutralBrush SystemFillColorAttentionBackground / SystemFillColorAttentionBackgroundBrush SystemFillColorSuccessBackground / SystemFillColorSuccessBackgroundBrush SystemFillColorCautionBackground / SystemFillColorCautionBackgroundBrush SystemFillColorCriticalBackground / SystemFillColorCriticalBackgroundBrush SystemFillColorNeutralBackground / SystemFillColorNeutralBackgroundBrush SystemFillColorSolidAttentionBackground / SystemFillColorSolidAttentionBackgroundBrush SystemFillColorSolidNeutralBackground / SystemFillColorSolidNeutralBackgroundBrush
High Contrast System Brushes
For x:Key="HighContrast" dictionaries only:
SystemColorWindowTextColorBrush SystemColorWindowColorBrush SystemColorButtonFaceColorBrush SystemColorButtonTextColorBrush SystemColorHighlightColorBrush SystemColorHighlightTextColorBrush SystemColorHotlightColorBrush SystemColorGrayTextColorBrush
Code Review Checklist
Theme Support
- [ ] Uses
{ThemeResource}for colors/brushes at usage sites - [ ] Uses
{StaticResource}withResourceKeyredirects inside theme dictionaries - [ ] Custom theme resources define
Light,Dark, andHighContrastvariants - [ ] No
x:Key="Default"— uses explicitLight/Dark/HighContrast - [ ]
ResourceKeyvalues end inBrush(not the Color name) - [ ] HC dictionary uses only the 8 system color brushes (no accent, no hardcoded, no WinUI brushes)
- [ ] No opacity on elements or brushes in HC dictionaries
- [ ] No HC resources (
SystemColor*) used in Light/Dark dictionaries - [ ]
StaticResourceredirects preferred over inlineSolidColorBrushin theme dicts - [ ] Theme dictionary
x:Keyorder consistent across Light/Dark/HighContrast - [ ] No partial theme updates — Light/Dark changes include matching HighContrast in same PR
- [ ] No ad-hoc themed literals (
White/Transparentfor themed surfaces) - [ ] Acrylic surfaces use correct border/background pairings
- [ ] Light and Dark dicts reference the same semantic WinUI keys; differences are intentional
- [ ] Empty HC dict used when WinUI defaults suffice (
<ResourceDictionary x:Key="HighContrast" />) - [ ]
HighContrastAdjustment="None"set at app level - [ ] Accent colors use
SystemAccentColor*resources (no hardcoded accent values) - [ ] Verify runtime theme switching (ThemeResource updates; StaticResource does not)
Data Binding
- [ ] Uses
{x:Bind}over{Binding}where possible - [ ]
Modeexplicitly set onx:Bindwhen values change (OneWay/TwoWay) - [ ]
DataTemplatehasx:DataTypespecified - [ ] No
IValueConverter— usesx:Bindwith functions - [ ] Button text uses
Contentdirectly, not a nestedTextBlock - [ ]
IsEnabledbound from ViewModel readiness state - [ ] Commands used instead of Click/Tapped event handlers (MVVM)
- [ ]
VisualStateManagerused for visual property changes (not code-behind) - [ ] ViewModel state mapped to named properties (bool/enum) instead of complex converter stacks
- [ ] Converters are only simple type conversions; business logic stays in ViewModel
- [ ] No code-behind for styles/colors/layout (exception:
HighContrastAdjustmentat app level)
Typography
- [ ] Uses system text styles, not hardcoded font properties
- [ ]
FontWeightisSemiBold, neverBold - [ ]
BasedOnstyles do not re-declare inherited properties - [ ] Default
TextFillColorPrimaryBrushforeground not explicitly set - [ ] No font sizes below 12px
- [ ] Icon TextBlocks set
IsTextScaleFactorEnabled="False" - [ ] Icon font uses
{ThemeResource SymbolThemeFontFamily}, not hardcoded
Layout
- [ ] Uses
ControlCornerRadius/OverlayCornerRadius(not hardcoded) - [ ] Selective corner rounding uses standard radii (e.g.,
8,8,0,0) - [ ] Margins/padding use multiples of 4
- [ ] Uses
MinHeight/MinWidthinstead of fixed sizing - [ ] No fixed heights on text containers
- [ ] No fixed button widths (content-driven or
MinWidth) - [ ]
Borderfor single-child containers (not nested Grids) - [ ]
StackPaneldoes not contain TextBlocks needingTextTrimming - [ ]
RowSpacing/ColumnSpacingused instead of spacer elements - [ ] No negative margins
- [ ]
ThemeShadowhasTranslation="0,0,32"and 12px parent padding - [ ] Shadow receiver is behind the elevated element (z-order)
- [ ]
BackgroundSizing="InnerBorderEdge"on bordered acrylic elements - [ ] Mixed-control rows vertically centered
Styles
- [ ] Styles referenced with
{StaticResource}(not{ThemeResource}) - [ ] Default WinUI property values not explicitly set (Padding, CornerRadius, etc.)
- [ ] Single-use styles inlined, named style deleted
- [ ] Existing WinUI styles checked before creating custom ones
- [ ] No no-op style churn
- [ ] App-specific resources stay in app or feature dictionaries
- [ ]
ThemeResourceused inside style setters for themed values - [ ] VisualStateManager uses AdaptiveTrigger for responsive layout when needed
- [ ] Unused VisualState definitions removed
Resource Organization & Naming
- [ ] Semantic resource keys used (avoid location-based names)
- [ ] Shared resources promoted only when reused across features
- [ ] One-off values remain local (no global resources for single-use)
Accessibility
- [ ]
AutomationProperties.Nameon icon-only controls - [ ] Light-dismiss targets are hit-test visible (
Background="Transparent") - [ ]
DividerStrokeColorDefaultBrushfor dividers (not custom opacity brushes)
Performance
- [ ]
x:Loadfor conditional content - [ ]
x:Phasefor list item incremental loading - [ ]
OneTimebinding for static content - [ ] Minimal container nesting
Formatting
- [ ] Uniform indentation (spaces, no tabs)
- [ ] Self-closing tags for childless elements
- [ ] No
pxsuffix on numeric values - [ ] No commented-out XAML
- [ ] Unused VisualState definitions removed
- [ ] ThemeDictionaries before non-themed resources
- [ ] Namespace declarations ordered consistently (default,
x:, platform, WinUI, local) - [ ] Attribute order consistent across related files
- [ ] No checkpoint files checked in (use
_CPlocally and remove before commit)
Testing Reminders
If changing brushes: Test in NightSky HC theme, hover on all interactive elements. Include Light/Dark/HC screenshot evidence.
If changing text/containers: Test with text scaling at max and with long/localized strings.
If changing layout: Test at 100%, 150%, 200%, 250% display scaling. Validate Figma at 100% scale.
Colors and Materials Reference
Colors — Theme Resources
Never hardcode colors. Always use {ThemeResource} brushes so your app works in Light, Dark, and High Contrast modes.
Text brushes
| Resource | Use for |
|---|---|
TextFillColorPrimaryBrush | Primary text (headings, body) |
TextFillColorSecondaryBrush | Secondary / supporting text |
TextFillColorTertiaryBrush | Pressed state text |
TextFillColorDisabledBrush | Disabled text only |
TextOnAccentFillColorPrimaryBrush | Text on accent-colored backgrounds |
AccentTextFillColorPrimaryBrush | Hyperlinks and accent text |
Control fill brushes
| Resource | Use for |
|---|---|
ControlFillColorDefaultBrush | Control rest state |
ControlFillColorSecondaryBrush | Control hover state |
ControlFillColorTertiaryBrush | Control pressed state |
ControlFillColorDisabledBrush | Disabled controls |
ControlFillColorInputActiveBrush | Focused text input fields |
Background brushes
| Resource | Use for |
|---|---|
CardBackgroundFillColorDefaultBrush | Card backgrounds |
CardBackgroundFillColorSecondaryBrush | Alternate card rows |
LayerFillColorDefaultBrush | Layered surface backgrounds |
SolidBackgroundFillColorBaseBrush | Opaque page backgrounds |
SmokeFillColorDefaultBrush | Overlay dimming (behind dialogs) |
AcrylicBackgroundFillColorBaseBrush | Acrylic material surfaces |
Accent fill (for primary action buttons)
| Resource | Use for |
|---|---|
AccentFillColorDefaultBrush | Primary button rest |
AccentFillColorSecondaryBrush | Primary button hover |
AccentFillColorTertiaryBrush | Primary button pressed |
AccentFillColorDisabledBrush | Disabled primary button |
Stroke / border brushes
| Resource | Use for |
|---|---|
CardStrokeColorDefaultBrush | Card borders |
ControlStrokeColorDefaultBrush | Control borders |
DividerStrokeColorDefaultBrush | Separators and dividers |
Color code examples
<!-- GOOD -->
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="{StaticResource OverlayCornerRadius}"
Padding="16">
<TextBlock Text="Card content"
Foreground="{ThemeResource TextFillColorPrimaryBrush}" />
</Border>
<!-- BAD — hardcoded colors break Dark mode and High Contrast -->
<Border Background="#FFFFFF" BorderBrush="#E0E0E0">
<TextBlock Text="Card content" Foreground="#000000" />
</Border>---
Materials — Mica & Acrylic
Mica — use for the app's main window background. It samples the desktop wallpaper for a subtle tinted translucency.
Acrylic — use for transient surfaces (flyouts, menus, sidebars) layered on top of the main window.
<!-- Window-level Mica (set in MainWindow.xaml) -->
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<!-- Alternative: Mica Base Alt (slightly different tint) -->
<Window.SystemBackdrop>
<MicaBackdrop Kind="BaseAlt" />
</Window.SystemBackdrop>
<!-- Acrylic for in-app surfaces -->
<Window.SystemBackdrop>
<DesktopAcrylicBackdrop />
</Window.SystemBackdrop>| Material | Surface lifetime | Example |
|---|---|---|
| Mica | Long-lived (app window) | Main window background |
| Mica Base Alt | Long-lived (alternate tint) | Secondary window background |
| Acrylic | Transient (overlays) | Flyouts, sidebars, command bars |
Materials fall back to solid color on unsupported systems — no code needed.
Control Styles
Built-in WinUI 3 styles and patterns. Use {StaticResource} to reference, BasedOn to extend.
Button Styles
| Style | Description |
|---|---|
DefaultButtonStyle | Standard button |
AccentButtonStyle | Accent-colored primary action button |
NavigationBackButtonNormalStyle | Back navigation (40x40) |
NavigationBackButtonSmallStyle | Small back navigation (30x30) |
<Button Content="Save" Style="{StaticResource AccentButtonStyle}" />
<Button Content="Cancel" Style="{StaticResource DefaultButtonStyle}" />Subtle Button Pattern
Override Button.Resources with StaticResource redirects. This preserves the WinUI template and all visual states:
<Button Content="Action">
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="ButtonBackground" ResourceKey="SubtleFillColorTransparentBrush" />
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondaryBrush" />
<StaticResource x:Key="ButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiaryBrush" />
<StaticResource x:Key="ButtonBorderBrush" ResourceKey="SubtleFillColorTransparentBrush" />
<StaticResource x:Key="ButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorTransparentBrush" />
<StaticResource x:Key="ButtonBorderBrushPressed" ResourceKey="SubtleFillColorTransparentBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<StaticResource x:Key="ButtonBackground" ResourceKey="SubtleFillColorTransparentBrush" />
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondaryBrush" />
<StaticResource x:Key="ButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiaryBrush" />
<StaticResource x:Key="ButtonBorderBrush" ResourceKey="SubtleFillColorTransparentBrush" />
<StaticResource x:Key="ButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorTransparentBrush" />
<StaticResource x:Key="ButtonBorderBrushPressed" ResourceKey="SubtleFillColorTransparentBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast" />
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Button.Resources>
</Button>Empty HC dictionary lets WinUI defaults apply. Light and Dark usually have identical redirects. Border brush states should match background states.
Typography Styles
| Style | Size | Weight | Use Case |
|---|---|---|---|
CaptionTextBlockStyle | 12px | Regular | Small labels, timestamps |
BodyTextBlockStyle | 14px | Regular | Default body text (applied by default) |
BaseTextBlockStyle | 14px | Semibold | Base body style (less common) |
BodyStrongTextBlockStyle | 14px | Semibold | Emphasized body text |
BodyLargeTextBlockStyle | 18px | Regular | Prominent body text |
SubtitleTextBlockStyle | 20px | Semibold | Section headers, card titles |
TitleTextBlockStyle | 28px | Semibold | Page titles |
TitleLargeTextBlockStyle | 40px | Semibold | Large feature titles |
DisplayTextBlockStyle | 68px | Semibold | Hero text |
Rules:
BodyTextBlockStyleis the default — do not explicitly apply it.TextWrapping="NoWrap"is the default — do not set it.- Use
SemiBold, neverBold. - Minimum 12px for CJK legibility.
BasedOnstyles must not re-declare inherited properties (FontSize, FontFamily, FontWeight, LineHeight).
Style Hygiene
- Reference styles with
{StaticResource}(not{ThemeResource}— unnecessary overhead). - Check for existing WinUI styles before creating custom ones.
- Single-use styles: inline the properties, delete the named style.
- Keep one-off values inline; promote to shared dictionary only when reused.
- Prefer setters/resource overrides for minor visual tweaks; avoid replacing
ControlTemplateunless structurally required. - Use
ThemeResourceinside style setters for theme-dependent values. - Avoid no-op style churn.
Naming Conventions
| Type | Convention | Example |
|---|---|---|
| Style | {Purpose}Style | PrimaryButtonStyle |
| Brush | {Usage}{Property}Brush | HeaderBackgroundBrush |
| DataTemplate | {DataType}Template | UserItemTemplate |
Element x:Name | PascalCase + suffix | SearchTextBox, SaveButton |
Iconography and Motion Reference
Iconography
Use Segoe Fluent Icons (Windows 11) via the SymbolThemeFontFamily resource, which falls back to Segoe MDL2 Assets on Windows 10 automatically.
Icon types in order of preference
| Type | When to use | Example |
|---|---|---|
SymbolIcon | Standard named icons (simplest) | <SymbolIcon Symbol="Save" /> |
FontIcon | Specific glyph codes from Segoe Fluent Icons | <FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="" /> |
AnimatedIcon | Interactive states (checkbox, nav, toggle) | Built-in with some controls |
ImageIcon | Custom brand icons or images | <ImageIcon Source="ms-appx:///Assets/logo.png" /> |
PathIcon | Custom vector shapes | <PathIcon Data="M 0,0 L 10,10" /> |
BitmapIcon | Legacy bitmap icons | Avoid — prefer ImageIcon |
Standard icon sizes: 16px (inline/compact), 20px (default control size), 24px (emphasis), 32px (large), 48px (hero/feature).
Icon code examples
<!-- MenuFlyout with icons -->
<MenuFlyoutItem Text="Copy" Icon="{ui:SymbolIcon Symbol=Copy}">
<MenuFlyoutItem.KeyboardAccelerators>
<KeyboardAccelerator Key="C" Modifiers="Control" />
</MenuFlyoutItem.KeyboardAccelerators>
</MenuFlyoutItem>
<!-- NavigationViewItem with icon -->
<NavigationViewItem Content="Settings" Icon="{ui:SymbolIcon Symbol=Setting}" />
<!-- FontIcon for glyphs not in SymbolIcon enum -->
<FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}"
Glyph=""
FontSize="16" />Browse available icons in the WinUI Gallery app → Design guidance → Iconography, or search Segoe Fluent Icons.
---
Corner Radius
Use the built-in theme resources — never hardcode CornerRadius values:
| Resource | Value | Use for |
|---|---|---|
ControlCornerRadius | 4px | In-page controls (buttons, inputs, list items) |
OverlayCornerRadius | 8px | Top-level containers (cards, dialogs, flyouts, app window) |
| 0px | — | Edges that intersect with other straight edges (no resource needed) |
<!-- GOOD — use theme resources -->
<Button CornerRadius="{StaticResource ControlCornerRadius}" Content="Save" />
<Border CornerRadius="{StaticResource OverlayCornerRadius}" Padding="16">
<!-- Card content -->
</Border>
<!-- BAD — hardcoded values -->
<Button CornerRadius="4" Content="Save" />
<Border CornerRadius="12" />---
Motion & Transitions
Prefer built-in theme transitions — they animate automatically and respect user "reduce motion" settings.
<!-- Implicit transitions — animate property changes automatically -->
<Button Opacity="1">
<Button.OpacityTransition>
<ScalarTransition />
</Button.OpacityTransition>
</Button>
<!-- Page transitions via Frame -->
<Frame x:Name="ContentFrame">
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition />
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>Connected animations
Animate elements between pages (e.g., list item → detail page):
// Source page — prepare animation
var service = ConnectedAnimationService.GetForCurrentView();
service.PrepareToAnimate("itemAnimation", sourceElement);
Frame.Navigate(typeof(DetailPage), item);
// Destination page — play animation
var animation = ConnectedAnimationService.GetForCurrentView()
.GetAnimation("itemAnimation");
animation?.TryStart(destinationElement);Review Guidance Patterns
Concrete guidance patterns for WinUI 3 XAML reviews. Use these as a checklist for common pitfalls and fixes.
1. Brush References Must Target Brush Resources
ResourceKey must reference the SolidColorBrush resource (suffix Brush), not the Color resource.
<!-- Wrong -->
<StaticResource x:Key="TextControlBackground" ResourceKey="ControlFillColorDefault" />
<!-- Correct -->
<StaticResource x:Key="TextControlBackground" ResourceKey="ControlFillColorDefaultBrush" />Applies to High Contrast as well:
<!-- Wrong -->
<StaticResource x:Key="MyBrush" ResourceKey="SystemColorWindowColor" />
<!-- Correct -->
<StaticResource x:Key="MyBrush" ResourceKey="SystemColorWindowColorBrush" />2. Prefer StaticResource Redirects Over Inline SolidColorBrush
Inline brushes allocate new objects. Redirect to existing WinUI brushes instead:
<!-- Wrong -->
<SolidColorBrush x:Key="ButtonBackground" Color="{StaticResource ControlFillColorDefault}" />
<!-- Correct -->
<StaticResource x:Key="ButtonBackground" ResourceKey="ControlFillColorDefaultBrush" />3. High Contrast Rules (Strict)
- Only use the 8 system color brushes in HighContrast dictionaries.
- No hardcoded colors, no opacity, no accent colors, no regular WinUI brushes in HC.
- No gradient animations in HC. Use a single SystemColor brush.
- Use
{ThemeResource}only forSystemColor*in HC; use{StaticResource}elsewhere. - Use empty HC dictionary when WinUI defaults suffice:
<ResourceDictionary x:Key="HighContrast" />
- Set
HighContrastAdjustment = ApplicationHighContrastAdjustment.Noneonce at app level.
4. Remove Defaults and Redundant Properties
Avoid setting WinUI default values; it blocks future updates.
<!-- Wrong: defaults -->
<Button Padding="12" Height="32" CornerRadius="4" Content="Action" />
<!-- Correct: only set what differs -->
<Button MinHeight="40" Content="Action" />Defaults you should not set explicitly:
BodyTextBlockStyleon TextBlockTextFillColorPrimaryBrushon TextBlockTextWrapping="NoWrap"Padding="0"orMargin="0"VerticalAlignment="Top"/HorizontalAlignment="Left"
5. Corner Radius Must Use System Resources
<!-- Correct -->
<Border CornerRadius="{StaticResource ControlCornerRadius}" />
<Border CornerRadius="{StaticResource OverlayCornerRadius}" />Never hardcode CornerRadius="3" or CornerRadius="7".
6. Typography Must Use Styles
Use system text styles instead of raw font properties:
<!-- Wrong -->
<TextBlock FontSize="14" FontFamily="Segoe UI" FontWeight="Normal" />
<!-- Correct -->
<TextBlock Style="{StaticResource BodyTextBlockStyle}" />Additional rules:
- Use
SemiBold, neverBold. - Minimum 12px font size.
BasedOnstyles must not re-declare inherited properties.- Use
{ThemeResource SymbolThemeFontFamily}for icon fonts.
7. Text Scaling and Localization
Always validate large text scale and long strings:
- Use
MinHeightinstead ofHeight. - Avoid fixed widths on buttons and text containers.
- Prefer
VerticalAlignment="Center"over fixed positioning. - Test at max text scaling and with long/localized strings.
8. Container Simplification
Remove wrappers that do not add layout or styling:
- If a Button contains only a SymbolIcon, put it directly in
Content. - Use
Borderfor single-child background containers, notGrid. - Remove StackPanel/Grid wrappers around single elements.
9. TextTrimming Requires Grid Constraints
StackPanel and ColumnDefinition Width="Auto" prevent trimming:
<!-- Wrong -->
<StackPanel Orientation="Horizontal">
<TextBlock TextTrimming="CharacterEllipsis" />
</StackPanel>
<!-- Correct -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" TextTrimming="CharacterEllipsis" />10. 4px Grid for Layout
All margins, padding, and sizes should be multiples of 4 (4, 8, 12, 16...). Avoid odd values like 3, 5, 7, 11, 15.
11. Flyout and Acrylic Surfaces
Flyout surfaces should use:
Background="{ThemeResource FlyoutPresenterBackground}"
BorderBrush="{ThemeResource FlyoutBorderThemeBrush}"
BorderThickness="{ThemeResource FlyoutBorderThemeThickness}"
CornerRadius="{StaticResource OverlayCornerRadius}"Acrylic pairings:
- Flyouts/tooltips:
AcrylicBackgroundFillColorDefaultBrush+SurfaceStrokeColorFlyoutBrush - UI surfaces:
AcrylicBackgroundFillColorBaseBrush+SurfaceStrokeColorDefaultBrush
Use BackgroundSizing="InnerBorderEdge" on bordered acrylic.
12. ThemeShadow and Elevation
ThemeShadow requires elevation:
Translation="0,0,32"Add 12px padding on parent to prevent shadow clipping. Prefer ThemeShadow over composition drop shadows.
13. Reused Values Should Be Named Resources
If the same margin/padding/thickness value appears multiple times, extract it into a named resource.
14. Icon Sizing and Spacing
- Prefer FontIcon with
FontSizefor system icons. - Use standard even sizes (16, 20, 24, 32).
- Use
UniformToFillfor non-square images to avoid distortion. - Keep icon padding consistent on all sides.
15. BasedOn Style Inheritance
When using BasedOn, remove all setters that duplicate the base style. Only keep differences.
17. ScrollViewer Configuration
VerticalScrollBarVisibility="Auto"(default is Visible).HorizontalContentAlignment="Stretch"to prevent content collapse.- Only the content area should scroll; headers/actions remain fixed.
18. ProgressBar / ProgressRing Defaults
Keep default templates. Custom overrides (CornerRadius, Foreground) have caused contrast and accessibility bugs.
19. Button.Resources for Single-Use Visual States
When customizing a single button's hover/pressed visuals, use Button.Resources with theme dictionaries instead of a new style or template.
Theme-Aware Resources
ThemeResource vs StaticResource
| Markup Extension | Evaluated | Updates on Theme Change | Use Case |
|---|---|---|---|
{ThemeResource} | Runtime | Yes | Theme-dependent values at usage sites |
{StaticResource} | Load time | No | Static values, inside theme dictionaries |
Runtime Theme Switching
Verify runtime theme switching. {ThemeResource} updates when the system theme changes; {StaticResource} does not.
StaticResource Redirects (Preferred Pattern)
Use <StaticResource> with ResourceKey to redirect to an existing WinUI brush. This reuses the existing brush object (zero allocation) instead of creating a new SolidColorBrush inline.
<!-- Correct: redirect -->
<StaticResource x:Key="ButtonBackground" ResourceKey="ControlFillColorDefaultBrush" />
<!-- Wrong: new brush object -->
<SolidColorBrush x:Key="ButtonBackground" Color="{StaticResource ControlFillColorDefault}" />Theme Dictionary Structure
Always define all three variants. Never use x:Key="Default".
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="MyBrush" ResourceKey="ControlFillColorDefaultBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<StaticResource x:Key="MyBrush" ResourceKey="ControlFillColorDefaultBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<StaticResource x:Key="MyBrush" ResourceKey="SystemColorWindowTextColorBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>Rules inside theme dictionaries:
{StaticResource}in Light/Dark (not{ThemeResource}— circular lookup risk){ThemeResource}only forSystemColor*in HighContrastResourceKeymust end inBrush- Keep
x:Keyorder identical across Light/Dark/HighContrast - Light and Dark should typically reference the same semantic WinUI keys
Accent Colors
Use the system accent color resources:
<!-- User accent color -->
<Border Background="{ThemeResource SystemAccentColor}" />
<!-- Lighter/darker variants -->
<Border Background="{ThemeResource SystemAccentColorLight1}" />
<Border Background="{ThemeResource SystemAccentColorDark1}" />High Contrast System Colors
The Eight Valid Brushes
| Resource | Purpose |
|---|---|
SystemColorWindowTextColorBrush | Text on window background |
SystemColorWindowColorBrush | Window/content background |
SystemColorHighlightTextColorBrush | Selected text foreground |
SystemColorHighlightColorBrush | Selection/hover background |
SystemColorButtonTextColorBrush | Button text/foreground |
SystemColorButtonFaceColorBrush | Button background |
SystemColorGrayTextColorBrush | Disabled/inactive text |
SystemColorHotlightColorBrush | Hyperlinks |
For color animations, use the matching Color resource (without "Brush" suffix).
HC Color Pairings
| Background | Foreground | Use Case |
|---|---|---|
SystemColorWindowColorBrush | SystemColorWindowTextColorBrush | General content |
SystemColorHighlightColorBrush | SystemColorHighlightTextColorBrush | Selected/hover states |
SystemColorButtonFaceColorBrush | SystemColorButtonTextColorBrush | Buttons |
SystemColorWindowColorBrush | SystemColorHotlightColorBrush | Hyperlinks |
SystemColorWindowColorBrush | SystemColorGrayTextColorBrush | Disabled content |
Never mix incompatible pairs.
HC Prohibitions
- No hardcoded colors
- No opacity on elements or brushes
- No accent colors (
SystemAccentColor) - No regular WinUI brushes (
TextFillColorPrimaryBrush, etc.) - No gradient animations — use one solid SystemColor
- No
SystemColor*resources in Light/Dark dictionaries
HC Border Thickness
Use 2px border in HC (vs 1px in Light/Dark) for flyouts, dialogs, cards:
<ResourceDictionary x:Key="Light">
<Thickness x:Key="CardBorderThickness">1</Thickness>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<Thickness x:Key="CardBorderThickness">1</Thickness>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<Thickness x:Key="CardBorderThickness">2</Thickness>
</ResourceDictionary>HighContrastAdjustment
Set at app level to prevent system from doubling HC overrides:
Application.Current.HighContrastAdjustment = ApplicationHighContrastAdjustment.None;ARGB Encoding for Opacity
Encode opacity in alpha channel rather than using Opacity property:
<!-- 25% opacity via alpha channel -->
<SolidColorBrush x:Key="BackplateBrush" Color="#40000000" />Acrylic Surface Pairings
| Surface Type | Background | Border |
|---|---|---|
| Menu flyouts, tooltips | AcrylicBackgroundFillColorDefaultBrush | SurfaceStrokeColorFlyoutBrush |
| UI surfaces (Start, Action Center) | AcrylicBackgroundFillColorBaseBrush | SurfaceStrokeColorDefaultBrush |
<Border Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource SurfaceStrokeColorFlyoutBrush}"
BorderThickness="1"
CornerRadius="{StaticResource OverlayCornerRadius}"
BackgroundSizing="InnerBorderEdge"
Translation="0,0,32">
<Border.Shadow>
<ThemeShadow />
</Border.Shadow>
</Border>Overlays on acrylic use LayerOnAcrylicFillColorDefaultBrush. Dividers use DividerStrokeColorDefaultBrush.
Dialog Overlays (Smoke)
For dim overlays behind dialogs or modals, use:
<Border Background="{ThemeResource ContentDialogSmokeFill}" />Windows 10 to 11 Migration
| Windows 10 Resource | Windows 11 (WinUI) Equivalent |
|---|---|
SystemControlForegroundBaseMediumBrush | TextFillColorSecondaryBrush |
SystemControlHighlightAltAccentBrush | HC: SystemColorHighlightTextColorBrush |
SystemControlHyperlinkTextBrush | HC: SystemColorHotlightColorBrush |
SystemAltHighColor | Use appropriate WinUI theme resource |
Typography and Spacing Reference
Typography — Type Ramp
Use the built-in TextBlock styles — never set FontSize or FontWeight manually. The type ramp uses Segoe UI Variable and scales correctly across displays.
| Style | Use for |
|---|---|
CaptionTextBlockStyle | Labels, timestamps, metadata |
BodyTextBlockStyle | Body text, descriptions (default) |
BodyStrongTextBlockStyle | Emphasized body text |
BodyLargeTextBlockStyle | Introductory text |
SubtitleTextBlockStyle | Section headings |
TitleTextBlockStyle | Page titles |
TitleLargeTextBlockStyle | Hero headings |
DisplayTextBlockStyle | Splash / display only |
Always reference these StaticResource styles — never hardcode font sizes, weights, or line heights.
<!-- GOOD — use built-in styles -->
<TextBlock Text="Settings" Style="{StaticResource SubtitleTextBlockStyle}" />
<TextBlock Text="Choose your preferences below." Style="{StaticResource BodyTextBlockStyle}" />
<TextBlock Text="Last updated: 3/10/2026" Style="{StaticResource CaptionTextBlockStyle}" />
<!-- BAD — never hardcode font properties -->
<TextBlock Text="Settings" FontSize="20" FontWeight="SemiBold" />Minimum readable sizes: 12px Regular for labels, 14px SemiBold for smallest bold text. Never go below 12px.
---
Spacing — 4px Grid
All spacing and sizing values must be multiples of 4px. This ensures consistent alignment and scaling across DPI settings.
Standard spacing scale (effective pixels):
| Value | Use for |
|---|---|
| 4px | Compact spacing between tightly related elements |
| 8px | Spacing between a control and its label, between grouped controls |
| 12px | Spacing between a control and its header, surface edge to text |
| 16px | Padding inside cards and list items |
| 24px | Spacing between content sections |
| 36px | Page-level padding (content area margins) |
| 48px | Spacing between major page sections with titles |
<!-- GOOD — multiples of 4 -->
<StackPanel Spacing="8">
<TextBlock Text="Name" Style="{StaticResource BodyStrongTextBlockStyle}" />
<TextBox PlaceholderText="Enter your name" />
</StackPanel>
<Grid Padding="36" RowSpacing="24" ColumnSpacing="16">
<!-- Page content with standard padding and section spacing -->
</Grid>
<!-- BAD — arbitrary values -->
<StackPanel Spacing="10" Margin="15,7,15,7" />Related skills
FAQ
What tool should I use before writing WinUI XAML?
Run winui-search.exe search and get to ground control choices in canonical Gallery and Toolkit samples.
How should I size a WinUI 3 window?
Derive width and height from layout rows in MainWindow constructor using DPI-scaled AppWindow.Resize.
Is winui-design safe to install?
Review the Security Audits panel on this page before installing in production.