Skip to content

Commit 288b8b8

Browse files
committed
Improved focus visuals
timepicker focus visual improved calender view focus visuals assign focus visual target focus visual target for: hyperlink button radio button button command bar menu items toggle switch improve focus visuals toggle switch command bar updated corner radius fix button focus visual Fix FocusVisual clipped by scrollviewer fix settingscard clipped tree view focus visuals improved focus visuals radio menu items focus visuals menu items focus visuals tabitem focus visuals fix treeview focus visuals generalizing AdornerDecorator context menu item focus visuals combobox focus visuals
1 parent 69ccdcd commit 288b8b8

File tree

23 files changed

+215
-64
lines changed

23 files changed

+215
-64
lines changed

source/iNKORE.UI.WPF.Modern.Controls/Controls/Community/SettingsControls/SettingsCard/SettingsCard.xaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
</ResourceDictionary>
7979

8080
</ControlTemplate.Resources>
81-
<ui:ElevationBorder x:Name="PART_RootBorder"
81+
<Border x:Name="PART_RootBorder"
8282
MinWidth="{TemplateBinding MinWidth}"
8383
MinHeight="{TemplateBinding MinHeight}"
8484
MaxWidth="{TemplateBinding MaxWidth}"
@@ -88,7 +88,8 @@
8888
Background="{TemplateBinding Background}"
8989
BorderBrush="{TemplateBinding BorderBrush}"
9090
BorderThickness="{TemplateBinding BorderThickness}"
91-
CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}">
91+
CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}"
92+
ui:FocusVisualHelper.IsTemplateFocusTarget="True">
9293
<VisualStateManager.VisualStateGroups>
9394
<VisualStateGroup x:Name="CommonStates">
9495
<ui:VisualStateGroupListener.Listener>
@@ -382,7 +383,7 @@
382383
ToolTipService.ToolTip="{TemplateBinding ActionIconToolTip}" />
383384
</Viewbox>
384385
</Grid>
385-
</ui:ElevationBorder>
386+
</Border>
386387

387388

388389
<ControlTemplate.Triggers>

source/iNKORE.UI.WPF.Modern.Controls/Controls/Community/SettingsControls/SettingsExpander/SettingsExpander.xaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@
5353
<Setter.Value>
5454
<ControlTemplate TargetType="ToggleButton">
5555

56-
<ui:ElevationBorder
56+
<Border
5757
x:Name="Background"
5858
Background="{TemplateBinding Background}"
5959
BorderBrush="{TemplateBinding BorderBrush}"
6060
BorderThickness="{TemplateBinding BorderThickness}"
6161
CornerRadius="{TemplateBinding chelper:ControlHelper.CornerRadius}"
62-
SnapsToDevicePixels="True">
62+
SnapsToDevicePixels="True"
63+
ui:FocusVisualHelper.IsTemplateFocusTarget="True">
6364
<Border
6465
x:Name="Border"
6566
Padding="{TemplateBinding Padding}"
@@ -116,7 +117,7 @@
116117
</VisualStateGroup>
117118
</VisualStateManager.VisualStateGroups>
118119

119-
</ui:ElevationBorder>
120+
</Border>
120121
<ControlTemplate.Triggers>
121122
<Trigger Property="IsMouseOver" Value="True">
122123
<Setter TargetName="Background" Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />

source/iNKORE.UI.WPF.Modern.Controls/Controls/Windows/CommandBar/CommandBar.xaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
-->
4949
<ContentControl
5050
x:Name="ContentControl"
51+
Margin="{TemplateBinding Padding}"
5152
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
5253
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
5354
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
@@ -76,14 +77,15 @@
7677
IsChecked="{Binding Path=IsOverflowOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
7778
IsEnabled="{TemplateBinding HasOverflowItems}"
7879
Style="{DynamicResource EllipsisButton}"
80+
ui:FocusVisualHelper.IsTemplateFocusTarget="True"
7981
Visibility="{TemplateBinding EffectiveOverflowButtonVisibility}">
8082
<ui:FontIcon
8183
x:Name="EllipsisIcon"
8284
Height="{DynamicResource AppBarExpandButtonCircleDiameter}"
8385
VerticalAlignment="Center"
84-
FontFamily="{DynamicResource FluentSystemIcons}"
86+
FontFamily="{DynamicResource SymbolThemeFontFamily}"
8587
FontSize="20"
86-
Glyph="&#xE826;" />
88+
Glyph="&#xE712;" />
8789
</ToggleButton>
8890
<Rectangle
8991
x:Name="HighContrastBorder"
@@ -129,6 +131,7 @@
129131
</primitives:CommandBarOverflowPresenter.Resources>
130132
<primitives:CommandBarOverflowPanel
131133
x:Name="PART_ToolBarOverflowPanel"
134+
Margin="{DynamicResource CommandBarOverflowPresenterMargin}"
132135
FocusVisualStyle="{x:Null}"
133136
Focusable="true"
134137
KeyboardNavigation.DirectionalNavigation="Cycle"
@@ -210,7 +213,6 @@
210213
SnapsToDevicePixels="True">
211214
<Border Padding="{TemplateBinding Padding}" CornerRadius="{TemplateBinding CornerRadius}">
212215
<ui:ScrollViewerEx
213-
Padding="{DynamicResource CommandBarOverflowPresenterMargin}"
214216
Content="{TemplateBinding Content}"
215217
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
216218
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"

