Fluent Builders Reference
SharpConsoleUI provides fluent builder APIs for creating windows and controls with clean, chainable syntax.
Table of Contents
WindowBuilder
The WindowBuilder class provides a fluent API for creating and configuring windows.
Basic Usage
using SharpConsoleUI.Builders;
var window = new WindowBuilder(windowSystem)
.WithTitle("My Window")
.WithSize(80, 25)
.Centered()
.Build();
Configuration Methods
Size and Position
.WithSize(width, height) // Set window dimensions
.AtPosition(x, y) // Set window position
.Centered() // Center on screen
.WithMinimumSize(width, height) // Set minimum size constraints
Appearance
.WithTitle(title) // Set window title
.WithColors(background, foreground) // Set colors
.Borderless() // Remove border
Behavior
.Resizable(bool) // Enable/disable resizing (default: true)
.Movable(bool) // Enable/disable moving (default: true)
.Closable(bool) // Enable/disable closing (default: true)
.Minimizable(bool) // Enable/disable minimizing (default: true)
.Maximizable(bool) // Enable/disable maximizing (default: true)
.AsModal() // Make window modal
State
.Maximized() // Start maximized
.Minimized() // Start minimized
Independent Window Thread
.WithAsyncWindowThread(asyncMethod) // Attach async update loop
The async method receives Window and CancellationToken:
private async Task UpdateWindowAsync(Window window, CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
// Update window content
await Task.Delay(1000, ct);
}
}
Event Handlers
.OnKeyPressed((sender, e) => { }) // Key press handler
.OnClosed((sender, e) => { }) // Window closed handler
Templates
// Dialog template (title, size, centered, modal)
.WithTemplate(new DialogTemplate("Title", width, height))
// Tool window template (title, position, size)
.WithTemplate(new ToolWindowTemplate("Tools", new Point(x, y), new Size(w, h)))
Complete Example
var mainWindow = new WindowBuilder(windowSystem)
.WithTitle("Task Manager")
.WithSize(80, 25)
.Centered()
.WithColors(Color.DarkBlue, Color.White)
.Resizable()
.Movable()
.WithMinimumSize(60, 20)
.OnKeyPressed((sender, e) =>
{
if (e.KeyInfo.Key == ConsoleKey.Escape)
{
windowSystem.CloseWindow(sender as Window);
e.Handled = true;
}
})
.Build();
Control Builders
Control builders provide fluent APIs for configuring controls before adding them to windows.
ButtonBuilder
Controls.Button("Click Me")
.WithWidth(20)
.WithAlignment(HorizontalAlignment.Center)
.WithMargin(0, 1, 0, 0)
.WithName("submitButton")
.OnClick((sender, e, window) =>
{
// Button click handler - window parameter available
})
.Build();
ListBuilder
Controls.List()
.AddItem("Item 1")
.AddItem("Item 2")
.AddItem("Item 3")
.WithHeight(10)
.WithColors(Color.Grey15, Color.White)
.OnItemActivated((sender, item, window) =>
{
// Item double-clicked or Enter pressed
})
.OnSelectionChanged((sender, index, window) =>
{
// Selection changed
})
.Build();
CheckboxBuilder
Controls.Checkbox("Enable feature", initialChecked: false)
.OnCheckedChanged((sender, isChecked, window) =>
{
// Checkbox state changed
})
.Build();
DropdownBuilder
Controls.Dropdown()
.AddItem("Option 1")
.AddItem("Option 2")
.AddItem("Option 3")
.WithWidth(30)
.OnSelectionChanged((sender, index, window) =>
{
// Selection changed
})
.Build();
PromptBuilder
Controls.Prompt("Enter name:")
.WithInitialText("")
.WithMaxLength(50)
.WithName("nameInput")
.OnEntered((sender, text, window) =>
{
// Enter key pressed
})
.OnInputChanged((sender, text, window) =>
{
// Text changed
})
.Build();
MarkupBuilder
Controls.Markup()
.AddLine("[bold yellow]Title[/]")
.AddLine("")
.AddLine("Regular text")
.AddLine("[green]Success message[/]")
.WithAlignment(HorizontalAlignment.Center)
.Build();
TreeControlBuilder
Controls.Tree()
.AddNode("Root", children =>
{
children.AddNode("Child 1");
children.AddNode("Child 2", grandchildren =>
{
grandchildren.AddNode("Grandchild");
});
})
.WithHeight(15)
.WithColors(Color.Grey15, Color.White)
.Build();
HorizontalGridBuilder
Controls.HorizontalGrid()
.WithAlignment(HorizontalAlignment.Stretch)
.Column(col => col.Add(Controls.Label("Left")))
.Column(col => col.Add(Controls.Label("Middle")))
.Column(col => col.Add(Controls.Label("Right")))
.Build();
ScrollablePanelBuilder
Controls.ScrollablePanel()
.AddControl(Controls.Label("Line 1"))
.AddControl(Controls.Label("Line 2"))
.AddControl(Controls.Label("Line 3"))
.WithHeight(5)
.Build();
MenuBuilder
Controls.Menu()
.AddItem(item => item
.WithText("File")
.AddSubmenu(submenu => submenu
.AddItem(i => i.WithText("New"))
.AddItem(i => i.WithText("Open"))
.AddSeparator()
.AddItem(i => i.WithText("Exit"))
)
)
.AddItem(item => item.WithText("Edit"))
.Build();
ToolbarBuilder
Controls.Toolbar()
.AddButton("New", onClick: (s, e, w) => { })
.AddButton("Open", onClick: (s, e, w) => { })
.AddSeparator()
.AddButton("Save", onClick: (s, e, w) => { })
.Build();
MultilineEditControlBuilder
Controls.MultilineEdit()
.WithViewportHeight(10)
.WithWrapMode(WrapMode.Wrap)
.WithInitialText("Initial content")
.Build();
FigleControlBuilder
Controls.Figle("BIG TEXT")
.WithFont(FigletFont.Load("standard"))
.WithAlignment(HorizontalAlignment.Center)
.WithColor(Color.Yellow)
.Build();
SparklineBuilder
// Basic sparkline with block characters (default)
new SparklineBuilder()
.WithHeight(6)
.WithMaxValue(100)
.WithBarColor(Color.Cyan1)
.WithBorder(BorderStyle.Rounded, Color.Grey50)
.WithTitle("CPU Usage %", Color.Cyan1)
.WithData(cpuHistory)
.Build();
// Braille mode for smoother appearance
new SparklineBuilder()
.WithHeight(6)
.WithMode(SparklineMode.Braille) // Use braille patterns (5 levels)
.WithMaxValue(100)
.WithBarColor(Color.Green)
.WithTitle("Memory %")
.Build();
// Bidirectional mode for network upload/download visualization
new SparklineBuilder()
.WithHeight(10)
.WithMode(SparklineMode.BidirectionalBraille) // Upload up, download down
.WithMaxValue(100) // Primary (upload) max
.WithSecondaryMaxValue(100) // Secondary (download) max
.WithBarColor(Color.Cyan1) // Upload color (goes up from center)
.WithSecondaryBarColor(Color.Green) // Download color (goes down from center)
.WithTitle("↑ Upload ↓ Download", Color.Grey70)
.WithBidirectionalData(uploadHistory, downloadHistory)
.Build();
SparklineMode Options:
Block(default) - Uses 9-level block characters (▁▂▃▄▅▆▇█)Braille- Uses 5-level braille patterns for smoother, denser appearanceBidirectional- Two series: primary goes up from center, secondary goes down (block chars)BidirectionalBraille- Same as Bidirectional but with braille patterns
Bidirectional Mode Methods:
WithSecondaryData(IEnumerable<double>)- Set secondary data seriesWithSecondaryBarColor(Color)- Color for secondary (downward) barsWithSecondaryMaxValue(double)- Max scale for secondary seriesWithBidirectionalData(primary, secondary)- Set both series at once
BarGraphBuilder
// Basic bar graph with fixed color
new BarGraphBuilder()
.WithLabel("CPU")
.WithValue(65.5)
.WithMaxValue(100)
.WithBarWidth(30)
.WithFilledColor(Color.Cyan1)
.WithUnfilledColor(Color.Grey35)
.ShowLabel()
.ShowValue()
.WithValueFormat("F1")
.Build();
// Bar graph with gradient thresholds
new BarGraphBuilder()
.WithLabel("RAM Used")
.WithValue(75.0)
.WithMaxValue(100)
.WithBarWidth(30)
.WithStandardGradient() // Green (0-49%), Yellow (50-79%), Red (80%+)
.Build();
// Custom gradient thresholds
new BarGraphBuilder()
.WithLabel("Swap")
.WithValue(30.0)
.WithMaxValue(100)
.WithGradient(
new ColorThreshold(0, Color.Green),
new ColorThreshold(25, Color.Yellow),
new ColorThreshold(50, Color.Red)
)
.Build();
// Aligned bar graphs with fixed label width
new BarGraphBuilder()
.WithLabel("RAM Used")
.WithLabelWidth(12) // All bars align at position 12 + ": "
.WithValue(75.0)
.WithMaxValue(100)
.WithBarWidth(30)
.Build();
Key Methods:
WithLabelWidth(int)- Fixed label column width for vertical alignmentWithGradient(params ColorThreshold[])- Set custom color thresholdsWithStandardGradient()- Convenience method for green/yellow/red at 0/50/80%
SpectreRenderableBuilder
var table = new Table()
.AddColumn("Name")
.AddColumn("Value")
.AddRow("Item 1", "100")
.AddRow("Item 2", "200");
Controls.SpectreRenderable(table)
.WithAlignment(HorizontalAlignment.Center)
.Build();
RuleBuilder
Controls.RuleBuilder()
.WithTitle("Section Title")
.WithColor(Color.Blue)
.StickyTop() // Stick to top of window
.Build();
PanelBuilder
// Basic panel with content
Controls.Panel()
.WithContent("[yellow bold]Panel Title[/]")
.WithHeader("Header Text")
.Rounded() // Use rounded border
.WithBorderColor(Color.Cyan1)
.WithPadding(2, 1)
.Build();
// Different border styles
Controls.Panel()
.WithContent("Double line border")
.DoubleLine()
.Build();
Controls.Panel()
.WithContent("Single line border")
.SingleLine()
.Build();
Controls.Panel()
.WithContent("No border")
.NoBorder()
.Build();
// Panel that fills available height
Controls.Panel()
.WithContent("Stretches vertically")
.FillVertical()
.Build();
// With header alignment
Controls.Panel()
.WithContent("Content here")
.WithHeader("Centered Header")
.HeaderCenter()
.Build();
Border Styles:
Rounded()- Rounded corners (╭─╮│╰╯)DoubleLine()- Double-line border (╔═╗║╚╝)SingleLine()- Single-line border (┌─┐│└┘)NoBorder()- No visible border
Key Methods:
WithContent(string)- Set text content (supports Spectre markup)WithContent(IRenderable)- Set any Spectre renderable as contentWithHeader(string)- Add header text to borderHeaderLeft()/HeaderCenter()/HeaderRight()- Header alignmentWithPadding(int)orWithPadding(left, top, right, bottom)- Inner paddingWithBorderColor(Color)- Border colorFillVertical()- Stretch panel to fill available heightWithHeight(int)- Set explicit height
Controls Static Factory
The Controls static class provides convenient factory methods.
Quick Creation Methods
// Simple controls (no builder needed)
Controls.Label("Text") // Plain text label
Controls.Header("Title") // Bold yellow header
Controls.Info("Info message") // Blue info text
Controls.Warning("Warning") // Orange warning text
Controls.Error("Error message") // Red error text
Controls.Success("Success!") // Green success text
Controls.Rule("Section") // Horizontal rule with title
Controls.Separator() // Plain horizontal line
Controls.Space() // Empty space/padding
Builder Methods
// Returns builders for fluent configuration
Controls.Button(text) // ButtonBuilder
Controls.Markup(line) // MarkupBuilder
Controls.List() // ListBuilder
Controls.Checkbox(label, checked) // CheckboxBuilder
Controls.Dropdown() // DropdownBuilder
Controls.Prompt(prompt) // PromptBuilder
Controls.Tree() // TreeControlBuilder
Controls.HorizontalGrid() // HorizontalGridBuilder
Controls.ScrollablePanel() // ScrollablePanelBuilder
Controls.Menu() // MenuBuilder
Controls.Toolbar() // ToolbarBuilder
Controls.MultilineEdit() // MultilineEditControlBuilder
Controls.Figle(text) // FigleControlBuilder
Controls.SpectreRenderable(widget) // SpectreRenderableBuilder
Controls.RuleBuilder() // RuleBuilder
Controls.Panel() // PanelBuilder (for bordered content panels)
Controls.Panel(text) // PanelControl directly with text content
new SparklineBuilder() // SparklineBuilder (for time-series graphs)
new BarGraphBuilder() // BarGraphBuilder (for horizontal bar graphs)
Builder Patterns
Common Pattern: Name and Find
Name controls to find them later:
window.AddControl(
Controls.Prompt("Enter name:")
.WithName("nameInput")
.Build()
);
window.AddControl(
Controls.Label("Status: Ready")
.WithName("statusLabel")
.Build()
);
// Later, find by name
var nameInput = window.FindControl<PromptControl>("nameInput");
var statusLabel = window.FindControl<MarkupControl>("statusLabel");
Common Pattern: Event Handlers with Window Access
All event handlers include a window parameter:
window.AddControl(
Controls.Button("Submit")
.OnClick((sender, e, window) =>
{
// Access other controls through window parameter
var input = window.FindControl<PromptControl>("nameInput");
var status = window.FindControl<MarkupControl>("status");
if (!string.IsNullOrWhiteSpace(input?.Text))
{
status?.SetContent($"[green]Hello, {input.Text}![/]");
}
})
.Build()
);
Common Pattern: Layout with Alignment
window.AddControl(
Controls.Header("Welcome")
.WithAlignment(HorizontalAlignment.Center)
.Build()
);
window.AddControl(
Controls.Button("Submit")
.WithWidth(20)
.WithAlignment(HorizontalAlignment.Center)
.Build()
);
Common Pattern: Sticky Positioning
// Stick to top
window.AddControl(
Controls.RuleBuilder()
.WithTitle("Header")
.StickyTop()
.Build()
);
// Stick to bottom
window.AddControl(
Controls.Label("Press ESC to close")
.WithAlignment(HorizontalAlignment.Right)
.StickyBottom()
.Build()
);
Common Pattern: Margins
window.AddControl(
Controls.Label("Text with margins")
.WithMargin(left: 2, top: 1, right: 2, bottom: 1)
.Build()
);
Complete Application Example
using SharpConsoleUI;
using SharpConsoleUI.Builders;
using SharpConsoleUI.Drivers;
var windowSystem = new ConsoleWindowSystem(new NetConsoleDriver(RenderMode.Buffer));
var mainWindow = new WindowBuilder(windowSystem)
.WithTitle("Contact Form")
.WithSize(60, 20)
.Centered()
.WithColors(Color.DarkBlue, Color.White)
.Build();
// Header
mainWindow.AddControl(
Controls.Header("Contact Information")
.WithAlignment(HorizontalAlignment.Center)
.Build()
);
mainWindow.AddControl(Controls.Space());
// Name input
mainWindow.AddControl(
Controls.Prompt("Name:")
.WithName("nameInput")
.WithMaxLength(50)
.OnInputChanged((sender, text, window) =>
{
var status = window.FindControl<MarkupControl>("statusLabel");
status?.SetContent($"[dim]Typing... ({text.Length} chars)[/]");
})
.Build()
);
// Email input
mainWindow.AddControl(
Controls.Prompt("Email:")
.WithName("emailInput")
.WithMaxLength(100)
.Build()
);
mainWindow.AddControl(Controls.Space());
// Message input
mainWindow.AddControl(Controls.Label("Message:"));
mainWindow.AddControl(
Controls.MultilineEdit()
.WithName("messageInput")
.WithViewportHeight(5)
.WithWrapMode(WrapMode.Wrap)
.Build()
);
mainWindow.AddControl(Controls.Space());
// Buttons
mainWindow.AddControl(
Controls.HorizontalGrid()
.Column(col => col.Add(
Controls.Button("Submit")
.OnClick((sender, e, window) =>
{
var name = window.FindControl<PromptControl>("nameInput");
var email = window.FindControl<PromptControl>("emailInput");
var message = window.FindControl<MultilineEditControl>("messageInput");
if (string.IsNullOrWhiteSpace(name?.Text))
{
windowSystem.NotificationStateService.ShowNotification(
"Validation Error",
"Name is required",
NotificationSeverity.Warning
);
return;
}
// Process form...
windowSystem.NotificationStateService.ShowNotification(
"Success",
"Message sent successfully!",
NotificationSeverity.Success
);
})
.Build()
))
.Column(col => col.Add(
Controls.Button("Clear")
.OnClick((sender, e, window) =>
{
window.FindControl<PromptControl>("nameInput")?.Clear();
window.FindControl<PromptControl>("emailInput")?.Clear();
window.FindControl<MultilineEditControl>("messageInput")?.Clear();
})
.Build()
))
.Build()
);
// Status label
mainWindow.AddControl(
Controls.Label("Ready")
.WithName("statusLabel")
.WithAlignment(HorizontalAlignment.Center)
.StickyBottom()
.Build()
);
windowSystem.AddWindow(mainWindow);
windowSystem.Run();