Skip to content

Commit 083ef0e

Browse files
0x5bfayaira2
andauthored
Code Quality: Improved Omnibar UX 2 (#17157)
Co-authored-by: Yair <[email protected]>
1 parent 6b5bf5b commit 083ef0e

20 files changed

+261
-149
lines changed

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.Properties.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,11 @@ public partial class BreadcrumbBar : Control
1515

1616
[GeneratedDependencyProperty]
1717
public partial object? ItemTemplate { get; set; }
18+
19+
[GeneratedDependencyProperty]
20+
public partial string? EllipsisButtonToolTip { get; set; }
21+
22+
[GeneratedDependencyProperty]
23+
public partial string? RootItemToolTip { get; set; }
1824
}
1925
}

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.xaml

Lines changed: 111 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<Thickness x:Key="BreadcrumbBarItemPadding">8,0</Thickness>
1414
<Thickness x:Key="BreadcrumbBarRootItemPadding">16,0,8,0</Thickness>
1515
<Thickness x:Key="BreadcrumbBarItemMargin">2,0,0,0</Thickness>
16+
<x:Double x:Key="BreadcrumbBarItemHeight">32</x:Double>
1617

1718
<CornerRadius x:Key="BreadcrumbBarItemCornerRadius">2,2,2,2</CornerRadius>
1819
<CornerRadius x:Key="BreadcrumbBarChevronCornerRaduis">2,2,2,2</CornerRadius>
@@ -55,17 +56,17 @@
5556
x:Name="PART_RootBreadcrumbBarItem"
5657
Grid.Column="0"
5758
Padding="{StaticResource BreadcrumbBarRootItemPadding}"
58-
AutomationProperties.AccessibilityView="Content"
59-
CornerRadius="{StaticResource BreadcrumbBarRootItemCornerRadius}">
59+
CornerRadius="{StaticResource BreadcrumbBarRootItemCornerRadius}"
60+
ItemToolTip="{TemplateBinding RootItemToolTip}">
6061
<ContentPresenter Content="{Binding RootItem, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" />
6162
</local:BreadcrumbBarItem>
6263

6364
<local:BreadcrumbBarItem
6465
x:Name="PART_EllipsisBreadcrumbBarItem"
6566
Grid.Column="1"
6667
Margin="{StaticResource BreadcrumbBarItemMargin}"
67-
AutomationProperties.AccessibilityView="Content"
6868
IsEllipsis="True"
69+
ToolTipService.ToolTip="{TemplateBinding EllipsisButtonToolTip}"
6970
Visibility="Collapsed">
7071
<FontIcon FontSize="{StaticResource BreadcrumbBarEllipsisFontSize}" Glyph="&#xE712;" />
7172
</local:BreadcrumbBarItem>
@@ -96,7 +97,7 @@
9697
<Setter Property="FontWeight" Value="{ThemeResource BreadcrumbBarItemFontWeight}" />
9798

9899
<Setter Property="Padding" Value="{ThemeResource BreadcrumbBarItemPadding}" />
99-
<Setter Property="Height" Value="{ThemeResource BreadcrumbBarHeight}" />
100+
<Setter Property="Height" Value="{ThemeResource BreadcrumbBarItemHeight}" />
100101

