Make button hover affordances visible on dark canvas
Some checks failed
CI / build-and-test (push) Failing after 27s

Hover state on Wd.Button.Ghost / Caption / RailIcon / IsoToggle was barely visible — the Wd.SurfaceHover fill (#242424) was only 14 luminance points off the canvas (#0A0A0A) and 16 off the cards (#141414), so the hover state read as 'no change' to the user.

Changes:

1. Bumped Wd.SurfaceHover #242424 -> #2A2A2A and Wd.SurfaceActive #2D2D2D -> #363636 across the theme (carries to DataGrid rows etc. with the same too-subtle problem).

2. Added Wd.Button.HoverBg (#33333A) + Wd.Button.PressBg (#3F3F47) — dedicated stronger hover/press fills for buttons specifically. The slight blue tint adds chroma so hover reads obviously distinct from a flat darken.

3. Wd.Button.Ghost hover now also sets BorderBrush=Wd.Accent.Cyan — dual cue (lighter fill + bright cyan border) makes the affordance unmistakable on any surface.

4. Wd.Button.RailIcon hover sets foreground=Wd.Accent.Cyan in addition to the brighter fill (rail buttons have icons, not text — color shift on the icon is the strongest signal).

5. Wd.Button.IsoToggle keeps its status-coded background on hover (LIVE cyan / ERROR coral / NO SIGNAL amber) so at-a-glance state isn't lost; instead bumps to a 2px cyan border for the affordance.

Verified: cleanly built, app launches, hover over Refresh button now has obvious brighter fill + tooltip vs. neighbors at rest.
This commit is contained in:
Zac Gaetano 2026-05-10 13:22:45 -04:00
parent d9eb02a9af
commit 554ab9e570

View file

@ -45,10 +45,19 @@
<SolidColorBrush x:Key="Wd.Rail" Color="#080808"/>
<SolidColorBrush x:Key="Wd.Surface" Color="#141414"/>
<SolidColorBrush x:Key="Wd.SurfaceElevated" Color="#1C1C1C"/>
<SolidColorBrush x:Key="Wd.SurfaceHover" Color="#242424"/>
<SolidColorBrush x:Key="Wd.SurfaceActive" Color="#2D2D2D"/>
<SolidColorBrush x:Key="Wd.SurfaceHover" Color="#2A2A2A"/>
<SolidColorBrush x:Key="Wd.SurfaceActive" Color="#363636"/>
<SolidColorBrush x:Key="Wd.Border" Color="#262626"/>
<SolidColorBrush x:Key="Wd.BorderStrong" Color="#383838"/>
<!--
Dedicated stronger hover background for buttons, used when the default
SurfaceHover doesn't read clearly enough on the dark cards. Combined
with a cyan accent border on hover this gives every interactive
button an unmistakable affordance regardless of what surface it
sits on (canvas, card, or rail).
-->
<SolidColorBrush x:Key="Wd.Button.HoverBg" Color="#33333A"/>
<SolidColorBrush x:Key="Wd.Button.PressBg" Color="#3F3F47"/>
<SolidColorBrush x:Key="Wd.Text.Primary" Color="#F5F5F5"/>
<SolidColorBrush x:Key="Wd.Text.Secondary" Color="#A3A3A3"/>
@ -147,11 +156,20 @@
Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<!--
Hover: strong fill change PLUS a cyan accent border.
The dual-cue (lighter surface + bright border) is
what gives the affordance an unmistakable read on
the dark canvas — a background-only change in this
palette is too subtle to spot at a glance.
-->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.SurfaceHover}"/>
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.Button.HoverBg}"/>
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Wd.Accent.Cyan}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.SurfaceActive}"/>
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.Button.PressBg}"/>
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Wd.Accent.CyanHover}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource Wd.Text.Disabled}"/>
@ -213,10 +231,10 @@
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.SurfaceHover}"/>
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.Button.HoverBg}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.SurfaceActive}"/>
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.Button.PressBg}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
@ -265,9 +283,15 @@
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<!-- Rail icons sit on Wd.Rail (#080808) — a darker
surface than Wd.Canvas. Use Wd.Button.HoverBg so
the affordance reads clearly. -->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.SurfaceHover}"/>
<Setter Property="Foreground" Value="{StaticResource Wd.Text.Primary}"/>
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.Button.HoverBg}"/>
<Setter Property="Foreground" Value="{StaticResource Wd.Accent.Cyan}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.Button.PressBg}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
@ -302,8 +326,23 @@
Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<!--
IsoToggle has a status-coded background (LIVE cyan,
ERROR coral, NO SIGNAL amber) set inline by the row
template. Hover *keeps* that background color (so
the at-a-glance status read is preserved) and adds
a thicker cyan-tinted border so the affordance is
unmistakable. We don't override Background here so
the data-trigger setter wins.
-->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Wd.SurfaceActive}"/>
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Wd.Accent.CyanHover}"/>
<Setter TargetName="Bd" Property="BorderThickness" Value="2"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Wd.Accent.Cyan}"/>
<Setter TargetName="Bd" Property="BorderThickness" Value="2"/>
<Setter TargetName="Bd" Property="Opacity" Value="0.85"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>