Skip to content

Code Quality: Improved Omnibar UX 2 #17157

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Jun 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7caf1a8
Added a workaround to keep Omnibar's focus on a mode button being cli…
0x5bfa May 26, 2025
e3826fe
Added auto scroll when the arrow keys are pressed
0x5bfa May 26, 2025
58b0a4c
Update test on arrow keys while UpdateTextOnSelect is false via a new…
0x5bfa May 26, 2025
56149c3
Added EllipsisButtonToolTip
0x5bfa May 26, 2025
5da93ee
Removed unclickable backplate on BreadcrumbBar when the ellipsis is s…
0x5bfa May 27, 2025
674ad66
[WIP] Added UnfocusedStateBehaviors
0x5bfa May 27, 2025
275af9d
Updated the a11y props
0x5bfa May 27, 2025
43747cc
[WIP] Adjusting automation props
0x5bfa May 29, 2025
fd12dbb
Fixed EllipsisIsRendered check
0x5bfa May 30, 2025
02b980b
Aot safe mode change in XAML
0x5bfa May 30, 2025
062f226
Revert "[WIP] Added UnfocusedStateBehaviors"
0x5bfa May 30, 2025
97b946b
Added tooltips to BreadcrumbBarItems
0x5bfa May 30, 2025
9fdfca6
Added custom brushes for breadcrumb items
yaira2 Jun 9, 2025
c5a29d0
Reverted to previous brushes
yaira2 Jun 9, 2025
5f82d34
Fix heights of mode buttons
yaira2 Jun 9, 2025
5b51de2
Fixed typo
yaira2 Jun 9, 2025
d7e2430
Removed extra tooltip
yaira2 Jun 9, 2025
2e79619
Fixed a11y issue
yaira2 Jun 9, 2025
a391cc0
Update BreadcrumbBar.xaml
yaira2 Jun 9, 2025
640fb76
Fixed tooltip
yaira2 Jun 9, 2025
11e2f0b
Revert to path mode on lost focus
yaira2 Jun 10, 2025
d57ebac
Remove focus when pressing esc
yaira2 Jun 10, 2025
887021b
Fixed rebase
yaira2 Jun 10, 2025
9578162
Simplify code
yaira2 Jun 10, 2025
adb6e79
More focus improvements
yaira2 Jun 10, 2025
82af711
Added 'no results' to the Command Palette
yaira2 Jun 11, 2025
ee54ec0
Updated the no results message
yaira2 Jun 11, 2025
a378633
Focus path bar when using Edit Path action
yaira2 Jun 11, 2025
2f35383
Expand flyout when pressing down key
yaira2 Jun 11, 2025
3dc4020
Disable search mode
yaira2 Jun 11, 2025
28dd8cd
Added icon to edit path action
yaira2 Jun 11, 2025
3cf3da9
Added icon to search action
yaira2 Jun 11, 2025
1a5a65a
Added icon to settings action
yaira2 Jun 11, 2025
c28dfa4
Added icon to compress action
yaira2 Jun 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,11 @@ public partial class BreadcrumbBar : Control

[GeneratedDependencyProperty]
public partial object? ItemTemplate { get; set; }

[GeneratedDependencyProperty]
public partial string? EllipsisButtonToolTip { get; set; }

[GeneratedDependencyProperty]
public partial string? RootItemToolTip { get; set; }
}
}
225 changes: 111 additions & 114 deletions src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<Thickness x:Key="BreadcrumbBarItemPadding">8,0</Thickness>
<Thickness x:Key="BreadcrumbBarRootItemPadding">16,0,8,0</Thickness>
<Thickness x:Key="BreadcrumbBarItemMargin">2,0,0,0</Thickness>
<x:Double x:Key="BreadcrumbBarItemHeight">32</x:Double>

