Skip to content
ConsoleMonster

Settings tabs

Tabs for each settings page, an outline that opens the section you pick and a breadcrumb that shows where you are.

Demos Terminal apps

Use it when a tool has more settings than fit on one screen and people jump between groups.

  • Live
  • 88×22
  • PowerShell 7.4+
  • .NET 8.0+
Settings tabs 88×2224-bitFull

How it's built

The whole program in one file, with its sample data at the top. It drew the recording above; all three styles produce the same frame bytes.

PowerShellsettings-tabs.ps1View on GitHub
# Settings across tabs, with an outline that opens each section and a breadcrumb that shows where you are.

Import-Module -Name ConsoleMonster
# All data is synthetic and inline; no services are contacted or changed.

# Layout: construct the widgets shown on screen.
$proxy = New-ConsoleCollapsible -Key Proxy -Expanded -Content {
    New-ConsoleTextInput -Key ProxyServer -Label 'Server' -Value 'proxy.contoso.test:8080'
    New-ConsoleToggle -Key ProxyBypass -Label 'Bypass for local addresses' -Value $true
}
$dns = New-ConsoleCollapsible -Key DNS -Content {
    New-ConsoleTextInput -Key DnsServers -Label 'Servers' -Value '10.0.0.53, 10.0.1.53'
    New-ConsoleTextInput -Key DnsSuffix -Label 'Search suffix' -Value 'corp.contoso.test'
}
$firewall = New-ConsoleCollapsible -Key Firewall -Content {
    New-ConsoleToggle -Key FirewallOn -Label 'Enabled' -Value $true
    New-ConsoleTextInput -Key FirewallPorts -Label 'Allowed ports' -Value '443, 8443'
}
$sections = New-ConsoleOutline -Key Sections -CurrentIndex 0 -Item @(
    [pscustomobject]@{ Title = 'Proxy'; Target = $proxy }
    [pscustomobject]@{ Title = 'DNS'; Target = $dns }
    [pscustomobject]@{ Title = 'Firewall'; Target = $firewall }
)
$general = New-ConsoleRows -Content {
    New-ConsoleTextInput -Key DisplayName -Label 'Display name' -Value 'Contoso Operations'
    New-ConsoleToggle -Key StartAtLogon -Label 'Start at logon' -Value $false
}
$network = New-ConsoleRows -Content {
    New-ConsoleBreadcrumb -Key Where -Ancestor 'Settings', 'Network' -Outline $sections
    New-ConsoleSplitter -Ratio 0.25 -First { $sections } -Second { $proxy; $dns; $firewall }
}
$logging = New-ConsoleRows -Content {
    New-ConsoleTextInput -Key LogPath -Label 'Folder' -Value 'C:\Logs\Operations'
    New-ConsoleToggle -Key LogVerbose -Label 'Verbose' -Value $false
}
$content = {
    New-ConsoleTabs -Content {
        @{ Title = 'General'; Content = $general }
        @{ Title = 'Network'; Content = $network }
        @{ Title = 'Logging'; Content = $logging }
    }
}

# Behaviour: Ctrl+PageUp/PageDown switch tabs, Enter on an outline entry opens its section; Escape exits.
Show-ConsoleApp -Content $content
C#Program.csView on GitHub
// Settings across tabs, with an outline that opens each section and a breadcrumb that shows where you are.
// All data is synthetic and inline; no services are contacted or changed.
using ConsoleMonster.Interactive;
using ConsoleMonster.Layout;
using ConsoleMonster.Widgets;

// Layout: construct the widgets shown on screen.
Collapsible proxy = new Collapsible("Proxy", new Rows(
    new TextInput("ProxyServer", "proxy.contoso.test:8080") { Label = "Server" },
    new Toggle("ProxyBypass", true) { Label = "Bypass for local addresses" }))
{
    Expanded = true
};
Collapsible dns = new Collapsible("DNS", new Rows(
    new TextInput("DnsServers", "10.0.0.53, 10.0.1.53") { Label = "Servers" },
    new TextInput("DnsSuffix", "corp.contoso.test") { Label = "Search suffix" }));
Collapsible firewall = new Collapsible("Firewall", new Rows(
    new Toggle("FirewallOn", true) { Label = "Enabled" },
    new TextInput("FirewallPorts", "443, 8443") { Label = "Allowed ports" }));
Outline sections = new Outline("Sections")
{
    Items =
    {
        new OutlineItem("Proxy") { Target = proxy },
        new OutlineItem("DNS") { Target = dns },
        new OutlineItem("Firewall") { Target = firewall }
    },
    CurrentIndex = 0
};
Breadcrumb where = new Breadcrumb("Where")
{
    Ancestors = { "Settings", "Network" },
    Outline = sections
};
Tabs layout = new Tabs()
    .Add("General", new Rows(
        new TextInput("DisplayName", "Contoso Operations") { Label = "Display name" },
        new Toggle("StartAtLogon", false) { Label = "Start at logon" }))
    .Add("Network", new Rows(
        where,
        new Splitter(sections, new Rows(proxy, dns, firewall)) { Ratio = 0.25 }))
    .Add("Logging", new Rows(
        new TextInput("LogPath", "C:\\Logs\\Operations") { Label = "Folder" },
        new Toggle("LogVerbose", false) { Label = "Verbose" }));