101102
<Setter Property="HorizontalAlignment" Value="Stretch" />
102103
<Setter Property="HorizontalContentAlignment" Value="Center" />
@@ -114,120 +115,116 @@
114115
x:Name="PART_LayoutRoot"
115116
TabFocusNavigation="Once"
116117
XYFocusKeyboardNavigation="Enabled">
117-
<Grid.ColumnDefinitions>
118-
<ColumnDefinition x:Name="PART_ContentColumn" Width="Auto" />
119-
<ColumnDefinition x:Name="PART_ChevronColumn" Width="Auto" />
120-
</Grid.ColumnDefinitions>
121-
122-
<!-- Clickable Area -->
123-
<Button
124-
x:Name="PART_ItemContentButton"
125-
Padding="{TemplateBinding Padding}"
126-
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
127-
AutomationProperties.AccessibilityView="Raw"
128-
Background="{TemplateBinding Background}"
129-
BorderBrush="{TemplateBinding BorderBrush}"
130-
BorderThickness="{TemplateBinding BorderThickness}"
131-
Control.IsTemplateFocusTarget="True"
132-
CornerRadius="{TemplateBinding CornerRadius}"
133-
UseSystemFocusVisuals="True">
134-
<Button.Resources>
135-
<ResourceDictionary>
136-
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SubtleFillColorTertiaryBrush" />
137-
<StaticResource x:Key="ButtonBackgroundPressed" ResourceKey="SubtleFillColorSecondaryBrush" />
138-
</ResourceDictionary>
139-
</Button.Resources>
140-
141-
<FlyoutBase.AttachedFlyout>
142-
<MenuFlyout
143-
x:Name="PART_ItemEllipsisDropDownMenuFlyout"
144-
Placement="Bottom"
145-
ScrollViewer.VerticalScrollBarVisibility="Auto"
146-
ScrollViewer.VerticalScrollMode="Auto">
147-
<MenuFlyout.MenuFlyoutPresenterStyle>
148-
<Style TargetType="MenuFlyoutPresenter">
149-
<Setter Property="MaxHeight" Value="400" />
150-
<!-- Workaround for https://github.com/files-community/Files/issues/13078 -->
151-
<Setter Target="HighContrastAdjustment" Value="None" />
152-
</Style>
153-
</MenuFlyout.MenuFlyoutPresenterStyle>
154-
</MenuFlyout>
155-
</FlyoutBase.AttachedFlyout>
156-
157-
<ContentPresenter
158-
x:Name="PART_ItemContentPresenter"
159-
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
118+
<StackPanel AutomationProperties.Name="{TemplateBinding ItemToolTip}" Orientation="Horizontal">
119+
<!-- Clickable Area -->
120+
<Button
121+
x:Name="PART_ItemContentButton"
122+
Padding="{TemplateBinding Padding}"
160123
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
161124
AutomationProperties.AccessibilityView="Raw"
162-
Content="{TemplateBinding Content}"
163-
ContentTemplate="{TemplateBinding ContentTemplate}"
164-
ContentTransitions="{TemplateBinding ContentTransitions}"
165-
FontFamily="{TemplateBinding FontFamily}"
166-
FontSize="{TemplateBinding FontSize}"
167-
FontWeight="{TemplateBinding FontWeight}"
168-
Foreground="{ThemeResource BreadcrumbBarForegroundBrush}"
169-
TextLineBounds="Tight" />
170-
171-
</Button>
172-
173-
<!-- Chevron -->
174-
<Button
175-
x:Name="PART_ItemChevronButton"
176-
Grid.Column="1"
177-
Margin="{StaticResource BreadcrumbBarItemMargin}"
178-
Padding="{StaticResource BreadcrumbBarChevronPadding}"
179-
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
180-
AutomationProperties.AccessibilityView="Content"
181-
Background="{TemplateBinding Background}"
182-
BorderBrush="{TemplateBinding BorderBrush}"
183-
BorderThickness="{TemplateBinding BorderThickness}"
184-
CornerRadius="{StaticResource BreadcrumbBarChevronCornerRaduis}"
185-
Style="{StaticResource BreadcrumbBarItemChevronButtonStyle}"
186-
UseSystemFocusVisuals="True">
187-
<Button.Resources>
188-
<ResourceDictionary>
189-
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SubtleFillColorTertiaryBrush" />
190-
<StaticResource x:Key="ButtonBackgroundPressed" ResourceKey="SubtleFillColorSecondaryBrush" />
191-
</ResourceDictionary>
192-
</Button.Resources>
193-
194-
<FlyoutBase.AttachedFlyout>
195-
<MenuFlyout
196-
x:Name="PART_ItemChevronDropDownMenuFlyout"
197-
Placement="BottomEdgeAlignedLeft"
198-
ScrollViewer.VerticalScrollBarVisibility="Auto"
199-
ScrollViewer.VerticalScrollMode="Auto">
200-
<MenuFlyout.MenuFlyoutPresenterStyle>
201-
<Style TargetType="MenuFlyoutPresenter">
202-
<Setter Property="MaxHeight" Value="400" />
203-
<!-- Workaround for https://github.com/files-community/Files/issues/13078 -->
204-
<Setter Target="HighContrastAdjustment" Value="None" />
205-
</Style>
206-
</MenuFlyout.MenuFlyoutPresenterStyle>
207-
</MenuFlyout>
208-
</FlyoutBase.AttachedFlyout>
209-
210-
<AnimatedIcon
211-
x:Name="PART_ItemChevronIcon"
212-
Width="{StaticResource BreadcrumbBarChevronFontSize}"
213-
Height="{StaticResource BreadcrumbBarChevronFontSize}"
214-
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
125+
AutomationProperties.Name="{TemplateBinding Content}"
126+
Background="{TemplateBinding Background}"
127+
BorderBrush="{TemplateBinding BorderBrush}"
128+
BorderThickness="{TemplateBinding BorderThickness}"
129+
Control.IsTemplateFocusTarget="True"
130+
CornerRadius="{TemplateBinding CornerRadius}"
131+
ToolTipService.ToolTip="{TemplateBinding ItemToolTip}"
132+
UseSystemFocusVisuals="True">
133+
<Button.Resources>
134+
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
135+
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
136+
</Button.Resources>
137+
138+
<FlyoutBase.AttachedFlyout>
139+
<MenuFlyout
140+
x:Name="PART_ItemEllipsisDropDownMenuFlyout"
141+
Placement="Bottom"
142+
ScrollViewer.VerticalScrollBarVisibility="Auto"
143+
ScrollViewer.VerticalScrollMode="Auto">
144+
<MenuFlyout.MenuFlyoutPresenterStyle>
145+
<Style TargetType="MenuFlyoutPresenter">
146+
<Setter Property="MaxHeight" Value="400" />
147+
<!-- Workaround for https://github.com/files-community/Files/issues/13078 -->
148+
<Setter Target="HighContrastAdjustment" Value="None" />
149+
</Style>
150+
</MenuFlyout.MenuFlyoutPresenterStyle>
151+
</MenuFlyout>
152+
</FlyoutBase.AttachedFlyout>
153+
154+
<ContentPresenter
155+
x:Name="PART_ItemContentPresenter"
156+
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
157+
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
158+
AutomationProperties.AccessibilityView="Raw"
159+
Content="{TemplateBinding Content}"
160+
ContentTemplate="{TemplateBinding ContentTemplate}"
161+
ContentTransitions="{TemplateBinding ContentTransitions}"
162+
FontFamily="{TemplateBinding FontFamily}"
163+
FontSize="{TemplateBinding FontSize}"
164+
FontWeight="{TemplateBinding FontWeight}"
165+
Foreground="{ThemeResource BreadcrumbBarForegroundBrush}"
166+
TextLineBounds="Tight" />
167+
168+
</Button>
169+
170+
<!-- Chevron -->
171+
<Button
172+
x:Name="PART_ItemChevronButton"
173+
Margin="{StaticResource BreadcrumbBarItemMargin}"
174+
Padding="{StaticResource BreadcrumbBarChevronPadding}"
215175
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
216-
AnimatedIcon.State="NormalOff"
217176
AutomationProperties.AccessibilityView="Raw"
218-
Foreground="{ThemeResource BreadcrumbBarForegroundBrush}"
219-
MirroredWhenRightToLeft="True"
220-
RenderTransformOrigin="0.5, 0.5">
221-
<AnimatedIcon.FallbackIconSource>
222-
<FontIconSource
223-
FontSize="{StaticResource BreadcrumbBarChevronFontSize}"
224-
Glyph="&#xE76C;"
225-
IsTextScaleFactorEnabled="False" />
226-
</AnimatedIcon.FallbackIconSource>
227-
<animatedvisuals:AnimatedChevronRightDownSmallVisualSource />
228-
</AnimatedIcon>
229-
230-
</Button>
177+
AutomationProperties.Name="Chevron"
178+
Background="{TemplateBinding Background}"
179+
BorderBrush="{TemplateBinding BorderBrush}"
180+
BorderThickness="{TemplateBinding BorderThickness}"
181+
CornerRadius="{StaticResource BreadcrumbBarChevronCornerRaduis}"
182+
Style="{StaticResource BreadcrumbBarItemChevronButtonStyle}"
183+
ToolTipService.ToolTip="{TemplateBinding ChevronToolTip}"
184+
UseSystemFocusVisuals="True">
185+
<Button.Resources>
186+
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
187+
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
188+
</Button.Resources>
189+
190+
<FlyoutBase.AttachedFlyout>
191+
<MenuFlyout
192+
x:Name="PART_ItemChevronDropDownMenuFlyout"
193+
Placement="BottomEdgeAlignedLeft"
194+
ScrollViewer.VerticalScrollBarVisibility="Auto"
195+
ScrollViewer.VerticalScrollMode="Auto">
196+
<MenuFlyout.MenuFlyoutPresenterStyle>
197+
<Style TargetType="MenuFlyoutPresenter">
198+
<Setter Property="MaxHeight" Value="400" />
199+
<!-- Workaround for https://github.com/files-community/Files/issues/13078 -->
200+
<Setter Target="HighContrastAdjustment" Value="None" />
201+
</Style>
202+
</MenuFlyout.MenuFlyoutPresenterStyle>
203+
</MenuFlyout>
204+
</FlyoutBase.AttachedFlyout>
205+
206+
<AnimatedIcon
207+
x:Name="PART_ItemChevronIcon"
208+
Width="{StaticResource BreadcrumbBarChevronFontSize}"
209+
Height="{StaticResource BreadcrumbBarChevronFontSize}"
210+
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
211+
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
212+
AnimatedIcon.State="NormalOff"
213+
AutomationProperties.AccessibilityView="Raw"
214+
Foreground="{ThemeResource BreadcrumbBarForegroundBrush}"
215+
MirroredWhenRightToLeft="True"
216+
RenderTransformOrigin="0.5, 0.5">
217+
<AnimatedIcon.FallbackIconSource>
218+
<FontIconSource
219+
FontSize="{StaticResource BreadcrumbBarChevronFontSize}"
220+
Glyph="&#xE76C;"
221+
IsTextScaleFactorEnabled="False" />
222+
</AnimatedIcon.FallbackIconSource>
223+
<animatedvisuals:AnimatedChevronRightDownSmallVisualSource />
224+
</AnimatedIcon>
225+
226+
</Button>
227+
</StackPanel>
231228

