One Terminal, Everything at Once
Here's a question I've been asking other terminal-UI frameworks, and the honest answer keeps coming back no:
Can you play an MP4 in one floating window, run a live process monitor in an embedded terminal next to it, drive a four-panel dashboard with real-time graphs above them, render all of that over an animated Matrix-rain desktop, and then re-theme the entire scene — without restarting, without flicker, all compositing through a single diff'd cell buffer?
The thing that makes this hard isn't any single feature. Plenty of libraries can draw a table or animate a spinner. The hard part is doing all of it simultaneously, in overlapping windows, smoothly. That's a desktop window manager — z-order, occlusion culling, per-cell alpha blending, dirty-region diffing — rendered into character cells. That's the architecture SharpConsoleUI is built on, and it's why the scene holds together.
And here's the part I want to be upfront about: every line of code in that video ships in one example app — Examples/DemoApp. No private branch, no staged demo rig. You can dotnet run --project Examples/DemoApp and reproduce the whole thing. So let's walk through what's on screen, with the real code.
The dashboard: a real 2D grid, not stacked panes
That ServerHub-style dashboard is a WinUI-style grid: star/auto tracks, column and row gaps, cells that span, draggable splitters, and per-cell borders and backgrounds. This is the actual builder call from GridDemoWindow.cs:
var grid = Controls.Grid()
.Columns(GridLength.Star(1), GridLength.Star(1), GridLength.Star(1), GridLength.Star(1))
.Rows(GridLength.Auto(), GridLength.Star(1), GridLength.Star(1), GridLength.Star(1))
.RowGap(1)
.ColumnGap(2)
.ColumnSplitterAfter(1) // drag-resize between columns 1 and 2
.RowSplitterAfter(1) // drag-resize between content rows 1 and 2
.ColumnGridlines() // thin rules between columns
.RowGridlines()
.GridlineStyle(BorderStyle.Single)
.Place(header, 0, 0, colSpan: 4) // header spans all 4 columns
.Place(settingsPanel, 1, 2)
.Place(alertsLog, 1, 3, rowSpan: 2) // alerts tile spans two rows
.Build();
// Per-cell styling — real per-cell border + background, not a global theme:
grid.Cell(1, 0).Border = BorderStyle.Rounded; // frame the CPU tile
grid.Cell(1, 1).Background = new Color(40, 44, 60); // slate fill behind resources
grid.Cell(1, 3).Border = BorderStyle.Rounded; // frame the spanning alerts tile
The tiles aren't decoration — every one is a live, interactive control. The bars use semantic color roles, so they re-tint with the theme instead of carrying hardcoded colors:
Controls.BarGraph().WithLabel("Mem ").WithValue(56).WithMaxValue(100)
.WithColorRole(ColorRole.Warning).ShowValue().Build();
And the splitters animate — grab one, or collapse a track programmatically:
grid.AnimateColumnWidth(1, 0, TimeSpan.FromMilliseconds(250)); // collapse
grid.AnimateRowHeight(1, savedRowCells ?? 5, TimeSpan.FromMilliseconds(250));
Examples/DemoApp/DemoWindows/GridDemoWindow.cs
Video, actually playing, in a window
That's sample_bunny.mp4 decoded through FFmpeg and rendered into the terminal as half-blocks (two pixels per cell). Press M mid-playback to cycle Half-Block → ASCII → Braille → Kitty graphics (on terminals that support it). The control is four lines:
var videoControl = Controls.Video()
.Fill()
.WithLooping()
.WithOverlay()
.Build();
…and you hand it a file:
var filePath = await FileDialogs.ShowFilePickerAsync(ws,
startPath: AppContext.BaseDirectory,
filter: "*.mp4;*.mkv;*.avi;*.webm;*.mov;*.flv;*.wmv");
videoControl.PlayFile(filePath);
The file picker you see floating over everything? That's FileDialogs.ShowFilePickerAsync — a modal, awaited inside the window's own async thread, compositing on top of the running dashboard behind it.
Examples/DemoApp/DemoWindows/VideoDemoWindow.cs
A real terminal, embedded
Not a fake shell — a PTY-backed terminal emulator running your real system shell, here showing a live btop-style monitor with CPU cores, network graphs, and a process table. It's also semi-transparent, so the desktop shows through:
return new WindowBuilder(ws)
.WithTitle("Terminal")
.WithSize(100, 30)
.Centered()
.WithBackgroundColor(new Color(30, 30, 60, 180)) // semi-transparent chrome
.AddControl(Controls.Terminal()
.WithBackgroundColor(Color.Transparent)
.Build())
.BuildAndShow();
Examples/DemoApp/DemoWindows/TerminalWindow.cs
The animated desktop behind it all
The cascading green katakana behind every window is a desktop background with a paint callback — the framework hands you the cell buffer each tick and you draw whatever you like. There are built-in effects:
ws.DesktopBackground = DesktopEffects.ColorCycling();
ws.DesktopBackground = DesktopEffects.Pulse(new Color(15, 25, 60));
ws.DesktopBackground = DesktopEffects.DriftingGradient(/* ... */);
…and Matrix rain is just a custom one. Here's the shape of it (from CreateMatrixRain()):
return new DesktopBackgroundConfig
{
AnimationIntervalMs = 70,
PaintCallback = (buffer, width, height, elapsed) =>
{
// per-column heads/speeds/trails over a Katakana glyph set,
// bright white-green head fading to dark green trail
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
buffer.SetCell(x, y, new Cell(' ', Color.Black, Color.Black));
// ...advance each column, paint head + fading trail...
}
};
The whole desktop is behind the window compositor — the windows occlude it, alpha-blend over it, and it keeps animating in the gaps. That's the compositor doing its job.
Examples/DemoApp/DemoWindows/DesktopBackgroundWindow.cs
Re-theme the whole scene, live
The toolbar dropdown switches themes, and because controls declare semantic roles rather than literal colors, the entire composited scene — borders, bars, panels, gradients — re-derives at once:
// a control says what it IS, not what color it is:
Controls.Checkbox("Auto-scale").WithColorRole(ColorRole.Success).Build();
Controls.Button(" Restart ").WithColorRole(ColorRole.Danger).Outline().Build();
// switching the theme re-derives every role's palette:
ws.ThemeStateService.SwitchTheme(themeName);
No per-control recoloring. Danger is whatever the active theme says danger is.
Examples/DemoApp/DemoWindows/ControlRolesWindow.cs,LauncherWindow.cs
Why it composes
Every piece above is ordinary — a grid, a video control, a terminal, a background, a theme. The reason they run together is the rendering model: each window owns its own CharacterBuffer, a compositor merges them with occlusion culling and per-cell Porter-Duff alpha blending, and only changed cells are flushed. So a video updating at 30fps in one window, a sparkline ticking in another, and Matrix rain animating behind both cost you only the cells that actually changed — not a full-screen repaint each frame. That's what makes it smooth over SSH, not just locally.
It's the same pattern a desktop window manager uses, adapted to character cells. Most TUI frameworks share one buffer and repaint the frame; that's a fine model for a form or a wizard, and a wall when you want overlapping, independently-animating windows.
Try it
git clone https://github.com/nickprotop/ConsoleEx
cd ConsoleEx
dotnet run --project Examples/DemoApp
Press Ctrl+L for the launcher. Everything in the video is a page in the sidebar — Grid Layout, Video Player, Terminal, Desktop Background, Control Roles — across ~50 demos in one app. The video features are flagged: video and terminal need FFmpeg on your PATH.
- Repo: https://github.com/nickprotop/ConsoleEx
-
NuGet:
dotnet add package SharpConsoleUI - Docs: https://nickprotop.github.io/ConsoleEx/
If you build something with it, I'd genuinely like to see it.





Top comments (0)