Browse Source

combobox - fix focus visual clipping and add selection pill to item

pull/21771/head
Emmanuel Hansen 3 weeks ago
parent
commit
6ff1b12fb9
  1. 17
      src/Avalonia.Themes.Fluent2/Controls/ComboBox.xaml
  2. 132
      src/Avalonia.Themes.Fluent2/Controls/ComboBoxItem.xaml

17
src/Avalonia.Themes.Fluent2/Controls/ComboBox.xaml

@ -60,16 +60,6 @@
<CornerRadius x:Key="ComboBoxDropDownButtonBackgroundCornerRadius">4</CornerRadius>
<StreamGeometry x:Key="ComboBoxDropDownPathData">M4.293 8.293a1 1 0 0 1 1.414 0L12 14.586l6.293-6.293a1 1 0 1 1 1.414 1.414l-7 7a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 0-1.414Z</StreamGeometry>
<ControlTheme TargetType="Rectangle" x:Key="ComboBoxItemPill">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Height" Value="{StaticResource ComboBoxItemPillHeight}" />
<Setter Property="Width" Value="{StaticResource ComboBoxItemPillWidth}" />
<Setter Property="Fill" Value="{StaticResource ComboBoxItemPillFillBrush}" />
<Setter Property="RadiusX" Value="{StaticResource ComboBoxItemPillCornerRadius}" />
<Setter Property="RadiusY" Value="{StaticResource ComboBoxItemPillCornerRadius}" />
<Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
</ControlTheme>
<!-- WinUI reference: ComboBox_themeresources.xaml (DefaultComboBoxStyle), 820 lines.
Closed control is Button-like: ControlFillColorDefault fill with a ControlElevationBorder
(both via the re-pointed ComboBox* aliases), radius 4 (ControlCornerRadius), background
@ -108,10 +98,11 @@
BorderBrush="{DynamicResource ComboBoxBackgroundBorderBrushUnfocused}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
IsVisible="False"/>
Opacity="0"/>
<Border x:Name="Background"
Grid.Column="0"
Grid.ColumnSpan="2"
TemplatedControl.IsTemplateFocusTarget="True"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"
@ -124,7 +115,7 @@
</Transitions>
</Border.Transitions>
</Border>
<Rectangle x:Name="Pill" Theme="{DynamicResource ComboBoxItemPill}" Margin="1,0,0,0" Grid.Column="0" Opacity="0">
<Rectangle x:Name="Pill" Theme="{StaticResource ComboBoxItemPill}" Margin="1,0,0,0" Grid.Column="0" Opacity="0">
<Rectangle.RenderTransform>
<ScaleTransform ScaleY="1"/>
</Rectangle.RenderTransform>
@ -264,7 +255,7 @@
<!-- Focused State -->
<Style Selector="^:focus-visible">
<Style Selector="^ /template/ Border#HighlightBackground">
<Setter Property="IsVisible" Value="True" />
<Setter Property="Opacity" Value="1" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxBackgroundBorderBrushFocused}" />
</Style>
<Style Selector="^ /template/ Rectangle#Pill">

132
src/Avalonia.Themes.Fluent2/Controls/ComboBoxItem.xaml