source/iNKORE.UI.WPF.Modern.Controls/Controls/Windows/HyperlinkButton/HyperlinkButton.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
BorderBrush="{TemplateBinding BorderBrush}"
3131
BorderThickness="{TemplateBinding BorderThickness}"
3232
CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}"
33+
ui:FocusVisualHelper.IsTemplateFocusTarget="True"
3334
SnapsToDevicePixels="True">
3435
<Border
3536
x:Name="Border"

source/iNKORE.UI.WPF.Modern.Controls/Controls/Windows/RadioMenuItem/RadioMenuItem.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<Setter Property="BorderThickness" Value="{DynamicResource MenuFlyoutItemRevealBorderThickness}" />
1515
<Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemForeground}" />
1616
<Setter Property="Padding" Value="{DynamicResource MenuFlyoutItemThemePadding}" />
17+
<Setter Property="ui:ControlHelper.CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
1718
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
1819
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
1920
<Setter Property="VerticalContentAlignment" Value="Center" />

source/iNKORE.UI.WPF.Modern.Controls/Controls/Windows/TimePicker/TimePicker.xaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@
8080
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
8181
<Setter Property="FocusVisualStyle" Value="{DynamicResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
8282
<Setter Property="UseSystemFocusVisuals" Value="{DynamicResource UseSystemFocusVisuals}" />
83-
<Setter Property="ui:FocusVisualHelper.FocusVisualMargin" Value="0,0,0,5" />
8483
<Setter Property="ui:ControlHelper.CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
8584
<Setter Property="VerticalAlignment" Value="Stretch" />
85+
<Setter Property="MaxHeight" Value="{DynamicResource LoopingSelectorMaxHeight}"/>
8686
<Setter Property="ItemsPanel">
8787
<Setter.Value>
8888
<ItemsPanelTemplate>
@@ -99,7 +99,7 @@
9999
Focusable="false"
100100
HorizontalScrollBarVisibility="Disabled"
101101
VerticalScrollBarVisibility="Hidden">
102-
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
102+
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="0,-3,0,0"/>
103103
</ScrollViewer>
104104
<RepeatButton
105105
x:Name="UpButton"
@@ -394,7 +394,7 @@
394394
Grid.ColumnSpan="7"
395395
Height="{DynamicResource TimePickerFlyoutPresenterHighlightHeight}"
396396
IsHitTestVisible="False"
397-
Margin="4,6,4,0"
397+
Margin="4,2,4,2"
398398
VerticalAlignment="Center"
399399
BorderThickness="0"
400400
CornerRadius="{TemplateBinding CornerRadius}"

source/iNKORE.UI.WPF.Modern.Controls/Controls/Windows/ToggleSwitch/ToggleSwitch.xaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<Setter Property="MinWidth" Value="{DynamicResource ToggleSwitchThemeMinWidth}" />
3333
<Setter Property="FocusVisualStyle" Value="{DynamicResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
3434
<Setter Property="ui:FocusVisualHelper.FocusVisualMargin" Value="-7,-3,-7,-3" />
35+
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
3536
<Setter Property="Template">
3637
<Setter.Value>
3738
<ControlTemplate TargetType="local:ToggleSwitch">
@@ -123,6 +124,8 @@
123124
Visibility="Collapsed" />
124125
<Grid
125126
Grid.Row="1"
127+
ui:FocusVisualHelper.IsTemplateFocusTarget="True"
128+
ui:ControlHelper.CornerRadius="{TemplateBinding CornerRadius}"
126129
HorizontalAlignment="Left"
127130
VerticalAlignment="Top">
128131