<CornerRadius x:Key="BreadcrumbBarItemCornerRadius">2,2,2,2</CornerRadius>
<CornerRadius x:Key="BreadcrumbBarChevronCornerRaduis">2,2,2,2</CornerRadius>
Expand Down Expand Up @@ -55,17 +56,17 @@
x:Name="PART_RootBreadcrumbBarItem"
Grid.Column="0"
Padding="{StaticResource BreadcrumbBarRootItemPadding}"
AutomationProperties.AccessibilityView="Content"
CornerRadius="{StaticResource BreadcrumbBarRootItemCornerRadius}">
CornerRadius="{StaticResource BreadcrumbBarRootItemCornerRadius}"
ItemToolTip="{TemplateBinding RootItemToolTip}">
<ContentPresenter Content="{Binding RootItem, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" />
</local:BreadcrumbBarItem>

<local:BreadcrumbBarItem
x:Name="PART_EllipsisBreadcrumbBarItem"
Grid.Column="1"
Margin="{StaticResource BreadcrumbBarItemMargin}"
AutomationProperties.AccessibilityView="Content"
IsEllipsis="True"
ToolTipService.ToolTip="{TemplateBinding EllipsisButtonToolTip}"
Visibility="Collapsed">
<FontIcon FontSize="{StaticResource BreadcrumbBarEllipsisFontSize}" Glyph="&#xE712;" />
</local:BreadcrumbBarItem>
Expand Down Expand Up @@ -96,7 +97,7 @@
<Setter Property="FontWeight" Value="{ThemeResource BreadcrumbBarItemFontWeight}" />

<Setter Property="Padding" Value="{ThemeResource BreadcrumbBarItemPadding}" />
<Setter Property="Height" Value="{ThemeResource BreadcrumbBarHeight}" />
<Setter Property="Height" Value="{ThemeResource BreadcrumbBarItemHeight}" />

<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
Expand All @@ -114,120 +115,116 @@
x:Name="PART_LayoutRoot"
TabFocusNavigation="Once"
XYFocusKeyboardNavigation="Enabled">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="PART_ContentColumn" Width="Auto" />
<ColumnDefinition x:Name="PART_ChevronColumn" Width="Auto" />
</Grid.ColumnDefinitions>

<!-- Clickable Area -->
<Button
x:Name="PART_ItemContentButton"
Padding="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}"
UseSystemFocusVisuals="True">
<Button.Resources>
<ResourceDictionary>
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SubtleFillColorTertiaryBrush" />
<StaticResource x:Key="ButtonBackgroundPressed" ResourceKey="SubtleFillColorSecondaryBrush" />
</ResourceDictionary>
</Button.Resources>

<FlyoutBase.AttachedFlyout>
<MenuFlyout
x:Name="PART_ItemEllipsisDropDownMenuFlyout"
Placement="Bottom"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollMode="Auto">
<MenuFlyout.MenuFlyoutPresenterStyle>
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="MaxHeight" Value="400" />
<!-- Workaround for https://github.com/files-community/Files/issues/13078 -->
<Setter Target="HighContrastAdjustment" Value="None" />
</Style>
</MenuFlyout.MenuFlyoutPresenterStyle>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>

<ContentPresenter
x:Name="PART_ItemContentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
<StackPanel AutomationProperties.Name="{TemplateBinding ItemToolTip}" Orientation="Horizontal">
<!-- Clickable Area -->
<Button
x:Name="PART_ItemContentButton"
Padding="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{ThemeResource BreadcrumbBarForegroundBrush}"
TextLineBounds="Tight" />

</Button>

<!-- Chevron -->
<Button
x:Name="PART_ItemChevronButton"
Grid.Column="1"
Margin="{StaticResource BreadcrumbBarItemMargin}"
Padding="{StaticResource BreadcrumbBarChevronPadding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Content"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{StaticResource BreadcrumbBarChevronCornerRaduis}"
Style="{StaticResource BreadcrumbBarItemChevronButtonStyle}"
UseSystemFocusVisuals="True">
<Button.Resources>
<ResourceDictionary>
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SubtleFillColorTertiaryBrush" />
<StaticResource x:Key="ButtonBackgroundPressed" ResourceKey="SubtleFillColorSecondaryBrush" />
</ResourceDictionary>
</Button.Resources>

