@using System.Diagnostics.CodeAnalysis @using LucideBlazor @using ShadcnBlazor.Sidebars @inject NavigationManager Navigation @implements IDisposable @{ var url = new Uri(Navigation.Uri); } Logo Moonlight @foreach (var group in Items.GroupBy(x => x.Group)) { @if (!string.IsNullOrWhiteSpace(group.Key)) { @group.Key } @foreach (var item in group) { var isActive = item.IsExactPath ? item.Path == url.LocalPath : url.LocalPath.StartsWith(item.Path, StringComparison.OrdinalIgnoreCase); @item.Name } } @code { private readonly List Items = new(); protected override void OnInitialized() { Items.AddRange([ new() { Name = "Overview", IconType = typeof(LayoutDashboardIcon), Path = "/", IsExactPath = true }, new() { Name = "Users", IconType = typeof(UsersRoundIcon), Path = "/users", IsExactPath = false, Group = "Admin" }, ]); Navigation.LocationChanged += OnLocationChanged; } private async void OnLocationChanged(object? sender, LocationChangedEventArgs e) { try { await InvokeAsync(StateHasChanged); } catch (Exception) { // Ignored } } private record SidebarItem { public string Name { get; set; } public string Path { get; set; } public bool IsExactPath { get; set; } public string? Group { get; set; } // Used to prevent the IL-Trimming from removing this type as its dynamically assigned a type and we // need it to work properly [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public Type IconType { get; set; } } public void Dispose() { Navigation.LocationChanged -= OnLocationChanged; } }