@@ -144,7 +147,6 @@
144147
Grid.RowSpan="3"
145148
Grid.ColumnSpan="5"
146149
Margin="0,5"
147-
ui:FocusVisualHelper.IsTemplateFocusTarget="True"
148150
Background="{DynamicResource ToggleSwitchContainerBackground}"
149151
CornerRadius="{TemplateBinding CornerRadius}" />
150152
<ui:ContentPresenterEx

source/iNKORE.UI.WPF.Modern.Gallery/Controls/ControlExample.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<sys:Double x:Key="ExampleMaxWidth">1000</sys:Double>
1414

1515
<Style TargetType="local:ControlExample">
16+
<Setter Property="IsTabStop" Value="False"/>
1617
<Setter Property="Template">
1718
<Setter.Value>
1819
<ControlTemplate TargetType="local:ControlExample">

source/iNKORE.UI.WPF.Modern/Controls/Helpers/FocusVisualHelper.cs

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Windows.Controls;
1111
using System.Windows.Documents;
1212
using System.Windows.Media;
13+
using iNKORE.UI.WPF.Helpers;
1314

1415
namespace iNKORE.UI.WPF.Modern.Controls.Helpers
1516
{
@@ -163,6 +164,20 @@ public static void SetFocusVisualSecondaryThickness(FrameworkElement element, Th
163164

164165
#endregion
165166

167+
#region FocusVisualPrimaryCornerRadius
168+
169+
public static CornerRadius GetFocusVisualPrimaryCornerRadius(FrameworkElement element) => (CornerRadius)element.GetValue(FocusVisualPrimaryCornerRadiusProperty);
170+
private static void SetFocusVisualPrimaryCornerRadius(FrameworkElement element, CornerRadius value) => element.SetValue(FocusVisualPrimaryCornerRadiusProperty, value);
171+
172+
public static readonly DependencyProperty FocusVisualPrimaryCornerRadiusProperty =
173+
DependencyProperty.RegisterAttached(
174+
"FocusVisualPrimaryCornerRadius",
175+
typeof(CornerRadius),
176+
typeof(FocusVisualHelper),
177+
new FrameworkPropertyMetadata(new CornerRadius(0)));
178+
179+
#endregion
180+
166181
#region FocusVisualMargin
167182

168183
/// <summary>
@@ -393,7 +408,7 @@ static void ShowFocusVisual(Control control, FrameworkElement target)
393408
{
394409
HideFocusVisual();
395410

396-
AdornerLayer adornerlayer = AdornerLayer.GetAdornerLayer(target);
411+
AdornerLayer adornerlayer = GetAdornerLayer(target);
397412
if (adornerlayer == null)
398413
return;
399414

@@ -414,6 +429,17 @@ static void ShowFocusVisual(Control control, FrameworkElement target)
414429
}
415430
}
416431

432+
static AdornerLayer? GetAdornerLayer(FrameworkElement element)
433+
{
434+
var scrollPresenter = element.FindAscendant<ScrollContentPresenter>();
435+
if (scrollPresenter?.Parent is AdornerDecorator adornerDecorator)
436+
{
437+
return adornerDecorator.AdornerLayer;
438+
}
439+
440+
return AdornerLayer.GetAdornerLayer(element);
441+
}
442+
417443
static void OnControlIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
418444
{
419445
((Control)sender).IsVisibleChanged -= OnControlIsVisibleChanged;
@@ -483,11 +509,13 @@ private static void OnFocusVisualIsVisibleChanged(object sender, DependencyPrope
483509
}
484510
else
485511
{
512+
var focusVisualMargin = GetFocusVisualMargin(focusedElement);
513+
ApplyCornerRadiusToFocusVisual(focusVisual, focusedElement, focusVisualMargin);
486514
TransferValue(focusedElement, focusVisual, FocusVisualPrimaryBrushProperty);
487515
TransferValue(focusedElement, focusVisual, FocusVisualPrimaryThicknessProperty);
488516
TransferValue(focusedElement, focusVisual, FocusVisualSecondaryBrushProperty);
489517
TransferValue(focusedElement, focusVisual, FocusVisualSecondaryThicknessProperty);
490-
focusVisual.Margin = GetFocusVisualMargin(focusedElement);
518+
focusVisual.Margin = focusVisualMargin;
491519
}
492520

493521
SetFocusedElement(focusVisual, focusedElement);
@@ -510,6 +538,39 @@ private static void OnFocusVisualIsVisibleChanged(object sender, DependencyPrope
510538
}
511539
}
512540

541+
private static void ApplyCornerRadiusToFocusVisual(Control focusVisual, FrameworkElement focusedElement, Thickness focusVisualMargin)
542+
{
543+
var cornerRadius = GetCornerRadiusForFocusedElement(focusedElement);
544+
if (cornerRadius is CornerRadius focusedCornerRadius && focusedCornerRadius != default)
545+
{
546+
var focusVisualCornerRadius = new CornerRadius(
547+
GetSumIfSourceIsNonZero(focusedCornerRadius.TopLeft, -(focusVisualMargin.Left + focusVisualMargin.Top) / 2),
548+
GetSumIfSourceIsNonZero(focusedCornerRadius.TopRight, -(focusVisualMargin.Right + focusVisualMargin.Top) / 2),
549+
GetSumIfSourceIsNonZero(focusedCornerRadius.BottomLeft, -(focusVisualMargin.Left + focusVisualMargin.Bottom) / 2),
550+
GetSumIfSourceIsNonZero(focusedCornerRadius.BottomRight, -(focusVisualMargin.Right + focusVisualMargin.Bottom) / 2));
551+
552+
ControlHelper.SetCornerRadius(focusVisual, focusVisualCornerRadius);
553+
var topLeftRadius = GetSumIfSourceIsNonZero(focusVisualCornerRadius.TopLeft, GetFocusVisualSecondaryThickness(focusedElement).Left);
554+
var topRightRadius = GetSumIfSourceIsNonZero(focusVisualCornerRadius.TopRight, GetFocusVisualSecondaryThickness(focusedElement).Right);
555+
var bottomRightRadius = GetSumIfSourceIsNonZero(focusVisualCornerRadius.BottomLeft, GetFocusVisualSecondaryThickness(focusedElement).Left);
556+
var bottomLeftRadius = GetSumIfSourceIsNonZero(focusVisualCornerRadius.BottomRight, GetFocusVisualSecondaryThickness(focusedElement).Right);
557+
558+
SetFocusVisualPrimaryCornerRadius(focusVisual, new CornerRadius(topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius));
559+
}
560+
}
561+
562+
private static CornerRadius? GetCornerRadiusForFocusedElement(FrameworkElement focusedElement)
563+
{
564+
var cornerRadiusTarget = focusedElement.GetValue(TemplateFocusTargetProperty) as FrameworkElement;
565+
cornerRadiusTarget ??= focusedElement;
566+
return cornerRadiusTarget switch
567+
{
568+
var _ when cornerRadiusTarget.GetValue(Border.CornerRadiusProperty) is CornerRadius borderResult && borderResult != default => borderResult,
569+
var _ when cornerRadiusTarget.GetValue(ControlHelper.CornerRadiusProperty) is CornerRadius controlResult => controlResult,
570+
_ => null
571+
};
572+
}
573+
513574
private static void TransferValue(DependencyObject source, DependencyObject target, DependencyProperty dp)
514575
{
515576
if (!source.HasDefaultValue(dp))
@@ -518,6 +579,12 @@ private static void TransferValue(DependencyObject source, DependencyObject targ
518579
}
519580
}
520581

582+
private static double GetSumIfSourceIsNonZero(double source, double adjustment) => source switch
583+
{
584+
0 => 0,
585+
_ => source + adjustment
586+
};
587+
521588
private sealed class FocusVisualAdorner : Adorner
522589
{
523590
public FocusVisualAdorner(Control focusedElement, UIElement adornedElement, Style focusVisualStyle) : base(adornedElement)
@@ -531,13 +598,18 @@ public FocusVisualAdorner(Control focusedElement, UIElement adornedElement, Styl
531598
Control control = new Control();
532599
SetIsSystemFocusVisual(control, false);
533600
control.Style = focusVisualStyle;
534-
control.Margin = GetFocusVisualMargin(focusedElement);
601+
602+
var focusVisualMargin = GetFocusVisualMargin(focusedElement);
603+
control.Margin = focusVisualMargin;
604+
605+
ApplyCornerRadiusToFocusVisual(control, focusedElement, focusVisualMargin);
606+
535607
TransferValue(focusedElement, control, FocusVisualPrimaryBrushProperty);
536608
TransferValue(focusedElement, control, FocusVisualPrimaryThicknessProperty);
537609
TransferValue(focusedElement, control, FocusVisualSecondaryBrushProperty);
538610
TransferValue(focusedElement, control, FocusVisualSecondaryThicknessProperty);
539611
_adorderChild = control;
540-
IsClipEnabled = true;
612+
IsClipEnabled = false;
541613
IsHitTestVisible = false;
542614
IsEnabled = false;
543615
AddVisualChild(_adorderChild);

0 commit comments

Comments
 (0)