<FlyoutBase.AttachedFlyout>
<MenuFlyout
x:Name="PART_ItemChevronDropDownMenuFlyout"
Placement="BottomEdgeAlignedLeft"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollMode="Auto">
<MenuFlyout.MenuFlyoutPresenterStyle>
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="MaxHeight" Value="400" />
<!-- Workaround for https://github.com/files-community/Files/issues/13078 -->
<Setter Target="HighContrastAdjustment" Value="None" />
</Style>
</MenuFlyout.MenuFlyoutPresenterStyle>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>

<AnimatedIcon
x:Name="PART_ItemChevronIcon"
Width="{StaticResource BreadcrumbBarChevronFontSize}"
Height="{StaticResource BreadcrumbBarChevronFontSize}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
AutomationProperties.Name="{TemplateBinding Content}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}"
ToolTipService.ToolTip="{TemplateBinding ItemToolTip}"
UseSystemFocusVisuals="True">
<Button.Resources>
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
</Button.Resources>

<FlyoutBase.AttachedFlyout>
<MenuFlyout
x:Name="PART_ItemEllipsisDropDownMenuFlyout"
Placement="Bottom"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollMode="Auto">
<MenuFlyout.MenuFlyoutPresenterStyle>
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="MaxHeight" Value="400" />
<!-- Workaround for https://github.com/files-community/Files/issues/13078 -->
<Setter Target="HighContrastAdjustment" Value="None" />
</Style>
</MenuFlyout.MenuFlyoutPresenterStyle>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>

<ContentPresenter
x:Name="PART_ItemContentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{ThemeResource BreadcrumbBarForegroundBrush}"
TextLineBounds="Tight" />

</Button>

<!-- Chevron -->
<Button
x:Name="PART_ItemChevronButton"
Margin="{StaticResource BreadcrumbBarItemMargin}"
Padding="{StaticResource BreadcrumbBarChevronPadding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AnimatedIcon.State="NormalOff"
AutomationProperties.AccessibilityView="Raw"
Foreground="{ThemeResource BreadcrumbBarForegroundBrush}"
MirroredWhenRightToLeft="True"
RenderTransformOrigin="0.5, 0.5">
<AnimatedIcon.FallbackIconSource>
<FontIconSource
FontSize="{StaticResource BreadcrumbBarChevronFontSize}"
Glyph="&#xE76C;"
IsTextScaleFactorEnabled="False" />
</AnimatedIcon.FallbackIconSource>
<animatedvisuals:AnimatedChevronRightDownSmallVisualSource />
</AnimatedIcon>

</Button>
AutomationProperties.Name="Chevron"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{StaticResource BreadcrumbBarChevronCornerRaduis}"
Style="{StaticResource BreadcrumbBarItemChevronButtonStyle}"
ToolTipService.ToolTip="{TemplateBinding ChevronToolTip}"
UseSystemFocusVisuals="True">
<Button.Resources>
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
</Button.Resources>

<FlyoutBase.AttachedFlyout>
<MenuFlyout
x:Name="PART_ItemChevronDropDownMenuFlyout"
Placement="BottomEdgeAlignedLeft"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollMode="Auto">
<MenuFlyout.MenuFlyoutPresenterStyle>
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="MaxHeight" Value="400" />
<!-- Workaround for https://github.com/files-community/Files/issues/13078 -->
<Setter Target="HighContrastAdjustment" Value="None" />
</Style>
</MenuFlyout.MenuFlyoutPresenterStyle>
</MenuFlyout>
</FlyoutBase.AttachedFlyout>

<AnimatedIcon
x:Name="PART_ItemChevronIcon"
Width="{StaticResource BreadcrumbBarChevronFontSize}"
Height="{StaticResource BreadcrumbBarChevronFontSize}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AnimatedIcon.State="NormalOff"
AutomationProperties.AccessibilityView="Raw"
Foreground="{ThemeResource BreadcrumbBarForegroundBrush}"
MirroredWhenRightToLeft="True"
RenderTransformOrigin="0.5, 0.5">
<AnimatedIcon.FallbackIconSource>
<FontIconSource
FontSize="{StaticResource BreadcrumbBarChevronFontSize}"
Glyph="&#xE76C;"
IsTextScaleFactorEnabled="False" />
</AnimatedIcon.FallbackIconSource>
<animatedvisuals:AnimatedChevronRightDownSmallVisualSource />
</AnimatedIcon>

