In XAML, you'd override control resources in a ResourceDictionary.ThemeDictionaries block. In Reactor, use .Resources() to inject per-control resource overrides. The control's VisualStateManager automatically uses them for hover/pressed/disabled states.
A toolbar-style button with transparent background:
Button("Action", onClick).Resources(r => r
.Set("ButtonBackground", Theme.SubtleFill)
.Set("ButtonBackgroundPointerOver", Theme.Ref("SubtleFillColorSecondaryBrush"))
.Set("ButtonBackgroundPressed", Theme.Ref("SubtleFillColorTertiaryBrush"))
.Set("ButtonBorderBrush", Theme.SubtleFill)
.Set("ButtonBorderBrushPointerOver", Theme.SubtleFill)
.Set("ButtonBorderBrushPressed", Theme.SubtleFill))A primary action button with accent color:
Button("Primary Action", onClick).Resources(r => r
.Set("ButtonBackground", Theme.Accent)
.Set("ButtonBackgroundPointerOver", Theme.AccentSecondary)
.Set("ButtonBackgroundPressed", Theme.AccentTertiary)
.Set("ButtonForeground", Theme.Ref("TextOnAccentFillColorPrimaryBrush"))
.Set("ButtonForegroundPointerOver", Theme.Ref("TextOnAccentFillColorPrimaryBrush"))
.Set("ButtonForegroundPressed", Theme.Ref("TextOnAccentFillColorSecondaryBrush")))Or, if the WinUI AccentButtonStyle is available:
Button("Primary Action", onClick).Set(b =>
b.Style = (Style)Application.Current.Resources["AccentButtonStyle"])Setting .Background() directly on a Button overrides the resting state only. Hover, pressed, and disabled states still use the default theme — creating visual inconsistency.
// Wrong: only changes resting state
Button("Action", onClick).Background(Theme.Accent)
// Hover/pressed/disabled states are still default gray
// Correct: all states are consistent
Button("Action", onClick).Resources(r => r
.Set("ButtonBackground", Theme.Accent)
.Set("ButtonBackgroundPointerOver", Theme.AccentSecondary)
.Set("ButtonBackgroundPressed", Theme.AccentTertiary))| Key | State | Purpose |
|---|---|---|
ButtonBackground |
Rest | Background color |
ButtonBackgroundPointerOver |
Hover | Hover background |
ButtonBackgroundPressed |
Pressed | Pressed background |
ButtonBackgroundDisabled |
Disabled | Disabled background |
ButtonForeground |
Rest | Text/icon color |
ButtonForegroundPointerOver |
Hover | Hover text color |
ButtonForegroundPressed |
Pressed | Pressed text color |
ButtonForegroundDisabled |
Disabled | Disabled text color |
ButtonBorderBrush |
Rest | Border color |
ButtonBorderBrushPointerOver |
Hover | Hover border |
ButtonBorderBrushPressed |
Pressed | Pressed border |
Consult the WinUI Button theme resources for the complete list.
| Key | Purpose |
|---|---|
TextControlForeground |
Text color |
TextControlBackground |
Background |
TextControlBorderBrush |
Border |
TextControlPlaceholderForeground |
Placeholder text |
TextControlForegroundFocused |
Focused text |
TextControlBackgroundFocused |
Focused background |
| Key | Purpose |
|---|---|
ToggleSwitchFillOn |
On state fill |
ToggleSwitchFillOff |
Off state fill |
ToggleSwitchStrokeOn |
On state border |
ToggleSwitchStrokeOff |
Off state border |
For built-in WinUI styles, use .Set():
Button("Accent", onClick).Set(b =>
b.Style = (Style)Application.Current.Resources["AccentButtonStyle"])
TextBlock("Body strong").Set(tb =>
tb.Style = (Style)Application.Current.Resources["BodyStrongTextBlockStyle"])- Check for existing WinUI styles first — don't create custom resource overrides when a WinUI style already exists.
- Keep visual states consistent — if overriding rest state, override hover/pressed/disabled too.
- ResourceKey values must end in "Brush" — target the
SolidColorBrush, not theColor:// Correct .Set("ButtonBackground", Theme.Ref("ControlFillColorDefaultBrush")) // Wrong .Set("ButtonBackground", Theme.Ref("ControlFillColorDefault"))
- Use
.Resources()for single-control overrides — don't create shared style resources for one-off customizations. - Don't override defaults — if the default WinUI button style is what you want, don't set
.Resources()at all. No-op resource overrides that repeat WinUI defaults add noise and block future WinUI updates. - Don't re-declare inherited properties — when applying a WinUI style via
.Set(), don't also set properties the style already defines (FontSize, FontWeight, etc.). They are redundant and block future updates.// Wrong: FontSize is already in BodyStrongTextBlockStyle TextBlock("Bold body").SemiBold().FontSize(14).Set(tb => tb.Style = (Style)Application.Current.Resources["BodyStrongTextBlockStyle"]) // Correct: style handles size and weight TextBlock("Bold body").Set(tb => tb.Style = (Style)Application.Current.Resources["BodyStrongTextBlockStyle"])
- Empty HC is valid for
.Resources()patterns — when your overrides target only Light/Dark appearance and WinUI defaults already satisfy HC accessibility, you do not need HC-specific resource overrides. This is the common case for subtle/accent button patterns.