// Behaviour: Ctrl+PageUp/PageDown switch tabs, Enter on an outline entry opens its section; Escape exits.
ConsoleApp.Run(layout);
C# fluentProgram.Fluent.csView on GitHub
// Settings across tabs, with an outline that opens each section and a breadcrumb that shows where you are.
// All data is synthetic and inline; no services are contacted or changed.
using ConsoleMonster.Interactive;
using ConsoleMonster.Layout;
using ConsoleMonster.Widgets;
using ConsoleMonster;

// Layout: construct the widgets shown on screen.
Collapsible proxy = ((Collapsible)Ui.Collapsible().Key("Proxy").Content(Ui.Rows().Content(c =>
{
    c.TextInput(textInput => textInput.Key("ProxyServer")
        .Value("proxy.contoso.test:8080")
        .Label("Server"));
    c.Toggle(toggle => toggle.Key("ProxyBypass").Value(true).Label("Bypass for local addresses"));
})).Expanded().Build());
Collapsible dns = ((Collapsible)Ui.Collapsible().Key("DNS").Content(Ui.Rows().Content(c =>
{
    c.TextInput(textInput => textInput.Key("DnsServers")
        .Value("10.0.0.53, 10.0.1.53")
        .Label("Servers"));
    c.TextInput(textInput => textInput.Key("DnsSuffix")
        .Value("corp.contoso.test")
        .Label("Search suffix"));
})).Build());
Collapsible firewall = ((Collapsible)Ui.Collapsible().Key("Firewall").Content(Ui.Rows().Content(c =>
{
    c.Toggle(toggle => toggle.Key("FirewallOn").Value(true).Label("Enabled"));
    c.TextInput(textInput => textInput.Key("FirewallPorts")
        .Value("443, 8443")
        .Label("Allowed ports"));
})).Build());
Outline sections = ((Outline)Ui.Outline()
    .Key("Sections")
    .Build()).AddItem(new OutlineItem("Proxy").Target(proxy))
    .AddItem(new OutlineItem("DNS").Target(dns))
    .AddItem(new OutlineItem("Firewall").Target(firewall))
    .CurrentIndex(0);
Breadcrumb where = ((Breadcrumb)Ui.Breadcrumb().Key("Where").Build()).AddAncestor("Settings")
    .AddAncestor("Network")
    .Outline(sections);
Tabs layout = Ui.Tabs().Add("General", Ui.Rows().Content(c =>
{
    c.TextInput(textInput => textInput.Key("DisplayName")
        .Value("Contoso Operations")
        .Label("Display name"));
    c.Toggle(toggle => toggle.Key("StartAtLogon").Value(false).Label("Start at logon"));
})).Add("Network", Ui.Rows().Content(c2 =>
{
    c2.Add(where);
    c2.Splitter(splitter => splitter.First(sections).Second(Ui.Rows().Content(c =>
    {
        c.Add(proxy);
        c.Add(dns);
        c.Add(firewall);
    })).Ratio(0.25));
})).Add("Logging", Ui.Rows().Content(c =>
{
    c.TextInput(textInput => textInput.Key("LogPath")
        .Value("C:\\Logs\\Operations")
        .Label("Folder"));
    c.Toggle(toggle => toggle.Key("LogVerbose").Value(false).Label("Verbose"));
}));

// Behaviour: Ctrl+PageUp/PageDown switch tabs, Enter on an outline entry opens its section; Escape exits.
ConsoleApp.Run(layout);

Run it yourself

Three steps in PowerShell, four in C#. Every command copies with one click.

  1. Install the module

    Once. Windows PowerShell 5.1 or PowerShell 7 on Windows, macOS or Linux.

    Install-Module ConsoleMonster -Scope CurrentUser
  2. Save the program

    Download it, or copy it from above into settings-tabs.ps1.

  3. Run it

    From the folder you saved it in.

    ./settings-tabs.ps1
  1. Create a project

    A plain console app; .NET 8 or later.

    dotnet new console -n SettingsTabs; cd SettingsTabs
  2. Save the project

    The project selects one C# style at a time and restores ConsoleMonster.

  3. Save both programs

    Replace Program.cs and save Program.Fluent.cs beside it.

  4. Run it

    dotnet run
  1. Create a project

    A plain console app; .NET 8 or later.

    dotnet new console -n SettingsTabs; cd SettingsTabs
  2. Save the project

    The project selects one C# style at a time and restores ConsoleMonster.

  3. Save both programs

    Replace Program.cs and save Program.Fluent.cs beside it.

  4. Run it

    dotnet run --property:DemoStyle=Fluent

Or skip the copying. Run the bundled program.

Show-ConsoleDemo settings-tabs
$source = (Get-ConsoleDemo settings-tabs).Source
[IO.File]::WriteAllText("$PWD/settings-tabs.ps1", $source, [Text.UTF8Encoding]::new($true))

Make it yours

Start with these, then read the rest of the file.

  1. Replace the pages and sections with your own tool's settings.

  2. Point outline entries at any control to jump to it, not only folding sections.

  3. Give the breadcrumb plain segments when there is no outline to follow.

More terminal apps

All demos