Skip to content

mitchdenny/hex1b

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

524 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Hex1b

Hex1b is a .NET library for building rich, interactive terminal user interfaces (TUI) with a React-inspired declarative API. Create beautiful console applications with widgets, layouts, theming, and more.

.NET License

✨ Features

  • Declarative UI - Build UIs using a widget tree pattern inspired by React and Flutter
  • Widget Library - TextBlock, TextBox, Button, List, VStack, HStack, Splitter, and more
  • Layout System - Flexible constraint-based layout with size hints (Fill, Content, Fixed)
  • Theming - Built-in themes with customizable colors and styles
  • Input Handling - Keyboard navigation, focus management, and shortcut bindings
  • Reconciliation - Efficient diff-based updates to minimize terminal redraws

πŸ“¦ Installation

dotnet add package Hex1b

πŸš€ Quick Start

Here's a simple "Hello World" application:

using Hex1b;
using Hex1b.Widgets;

using var cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) => { e.Cancel = true; cts.Cancel(); };

using var app = new Hex1bApp(
    ctx => Task.FromResult<Hex1bWidget>(
        new VStackWidget([
            new TextBlockWidget("Hello, Terminal!"),
            new ButtonWidget("Exit", () => cts.Cancel())
        ])
    )
);

await app.RunAsync(cts.Token);

🎨 Widgets

Hex1b provides a variety of built-in widgets:

Widget Description
TextBlockWidget Display static or dynamic text
TextBoxWidget Editable text input with cursor and selection
ButtonWidget Clickable button with label and action
ListWidget Scrollable list with selection
VStackWidget Vertical layout container
HStackWidget Horizontal layout container
SplitterWidget Resizable split pane layout

πŸ“ Layout System

Hex1b uses a constraint-based layout system with size hints:

// Children with size hints: first fills available space, second sizes to content
new VStackWidget(
    [contentWidget, statusBarWidget],
    [SizeHint.Fill, SizeHint.Content]
);

Size Hints:

  • SizeHint.Fill - Expand to fill available space
  • SizeHint.Content - Size to fit content
  • SizeHint.Fixed(n) - Fixed size of n units

🎹 Input Bindings

Define keyboard bindings at any level of your widget tree:

var widget = new SplitterWidget(left, right, 25) with
{
    InputBindings = [
        InputBinding.Ctrl(Hex1bKey.S, Save, "Save"),
        InputBinding.Ctrl(Hex1bKey.Q, Quit, "Quit"),
    ]
};

🎨 Theming

Apply built-in themes or create your own:

using var app = new Hex1bApp(builder, new Hex1bAppOptions { Theme = Hex1bThemes.Sunset });

πŸ—οΈ Architecture

Hex1b follows a widget/node separation pattern:

  1. Widgets - Immutable configuration objects describing what to render
  2. Nodes - Mutable render objects that manage state and layout
  3. Reconciliation - Efficient diffing to update nodes when widgets change
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Hex1bApp.RunAsync()                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  1. Build widget tree (your code)                           β”‚
β”‚  2. Reconcile β†’ Update node tree                            β”‚
β”‚  3. Layout β†’ Measure and arrange nodes                      β”‚
β”‚  4. Render β†’ Draw to terminal                               β”‚
β”‚  5. Wait for input β†’ Dispatch to focused node               β”‚
β”‚  6. Repeat from step 1                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ§ͺ Samples

The samples/ directory contains example applications demonstrating various features:

  • Cancellation - Master-detail contact editor with save/cancel functionality

Running Samples with Aspire

This repository is set up with Aspire to make it easy to run and test sample applications:

dotnet run --project apphost.cs

Note: Aspire doesn't natively support interactive terminal applications, but this project explores techniques to make TUI app development and testing in Aspire possible.

πŸ› οΈ Development

Prerequisites

  • .NET 10.0 SDK (preview)
  • A terminal emulator with good ANSI support

Building

dotnet build

Running Tests

dotnet test

Project Structure

hex1b/
β”œβ”€β”€ src/
β”‚   └── Hex1b/              # Main library
β”‚       β”œβ”€β”€ Layout/         # Constraint-based layout system
β”‚       β”œβ”€β”€ Nodes/          # Render nodes (mutable, stateful)
β”‚       β”œβ”€β”€ Widgets/        # Widget definitions (immutable config)
β”‚       β”œβ”€β”€ Theming/        # Theme system and built-in themes
β”‚       └── Input/          # Keyboard input and bindings
β”œβ”€β”€ samples/                # Example applications
β”œβ”€β”€ tests/
β”‚   └── Hex1b.Tests/        # Unit tests
└── apphost.cs              # Aspire app host for running samples

🀝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

For AI coding agents, see AGENTS.md for context and conventions.

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ”— Related Projects

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors