Skip to content

DoubledDoge/consoleprism

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

104 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ConsolePrism

CI/CD CodeQL NuGet License: MIT .NET Downloads

An opinionated, component-based UI framework for .NET console applications. Build terminal interfaces with tables, menus, progress bars, spinners, layout containers, and more.


๐ŸšจImportant Note

Do note that this simple project is very limited and simple in scope compared to a more advanced notable project like Spectre.Console, so use that instead if you can. Its much better than this little library that I've made for myself.


๐Ÿ“‘ Table of Contents


๐Ÿš€ Features

  • Theming System โ€” Fully composable themes combining colour schemes and border styles, with built-in presets
  • Semantic Colour Output โ€” Contextual coloured text for errors, success, warnings, and information
  • Rich Components โ€” Tables, menus, progress bars, spinners, and notifications
  • Layout Containers โ€” Panel, Row, Column, and Viewport for structured terminal layouts
  • Renderer Abstraction โ€” Swap rendering backends for testing or deferred output via IRenderer
  • Scoped Theming โ€” Apply themes globally or per-component, with scoped overrides via ConsoleContext

๐Ÿ“ฆ Installation

NuGet Package

dotnet add package ConsolePrism

Manual Installation

  1. Clone the repository
  2. Add a reference to your project:
dotnet add reference path/to/src/ConsolePrism.csproj

๐Ÿ“š Usage Guide

Semantic Colour Output

using ConsolePrism.Core;

ColorWriter.WriteSuccessLine("Operation completed!");
ColorWriter.WriteErrorLine("Something went wrong.");
ColorWriter.WriteWarningLine("Proceed with caution.");
ColorWriter.WriteInfoLine("Here is some information.");
ColorWriter.WriteHighlightLine("Important text.");

// Explicit colour when needed
ColorWriter.WriteColoredLine("Custom text", ConsoleColor.Magenta);

Menus

using ConsolePrism.Components;

// Arrow-key interactive menu (default)
string[] choices = ["New Game", "Continue", "Settings", "Exit"];

Menu interactive = new("Main Menu", MenuStyle.Interactive, choices);

int choice = interactive.Interact();

// Numbered menu
Menu numbered = new("Select Difficulty", MenuStyle.Numbered, "Easy", "Normal", "Hard");

int difficulty = numbered.Interact();

// Bordered menu
Menu bordered = new("Choose Mode", MenuStyle.Bordered, "Story", "Creative", "Survival");

int mode = bordered.Interact();

Tables

using ConsolePrism.Components;

string[] headers = ["Name", "Score", "Level"];
string[][] data = [
    ["Alice",   "1250", "10"],
    ["Bob",     "980",  "8" ],
    ["Charlie", "1500", "12"],
]; // Can be nullable for empty cells

new Table(headers, data).Render();

// Alternatively for coloured cells
TableCell[][] colouredData = [
    ["Alice",   new TableCell("1250", ConsoleColor.Green), "10"],
    ["Bob",     new TableCell("980", ConsoleColor.Red),    "8" ],
    ["Charlie", new TableCell("1500", ConsoleColor.Yellow),"12"],
];

new Table(headers, colouredData).Render();

// Custom column widths
int[] widths = [15, 10, 8];
new Table(headers, data, widths).Render();

Progress Bars

using ConsolePrism.Components;

// Static progress bar
new ProgressBar(75, "Processing", 100).Render();

// Animated in-place progress
ProgressBar bar = new(0, "Loading", 100) { InPlace = true };

for (int i = 0; i <= 100; i++)
{
    bar.Current = i;
    bar.Render();
    Thread.Sleep(50);
}

Spinners

using ConsolePrism.Components;

Spinner spinner = new(Spinner.Dots, "Loading assets...");
spinner.Start();

// Do work...
await LoadAssetsAsync();

spinner.Stop("Assets loaded successfully!");

// Using Dispose pattern
using Spinner spinner = new(Spinner.Pulse, "Connecting...");
spinner.Start();
await ConnectAsync();

Notifications

using ConsolePrism.Components;

new Notification("File saved!", false, NotificationLevel.Success).Render();
new Notification("Low disk space.", false, NotificationLevel.Warning).Render();
new Notification("Connection failed.", false NotificationLevel.Error).Render();

// Transient notification
new Notification("Autosaving...", false, NotificationLevel.Info, 2000).Render();

// Bordered notification
new Notification("Welcome to ConsolePrism!", true, NotificationLevel.Info).Render();

Console Text

using ConsolePrism.Components;

// Simple text
new ConsoleText("This is a simple text component.").Render();

// Text with colour
new ConsoleText("This is an error message.", ConsoleColor.Red).Render();

// Note: This has been implemented with the sole purpose of for ease of use in the panel, column, row and viewport layouts.

Panels

using ConsolePrism.Layout;

Panel simplePanel = new(
	content: new ConsoleText("This is a simple panel.") // Or any component
);

// Complex panel with title, content, and padding
Panel panel = new(
    title: "Welcome",
    content: new ConsoleText("Hello, World!"),
    horizontalPadding: 2,
    verticalPadding: 1
);

panel.Render();