232229
<VisualStateManager.VisualStateGroups>
233230

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarItem.Events.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4+
using Microsoft.UI.Xaml.Input;
5+
using Windows.System;
6+
47
namespace Files.App.Controls
58
{
69
public partial class BreadcrumbBarItem
@@ -15,6 +18,18 @@ private void ItemChevronButton_Click(object sender, RoutedEventArgs e)
1518
FlyoutBase.ShowAttachedFlyout(_itemChevronButton);
1619
}
1720

21+
private void ItemChevronButton_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
22+
{
23+
if (e.Key == VirtualKey.Down)
24+
FlyoutBase.ShowAttachedFlyout(_itemChevronButton);
25+
}
26+
27+
private void ItemContentButton_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
28+
{
29+
if (e.Key == VirtualKey.Down)
30+
FlyoutBase.ShowAttachedFlyout(_itemChevronButton);
31+
}
32+
1833
private void ChevronDropDownMenuFlyout_Opening(object? sender, object e)
1934
{
2035
if (_ownerRef is null ||

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarItem.Properties.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ public partial class BreadcrumbBarItem
1313
[GeneratedDependencyProperty]
1414
public partial bool IsLastItem { get; set; }
1515

16+
[GeneratedDependencyProperty]
17+
public partial string ItemToolTip { get; set; }
18+
19+
[GeneratedDependencyProperty]
20+
public partial string ChevronToolTip { get; set; }
21+
1622
partial void OnIsEllipsisChanged(bool newValue)
1723
{
1824
VisualStateManager.GoToState(this, newValue ? "ChevronCollapsed" : "ChevronVisible", true);

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarItem.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ protected override void OnApplyTemplate()
4747
VisualStateManager.GoToState(this, "ChevronCollapsed", true);
4848

4949
_itemContentButton.Click += ItemContentButton_Click;
50+
_itemContentButton.PreviewKeyDown += ItemContentButton_PreviewKeyDown;
5051
_itemChevronButton.Click += ItemChevronButton_Click;
52+
_itemChevronButton.PreviewKeyDown += ItemChevronButton_PreviewKeyDown;
5153
_itemChevronDropDownMenuFlyout.Opening += ChevronDropDownMenuFlyout_Opening;
5254
_itemChevronDropDownMenuFlyout.Opened += ChevronDropDownMenuFlyout_Opened;
5355
_itemChevronDropDownMenuFlyout.Closed += ChevronDropDownMenuFlyout_Closed;

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarItemAutomationPeer.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ protected override string GetLocalizedControlTypeCore()
2424

2525
protected override object GetPatternCore(PatternInterface patternInterface)
2626
{
27-
if (patternInterface is PatternInterface.Invoke)
27+
if (patternInterface is PatternInterface.ExpandCollapse or PatternInterface.Invoke)
2828
return this;
2929

3030
return base.GetPatternCore(patternInterface);
@@ -37,12 +37,15 @@ protected override string GetClassNameCore()
3737

3838
protected override AutomationControlType GetAutomationControlTypeCore()
3939
{
40-
return AutomationControlType.Button;
40+
return AutomationControlType.SplitButton;
4141
}
4242

43-
/// <summary>
44-
/// Sends a request to invoke the item associated with the automation peer.
45-
/// </summary>
43+
protected override bool IsControlElementCore()
44+
{
45+
return true;
46+
}
47+
48+
/// <inheritdoc/>
4649
public void Invoke()
4750
{
4851
if (Owner is not BreadcrumbBarItem item)

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarLayout.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ protected override Size MeasureOverride(NonVirtualizingLayoutContext context, Si
3333
var accumulatedSize = new Size(0, 0);
3434
_availableSize = availableSize;
3535

36+
var indexAfterEllipsis = GetFirstIndexToRender(context);
37+
3638
// Go through all items and measure them
37-
foreach (var item in context.Children)
39+
for (int index = 0; index < context.Children.Count; index++)
3840
{
39-
if (item is BreadcrumbBarItem breadcrumbItem)
41+
if (context.Children[index] is BreadcrumbBarItem breadcrumbItem)
4042
{
4143
breadcrumbItem.Measure(availableSize);
42-
accumulatedSize.Width += breadcrumbItem.DesiredSize.Width;
44+
accumulatedSize.Width += index < indexAfterEllipsis ? 0: breadcrumbItem.DesiredSize.Width;
4345
accumulatedSize.Height = Math.Max(accumulatedSize.Height, breadcrumbItem.DesiredSize.Height);
4446
}
4547
}
@@ -49,7 +51,7 @@ protected override Size MeasureOverride(NonVirtualizingLayoutContext context, Si
4951
_ellipsisButton ??= context.Children[0] as BreadcrumbBarItem;
5052

5153
// Sets the ellipsis item's visibility based on whether the items are overflowing
52-
EllipsisIsRendered = accumulatedSize.Width > availableSize.Width;
54+
EllipsisIsRendered = indexAfterEllipsis is not 0;
5355

5456
return accumulatedSize;
5557
}

0 commit comments

Comments
 (0)