UI/SpawnMenu/UtilityTab.razor
@using Sandbox;
@using Sandbox.UI;
@inherits Panel
@namespace Sandbox
@implements IUtilityTab
@attribute [Icon("🌍")]
@attribute [Title("#spawnmenu.tab.utilities")]
@attribute [Order(0)]

<root class="tab">
    <div class="left">
        <VerticalMenu class="menuinner">
            <Options>
                @foreach ( var group in GetVisiblePages().GroupBy( x => x.Group ).OrderBy( x => x.Min( t => t.Order ) ) )
                {
                    @if ( !string.IsNullOrWhiteSpace( group.Key ) )
                    {
                        <h2>@group.Key</h2>
                    }

                    @foreach ( var type in group.OrderBy( x => x.Order ).ThenBy( x => x.Title ) )
                    {
                        <MenuOption Text="@type.Title" Icon="@type.Icon"
                            class=@( SelectedPageType == type ? "active" : "" )
                            @onclick="@(() => OnSelect( type ))">
                        </MenuOption>
                    }
                }
            </Options>
        </VerticalMenu>
    </div>

    <div class="body menuinner" @ref="PageContainer"></div>
</root>

@code
{
    TypeDescription SelectedPageType { get; set; }
    Panel PageContainer;
    UtilityPage ActivePage;

    IEnumerable<TypeDescription> GetVisiblePages()
    {
        foreach ( var type in Game.TypeLibrary.GetTypes<UtilityPage>() )
        {
            if ( type.IsAbstract ) continue;
            var instance = type.Create<UtilityPage>();
            if ( instance is null || !instance.IsPageVisible() ) continue;
            instance.Delete();
            yield return type;
        }
    }

    void OnSelect( TypeDescription type )
    {
        SelectedPageType = type;

        ActivePage?.Delete();
        ActivePage = type.Create<UtilityPage>();
        PageContainer.AddChild( ActivePage );

        StateHasChanged();
    }
}