Rows

using ConsolePrism.Layout;

Row row = new(
	spacing: 1,
	new ConsoleText("Header"),
	new Panel(title: "Info", content: new ConsoleText("Details...")),
	new ConsoleText("Footer")
);

row.Render();

// Alternatively through Fluent API:
Row fluentRow = new Row(spacing: 1)
    .Add(new ConsoleText("Header"))
    .Add(new Panel(title: "Info", content: new ConsoleText("Details...")))
    .Add(new ConsoleText("Footer"));

fluentRow.Render();

Viewport

using ConsolePrism.Layout;

Viewport viewport = new(
	height: 2,
	new ConsoleText("Line 1"),
	new ConsoleText("Line 2"),
	new ConsoleText("Line 3"),
	new ConsoleText("Line 4"),
	new ConsoleText("Line 5")
);

viewport.Render();

// Alternatively through Fluent API:
Viewport fluentViewport = new Viewport(height: 10)
    .Add(new ConsoleText("Line 1"))
    .Add(new ConsoleText("Line 2"))
    // ... 50+ more lines
    .Add(new ConsoleText("Line 52"));

fluentViewport.Render();  // Initially shows lines 1-10

// User can scroll
fluentViewport.ScrollDown(3);  // Now shows lines 4-13
fluentViewport.Render();

fluentViewport.ScrollUp(1);    // Back to lines 3-12
fluentViewport.Render();

fluentViewport.ScrollToTop();  // Back to lines 1-10
fluentViewport.Render();

// Users can also interact with the viewport itself through up/down arrow keys:
fluenViewport.Interact();

Columns

using ConsolePrism.Layout;

Column column = new(
	gap: 2,
	new Panel(title: "Left", content: new ConsoleText("A")),
	new Panel(title: "Middle", content: new ConsoleText("B")),
	new Panel(title: "Right", content: new ConsoleText("C"))
);		

column.Render();

// Alternatively through Fluent API:
Column fluentColumn = new Column(gap: 2)
    .Add(new Panel(title: "Left", content: new ConsoleText("A")))
    .Add(new Panel(title: "Middle", content: new ConsoleText("B")))
    .Add(new Panel(title: "Right", content: new ConsoleText("C")));

fluentColumn.Render();

App Shell

using ConsolePrism.Layout;
using ConsolePrism.Components;

Panel mainContent = new(
    title: "Dashboard",
    content: new ConsoleText("Welcome to the application!"),
    horizontalPadding: 2
);

// Wrap the content in the AppShell
AppShell shell = new(
    title: "MY AWESOME CLI",
    content: mainContent,
    leftFooter: "Status: Online",
    rightFooter: "v1.0.0 | Press ESC to exit"
);

shell.Render();

Console Utilities

using ConsolePrism.Core;

// Positioning
ConsoleHelper.WriteCentered("Centered Title");
ConsoleHelper.WriteRight("Right-aligned", padding: 2);
ConsoleHelper.WriteAt("Positioned text", x: 10, y: 5);

// Cursor control
ConsoleHelper.HideCursor();
ConsoleHelper.MoveCursor(0, 10);
ConsoleHelper.ShowCursor();

// Drawing
ConsoleHelper.DrawHorizontalLine('โ”€');
ConsoleHelper.WriteEmptyLines(2);

๐ŸŽจ Theming

List of available theme presets:

  • NordTheme - Arctic blue tones with rounded borders
  • MonochromeTheme - Grayscale for minimal or accessible output
  • RetroTheme - Amber tones with ASCII borders
  • MatrixTheme - Cascading greens against a dark background
  • SunsetTheme - Cosy oranges, magenta and soft whites to evoke a twilight atmosphere
  • SolarizedTheme - Warm amber and earthy tones with cool accent colours
  • PastelTheme - Muted, light tones for a gentle visual experience

Applying a Built-in Preset

using ConsolePrism.Themes;
using ConsolePrism.Themes.Presets;

// Apply globally
Theme.Apply(NordTheme.Instance);

// Reset to default
Theme.Apply(Theme.Default);

Creating a Custom Theme

using ConsolePrism.Themes;

Theme myTheme = new()
{
    Colors = new ColorScheme
    {
        Primary   = ConsoleColor.Cyan,
        Success   = ConsoleColor.Green,
        Error     = ConsoleColor.Red,
        Warning   = ConsoleColor.Yellow,
        Info      = ConsoleColor.Blue,
        Highlight = ConsoleColor.Magenta,
        Muted     = ConsoleColor.DarkGray,

        MenuTitle    = ConsoleColor.Cyan,
        MenuOption   = ConsoleColor.White,
        MenuSelected = ConsoleColor.Green,
        MenuBorder   = ConsoleColor.DarkGray,

        TableHeader  = ConsoleColor.Cyan,
        TableBorder  = ConsoleColor.DarkGray,
        TableData    = ConsoleColor.White,

        ProgressBarComplete   = ConsoleColor.Green,
        ProgressBarIncomplete = ConsoleColor.DarkGray,
        ProgressBarText       = ConsoleColor.White
    },
    Border = BorderStyle.Rounded
};