@ -16,114 +16,144 @@
</Design.PreviewWith>
<!-- WinUI reference: ComboBox_themeresources.xaml (DefaultComboBoxItemStyle + ComboBoxItemPill).
Items are rounded (ComboBoxItemCornerRadius = 3), inset 5,2 from the dropdown edges
(LayoutRoot margin in WinUI), padded 11,5,11,7 (ComboBoxItemThemePadding, shared resource),
with an accent selection pill (ComboBoxItemPillWidth x ComboBoxItemPillHeight = 3x16, r1.5)
whose height WinUI animates over 167ms (ComboBoxItemScaleAnimationDuration). -->
Items are rounded (ComboBoxItemCornerRadius = 3), inset 5,2 from the dropdown edges
(LayoutRoot margin in WinUI), padded 11,5,11,7 (ComboBoxItemThemePadding, shared resource),
with an accent selection pill (ComboBoxItemPillWidth x ComboBoxItemPillHeight = 3x16, r1.5)
whose height WinUI animates over 167ms (ComboBoxItemScaleAnimationDuration). -->
<CornerRadius x:Key="ComboBoxItemCornerRadius">3</CornerRadius>
<x:Double x:Key="ComboBoxItemPillWidth">3</x:Double>
<x:Double x:Key="ComboBoxItemPillHeight">16</x:Double>
<x:Double x:Key="ComboBoxItemPillMinScale">0.625</x:Double>
<ControlTheme TargetType="Rectangle" x:Key="ComboBoxItemPill">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Height" Value="{StaticResource ComboBoxItemPillHeight}" />
<Setter Property="Width" Value="{StaticResource ComboBoxItemPillWidth}" />
<Setter Property="Fill" Value="{StaticResource ComboBoxItemPillFillBrush}" />
<Setter Property="RadiusX" Value="{StaticResource ComboBoxItemPillCornerRadius}" />
<Setter Property="RadiusY" Value="{StaticResource ComboBoxItemPillCornerRadius}" />
<Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
</ControlTheme>
<ControlTheme x:Key="{x:Type ComboBoxItem}" TargetType="ComboBoxItem">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForeground}" />
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackground}" />
<Setter Property="Padding" Value="{DynamicResource ComboBoxItemThemePadding}" />
<Setter Property="CornerRadius" Value="{DynamicResource ComboBoxItemCornerRadius}" />
<!--Winui uses system focus visuals, which ignores visual clipping. Avalonia focus visual is clipped by the target, thus we disable clipping on the combobox item and clip instead in the root border-->
<Setter Property="ClipToBounds" Value="False" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<ControlTemplate>
<!-- Margin matches WinUI's LayoutRoot margin (5,2,5,2). -->
<Panel Margin="5,2,5,2">
<ContentPresenter Name="PART_ContentPresenter"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
BackgroundSizing="InnerBorderEdge"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Padding="{TemplateBinding Padding}" />
<!-- Selection pill, scale-animated like the ListBoxItem one. ComboBoxItemPillFillBrush is
not aliased in this theme yet, so the Fluent 2 token AccentFillColorDefaultBrush is
referenced directly. -->
<Rectangle Name="SelectionIndicator"
IsVisible="False"
Width="{DynamicResource ComboBoxItemPillWidth}"
Height="{DynamicResource ComboBoxItemPillHeight}"
RadiusX="1.5"
RadiusY="1.5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
IsHitTestVisible="False"
UseLayoutRounding="False"
RenderTransform="scaleY(0)"
Fill="{DynamicResource AccentFillColorDefaultBrush}">
<Rectangle.Transitions>
<Transitions>
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.167" Easing="0,0 0,1" />
</Transitions>
</Rectangle.Transitions>
</Rectangle>
</Panel>
<Border Name="LayoutRoot"
Margin="5,2,5,2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
TemplatedControl.IsTemplateFocusTarget="True"
ClipToBounds="True"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid ClipToBounds="True">
<Rectangle Name="Pill"
Theme="{DynamicResource ComboBoxItemPill}"
Opacity="0"
IsHitTestVisible="False"
UseLayoutRounding="False"
RenderTransform="scaleY(1)"/>
<ContentPresenter Name="PART_ContentPresenter"
Foreground="{TemplateBinding Foreground}"
BackgroundSizing="InnerBorderEdge"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}" />
</Grid>
</Border>
</ControlTemplate>
</Setter>
<!-- PointerOver state -->
<Style Selector="^:pointerover /template/ ContentPresenter">
<Style Selector="^:pointerover /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushPointerOver}" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundPointerOver}" />
</Style>
<!-- Disabled state -->
<Style Selector="^:disabled /template/ ContentPresenter">
<Style Selector="^:disabled /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushDisabled}" />
</Style>
<Style Selector="^:disabled /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundDisabled}" />
</Style>
<!-- Pressed state -->
<Style Selector="^:pressed /template/ ContentPresenter">
<Style Selector="^:pressed /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushPressed}" />
</Style>
<Style Selector="^:pressed /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundPressed}" />
</Style>
<!-- Focused state -->
<Style Selector="^:focus /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelected}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelected}" />
</Style>
<Style Selector="^:focus /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelected}" />
</Style>
<!-- Selected state -->
<Style Selector="^:selected">
<Style Selector="^ /template/ ContentPresenter">
<Style Selector="^ /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelected}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelected}" />
</Style>
<Style Selector="^ /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelected}" />
</Style>
<Style Selector="^ /template/ Rectangle#SelectionIndicator">
<Setter Property="IsVisible" Value="True" />
<Setter Property="RenderTransform" Value="scaleY(1)" />
<Style Selector="^ /template/ Rectangle#Pill">
<Setter Property="Opacity" Value="1" />
</Style>
<!-- Selected Disabled state -->
<Style Selector="^:disabled /template/ ContentPresenter">
<Style Selector="^:disabled /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedDisabled}" />
</Style>
<Style Selector="^:disabled /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedDisabled}" />
</Style>
<Style Selector="^:disabled /template/ Rectangle#SelectionIndicator">
<Style Selector="^:disabled /template/ Rectangle#Pill">
<Setter Property="Fill" Value="{DynamicResource AccentFillColorDisabledBrush}" />
</Style>
<!-- Selected PointerOver state -->
<Style Selector="^:pointerover /template/ ContentPresenter">
<Style Selector="^:pointerover /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedPointerOver}" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedPointerOver}" />
</Style>
<!-- Selected Pressed state -->
<Style Selector="^:pressed /template/ ContentPresenter">
<Style Selector="^:pressed /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedPressed}" />
</Style>
<Style Selector="^:pressed /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedPressed}" />
</Style>
<Style Selector="^:pressed /template/ Rectangle#Pill">
<Setter Property="RenderTransform" >
<ScaleTransform ScaleY="{DynamicResource ComboBoxItemPillMinScale}" />
</Setter>
</Style>
</Style>
</ControlTheme>
</ResourceDictionary>

Loading…
Cancel
Save