</Button>
</StackPanel>

<VisualStateManager.VisualStateGroups>

Expand Down
15 changes: 15 additions & 0 deletions src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarItem.Events.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using Microsoft.UI.Xaml.Input;
using Windows.System;

namespace Files.App.Controls
{
public partial class BreadcrumbBarItem
Expand All @@ -15,6 +18,18 @@ private void ItemChevronButton_Click(object sender, RoutedEventArgs e)
FlyoutBase.ShowAttachedFlyout(_itemChevronButton);
}

private void ItemChevronButton_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Down)
FlyoutBase.ShowAttachedFlyout(_itemChevronButton);
}

private void ItemContentButton_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Down)
FlyoutBase.ShowAttachedFlyout(_itemChevronButton);
}

private void ChevronDropDownMenuFlyout_Opening(object? sender, object e)
{
if (_ownerRef is null ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ public partial class BreadcrumbBarItem
[GeneratedDependencyProperty]
public partial bool IsLastItem { get; set; }

[GeneratedDependencyProperty]
public partial string ItemToolTip { get; set; }

[GeneratedDependencyProperty]
public partial string ChevronToolTip { get; set; }

partial void OnIsEllipsisChanged(bool newValue)
{
VisualStateManager.GoToState(this, newValue ? "ChevronCollapsed" : "ChevronVisible", true);
Expand Down
2 changes: 2 additions & 0 deletions src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ protected override void OnApplyTemplate()
VisualStateManager.GoToState(this, "ChevronCollapsed", true);

_itemContentButton.Click += ItemContentButton_Click;
_itemContentButton.PreviewKeyDown += ItemContentButton_PreviewKeyDown;
_itemChevronButton.Click += ItemChevronButton_Click;
_itemChevronButton.PreviewKeyDown += ItemChevronButton_PreviewKeyDown;
_itemChevronDropDownMenuFlyout.Opening += ChevronDropDownMenuFlyout_Opening;
_itemChevronDropDownMenuFlyout.Opened += ChevronDropDownMenuFlyout_Opened;
_itemChevronDropDownMenuFlyout.Closed += ChevronDropDownMenuFlyout_Closed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ protected override string GetLocalizedControlTypeCore()

protected override object GetPatternCore(PatternInterface patternInterface)
{
if (patternInterface is PatternInterface.Invoke)
if (patternInterface is PatternInterface.ExpandCollapse or PatternInterface.Invoke)
return this;

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

protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Button;
return AutomationControlType.SplitButton;
}

/// <summary>
/// Sends a request to invoke the item associated with the automation peer.
/// </summary>
protected override bool IsControlElementCore()
{
return true;
}

/// <inheritdoc/>
public void Invoke()
{
if (Owner is not BreadcrumbBarItem item)
Expand Down
10 changes: 6 additions & 4 deletions src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ protected override Size MeasureOverride(NonVirtualizingLayoutContext context, Si
var accumulatedSize = new Size(0, 0);
_availableSize = availableSize;

var indexAfterEllipsis = GetFirstIndexToRender(context);

// Go through all items and measure them
foreach (var item in context.Children)
for (int index = 0; index < context.Children.Count; index++)
{
if (item is BreadcrumbBarItem breadcrumbItem)
if (context.Children[index] is BreadcrumbBarItem breadcrumbItem)
{
breadcrumbItem.Measure(availableSize);
accumulatedSize.Width += breadcrumbItem.DesiredSize.Width;
accumulatedSize.Width += index < indexAfterEllipsis ? 0: breadcrumbItem.DesiredSize.Width;
accumulatedSize.Height = Math.Max(accumulatedSize.Height, breadcrumbItem.DesiredSize.Height);
}
}
Expand All @@ -49,7 +51,7 @@ protected override Size MeasureOverride(NonVirtualizingLayoutContext context, Si
_ellipsisButton ??= context.Children[0] as BreadcrumbBarItem;

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

return accumulatedSize;
}
Expand Down
Loading
Loading