Theme.Apply(myTheme);

Scoped Theme Override

using ConsolePrism.Core;
using ConsolePrism.Themes.Presets;

// Theme.Current is temporarily replaced for the duration of the block
using (new ConsoleContext(MonochromeTheme.Instance))
{
    table.Render();
}
// Theme.Current is automatically restored here

Per-Component Theme Override

Table table = new(headers, data)
{
    Theme = RetroTheme.Instance
};

table.Render(); // uses RetroTheme regardless of Theme.Current

Border Styles

using ConsolePrism.Themes;

// Built-in presets
BorderStyle.Single;   // โ”Œโ”€โ” โ”‚ โ””โ”€โ”˜  (default)
BorderStyle.Double;   // โ•”โ•โ•— โ•‘ โ•šโ•โ•
BorderStyle.Rounded;  // โ•ญโ”€โ•ฎ โ”‚ โ•ฐโ”€โ•ฏ
BorderStyle.Ascii;    // +-+ | +-+

// Custom border
Borderstyle custom = new()
{
    TopLeft  = 'โ•”', TopRight  = 'โ•—',
    BottomLeft = 'โ•š', BottomRight = 'โ•',
    Horizontal = 'โ•', Vertical = 'โ•‘',
    Cross = 'โ•ฌ',
    TeeLeft = 'โ• ', TeeRight = 'โ•ฃ',
    TeeTop  = 'โ•ฆ', TeeBottom = 'โ•ฉ'
};

๐Ÿ—๏ธ Architecture

ConsolePrism/
โ”œโ”€โ”€ Interfaces/
โ”‚   โ”œโ”€โ”€ IRenderable       โ†’ Anything that can render itself
โ”‚   โ”œโ”€โ”€ IInteractable     โ†’ Components that accept user input
โ”‚   โ”œโ”€โ”€ IComponent        โ†’ Base interface for all UI components
|   โ””โ”€โ”€ IRenderer         โ†’ Output backend abstraction
โ”‚
โ”œโ”€โ”€ Themes/
โ”‚   โ”œโ”€โ”€ ColorScheme       โ†’ Full color palette definition
โ”‚   โ”œโ”€โ”€ BorderStyle       โ†’ Border character set definition
โ”‚   โ”œโ”€โ”€ Theme             โ†’ Unified theme object (ColorScheme + BorderStyle)
โ”‚   โ””โ”€โ”€ Presets/
โ”‚
โ”œโ”€โ”€ Core/
โ”‚   โ”œโ”€โ”€ ColorWriter       โ†’ Semantic colored text output
โ”‚   โ”œโ”€โ”€ ConsoleHelper     โ†’ Cursor control, positioning, and drawing utilities
โ”‚   โ”œโ”€โ”€ ConsoleContext    โ†’ Scoped theme switching via IDisposable
โ”‚   โ””โ”€โ”€ Rendering/
โ”‚       โ”œโ”€โ”€ ConsoleRenderer   โ†’ Default implementation writing to Console
โ”‚       โ””โ”€โ”€ StringRenderer    โ†’ In-memory buffer for testing and layout buffering
โ”‚
โ”œโ”€โ”€ Components/
|   โ”œโ”€โ”€ ComponentBase     โ†’ Abstract base with theme resolution and renderer swapping
โ”‚   โ”œโ”€โ”€ Menu              โ†’ Numbered, interactive, and bordered menu styles
โ”‚   โ”œโ”€โ”€ Table             โ†’ Auto-sizing bordered table with text wrapping
|   โ”œโ”€โ”€ TableCell         โ†’ Cell content with optional colour
โ”‚   โ”œโ”€โ”€ ProgressBar       โ†’ Static and in-place animated progress bars
โ”‚   โ”œโ”€โ”€ Spinner           โ†’ Animated spinners for async operations
โ”‚   โ”œโ”€โ”€ Notification      โ†’ Transient styled messages with optional auto-dismiss
|   โ”œโ”€โ”€ ConsoleText       โ†’ Simple text for use with the layout components
โ”‚   โ””โ”€โ”€ Prompt            โ†’ Styled input prompt with optional masked entry
โ”‚
โ””โ”€โ”€ Layout/
    โ”œโ”€โ”€ Panel             โ†’ Bordered content container with title support
    โ”œโ”€โ”€ Row               โ†’ Vertical component stacking with optional spacing
    โ”œโ”€โ”€ Column            โ†’ Horizontal side-by-side component layout
    โ”œโ”€โ”€ AppShell          โ†’ Common application layout with header, footer, and main content
    โ””โ”€โ”€ Viewport          โ†’ Scrollable content region with fixed visible height

๐Ÿ’ป Requirements

  • .NET 9.0 or .NET 10.0
  • Windows, macOS, or Linux
  • A terminal with a dark background is recommended for the best visual experience

๐Ÿ“„ Licence

See LICENCE for details. (MIT Licence)


๐Ÿค Contributing

Contributions are welcome! You can:

  • Report bugs or request features via Issues
  • Submit pull requests
  • Suggest improvements to the API
  • Propose new components, themes, or layout containers

About

Another opinionated console UI framework for .NET applications.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages