diff --git a/demo/Ursa.Demo/Converters/IconNameToPathConverter.cs b/demo/Ursa.Demo/Converters/IconNameToPathConverter.cs
new file mode 100644
index 0000000..5a602e8
--- /dev/null
+++ b/demo/Ursa.Demo/Converters/IconNameToPathConverter.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Globalization;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data.Converters;
+using Avalonia.Media;
+
+namespace Ursa.Demo.Converters;
+
+public class IconNameToPathConverter: IValueConverter
+{
+ private string[] paths = new[]
+ {
+ "M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z",
+ "M16 12L9 2L2 12H3.86L0 18H7V22H11V18H18L14.14 12H16M20.14 12H22L15 2L12.61 5.41L17.92 13H15.97L19.19 18H24L20.14 12M13 19H17V22H13V19Z",
+ "M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z",
+ "M5 21C3.9 21 3 20.1 3 19V5C3 3.9 3.9 3 5 3H19C20.1 3 21 3.9 21 5V19C21 20.1 20.1 21 19 21H5M15.3 16L13.2 13.9L17 10L14.2 7.2L10.4 11.1L8.2 8.9V16H15.3Z",
+ "M16,9V7H12V12.5C11.58,12.19 11.07,12 10.5,12A2.5,2.5 0 0,0 8,14.5A2.5,2.5 0 0,0 10.5,17A2.5,2.5 0 0,0 13,14.5V9H16M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2Z",
+ "M16.67,4H15V2H9V4H7.33A1.33,1.33 0 0,0 6,5.33V20.67C6,21.4 6.6,22 7.33,22H16.67A1.33,1.33 0 0,0 18,20.67V5.33C18,4.6 17.4,4 16.67,4Z",
+ "M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12S17.5 2 12 2M12.5 13H11V7H12.5V11.3L16.2 9.2L17 10.5L12.5 13Z"
+ };
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is int i)
+ {
+ string s = paths[i % paths.Length];
+ return StreamGeometry.Parse(s);
+ }
+ return AvaloniaProperty.UnsetValue;
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ return AvaloniaProperty.UnsetValue;
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Models/MenuKeys.cs b/demo/Ursa.Demo/Models/MenuKeys.cs
index ea8f8f5..56e6a49 100644
--- a/demo/Ursa.Demo/Models/MenuKeys.cs
+++ b/demo/Ursa.Demo/Models/MenuKeys.cs
@@ -19,6 +19,7 @@ public static class MenuKeys
public const string MenuKeyLoading = "Loading";
public const string MenuKeyMessageBox = "MessageBox";
public const string MenuKeyNavigation = "Navigation";
+ public const string MenuKeyNavMenu = "NavMenu";
public const string MenuKeyNumericUpDown = "NumericUpDown";
public const string MenuKeyPagination = "Pagination";
public const string MenuKeyRangeSlider = "RangeSlider";
diff --git a/demo/Ursa.Demo/Pages/NavMenuDemo.axaml b/demo/Ursa.Demo/Pages/NavMenuDemo.axaml
new file mode 100644
index 0000000..f1ac1cd
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/NavMenuDemo.axaml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+ Collapse
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/Ursa.Demo/Pages/NavMenuDemo.axaml.cs b/demo/Ursa.Demo/Pages/NavMenuDemo.axaml.cs
new file mode 100644
index 0000000..eac27af
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/NavMenuDemo.axaml.cs
@@ -0,0 +1,27 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Shapes;
+using Avalonia.Input;
+using Avalonia.LogicalTree;
+using Avalonia.Markup.Xaml;
+using Ursa.Demo.ViewModels;
+
+namespace Ursa.Demo.Pages;
+
+public partial class NavMenuDemo : UserControl
+{
+ public NavMenuDemo()
+ {
+ InitializeComponent();
+ this.DataContext = new NavMenuDemoViewModel();
+ }
+
+ private void InputElement_OnPointerPressed(object? sender, PointerPressedEventArgs e)
+ {
+ if (sender is Rectangle c)
+ {
+ c.ApplyStyling();
+ var ancestors = c.GetLogicalAncestors();
+ }
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
index 0a20fe2..43166bd 100644
--- a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
@@ -41,6 +41,7 @@ public class MainViewViewModel : ViewModelBase
MenuKeys.MenuKeyLoading => new LoadingDemoViewModel(),
MenuKeys.MenuKeyMessageBox => new MessageBoxDemoViewModel(),
MenuKeys.MenuKeyNavigation => new NavigationMenuDemoViewModel(),
+ MenuKeys.MenuKeyNavMenu => new NavMenuDemoViewModel(),
MenuKeys.MenuKeyNumericUpDown => new NumericUpDownDemoViewModel(),
MenuKeys.MenuKeyPagination => new PaginationDemoViewModel(),
MenuKeys.MenuKeyRangeSlider => new RangeSliderDemoViewModel(),
diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
index 1377af9..6f6da25 100644
--- a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
@@ -28,6 +28,7 @@ public class MenuViewModel: ViewModelBase
new() { MenuHeader = "Loading", Key = MenuKeys.MenuKeyLoading },
new() { MenuHeader = "Message Box", Key = MenuKeys.MenuKeyMessageBox, Status = "New" },
new() { MenuHeader = "Navigation", Key = MenuKeys.MenuKeyNavigation, Status = "WIP" },
+ new() { MenuHeader = "Nav Menu", Key = MenuKeys.MenuKeyNavMenu, Status = "WIP"},
new() { MenuHeader = "NumericUpDown", Key = MenuKeys.MenuKeyNumericUpDown, Status = "New" },
new() { MenuHeader = "Pagination", Key = MenuKeys.MenuKeyPagination },
new() { MenuHeader = "RangeSlider", Key = MenuKeys.MenuKeyRangeSlider, Status = "New"},
diff --git a/demo/Ursa.Demo/ViewModels/NavMenuDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/NavMenuDemoViewModel.cs
new file mode 100644
index 0000000..66bec4c
--- /dev/null
+++ b/demo/Ursa.Demo/ViewModels/NavMenuDemoViewModel.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Ursa.Controls;
+namespace Ursa.Demo.ViewModels;
+
+public class NavMenuDemoViewModel: ObservableObject
+{
+ private MenuItem? _selectedMenuItem;
+
+ public MenuItem? SelectedMenuItem
+ {
+ get=>_selectedMenuItem;
+ set => SetProperty(ref _selectedMenuItem, value);
+ }
+ public ObservableCollection