zcatui/README.md
reugenio 79c0bb1a58 feat: Add form widgets, status bar, toast system, and documentation
Form widgets:
- Checkbox and CheckboxGroup for boolean inputs
- RadioGroup for single-selection options
- Select dropdown with keyboard navigation
- Slider and RangeSlider for numeric inputs
- TextArea for multi-line text input

UI utilities:
- StatusBar for bottom-of-screen information
- Toast and ToastManager for notifications

Examples:
- form_demo.zig: Interactive form widgets showcase
- panel_demo.zig: Docking panel system demo

Documentation:
- Complete README.md with Quick Start, widget examples, and API reference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 18:02:06 +01:00

324 lines
7.7 KiB
Markdown

# zcatui
A Terminal User Interface (TUI) library for Zig, inspired by [ratatui](https://github.com/ratatui/ratatui).
> **zcatui** = "zcat" + "ui" (a nod to ratatui and Zig's mascot)
## Features
### Core
- **Immediate mode rendering** with double buffering and diff-based updates
- **Flexible layout system** with constraints (Length, Min, Max, Percentage, Ratio)
- **Rich styling** with 16/256/RGB colors and modifiers (bold, italic, underline, etc.)
- **Full event handling** for keyboard and mouse input
- **Cross-terminal compatibility** via ANSI escape sequences
### Widgets (30+)
| Category | Widgets |
|----------|---------|
| **Basic** | Block, Paragraph, List, Table, Tabs |
| **Data** | Gauge, LineGauge, Sparkline, BarChart, Chart, Canvas |
| **Input** | Input (text field), TextArea, Checkbox, RadioGroup, Select, Slider |
| **Navigation** | Menu, MenuBar, ContextMenu, Tree, FilePicker |
| **Overlays** | Popup, Modal, Tooltip, Toast |
| **Layout** | Panel, PanelSplit, TabbedPanel, DockingPanel, ScrollView, VirtualList |
| **Utilities** | Scrollbar, Calendar, StatusBar, Clear |
### Terminal Extensions
- **Clipboard** (OSC 52) - Read/write system clipboard
- **Hyperlinks** (OSC 8) - Clickable links in terminal
- **Notifications** (OSC 9/777) - Desktop notifications
- **Images** (Kitty/iTerm2) - Display images in terminal
- **Cursor control** - Style, visibility, position
### Advanced Features
- **Animation system** with easing functions
- **Lazy rendering** with caching and throttling
- **Virtual scrolling** for large datasets
- **LEGO panel system** for complex layouts
## Quick Start
```zig
const std = @import("std");
const zcatui = @import("zcatui");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Initialize terminal
var term = try zcatui.Terminal.init(allocator);
defer term.deinit();
// Main loop
while (true) {
try term.draw(render);
if (try term.pollEvent(100)) |event| {
if (event == .key) {
if (event.key.code == .char and event.key.code.char == 'q') {
break;
}
}
}
}
}
fn render(area: zcatui.Rect, buf: *zcatui.Buffer) void {
const block = zcatui.widgets.Block.init()
.title(" Hello zcatui! ")
.setBorders(zcatui.widgets.Borders.all)
.style(zcatui.Style.default.fg(zcatui.Color.cyan));
block.render(area, buf);
}
```
## Installation
Add zcatui to your `build.zig.zon`:
```zig
.dependencies = .{
.zcatui = .{
.url = "https://git.reugenio.com/reugenio/zcatui/archive/main.tar.gz",
// Add hash after first build attempt
},
},
```
Then in `build.zig`:
```zig
const zcatui = b.dependency("zcatui", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("zcatui", zcatui.module("zcatui"));
```
## Examples
Run examples with:
```bash
zig build hello # Basic hello world
zig build events-demo # Keyboard/mouse events
zig build list-demo # List widget
zig build table-demo # Table widget
zig build dashboard # Dashboard with multiple widgets
zig build input-demo # Text input
zig build animation-demo # Animations
zig build menu-demo # Menus and modals
zig build form-demo # Form widgets
zig build panel-demo # Panel system
```
## Widget Examples
### Layout
```zig
const Layout = zcatui.Layout;
const Constraint = zcatui.Constraint;
// Split area vertically
const chunks = Layout.vertical(&.{
Constraint.length(3), // Fixed 3 rows
Constraint.percentage(50), // 50% of remaining
Constraint.min(5), // At least 5 rows
}).split(area);
// Split horizontally
const cols = Layout.horizontal(&.{
Constraint.ratio(1, 3), // 1/3 of width
Constraint.ratio(2, 3), // 2/3 of width
}).split(area);
```
### Block with Borders
```zig
const Block = zcatui.widgets.Block;
const Borders = zcatui.widgets.Borders;
const block = Block.init()
.title(" My Panel ")
.setBorders(Borders.all)
.style(Style.default.fg(Color.cyan));
block.render(area, buf);
const inner = block.inner(area); // Get content area
```
### List
```zig
const List = zcatui.widgets.List;
const ListItem = zcatui.widgets.ListItem;
const items = &[_]ListItem{
ListItem.init("Item 1"),
ListItem.init("Item 2").style(Style.default.fg(Color.green)),
ListItem.init("Item 3"),
};
var list = List.init(items)
.block(Block.init().title("List").setBorders(Borders.all))
.highlightStyle(Style.default.bg(Color.blue));
list.renderStateful(area, buf, &list_state);
```
### Form Widgets
```zig
// Checkbox
const checkbox = Checkbox.init("Enable feature")
.setChecked(true)
.setFocused(is_focused);
checkbox.render(area, buf);
// Radio buttons
var radio = RadioGroup.init(&.{"Option A", "Option B", "Option C"})
.setSelected(1);
radio.render(area, buf);
// Dropdown select
var select = Select.init(&.{"Small", "Medium", "Large"})
.setPlaceholder("Choose size...");
select.render(area, buf);
// Slider
const slider = Slider.init(0, 100)
.setValue(50)
.setLabel("Volume");
slider.render(area, buf);
```
### Charts
```zig
// Bar chart
const BarChart = zcatui.widgets.BarChart;
const chart = BarChart.init()
.data(&.{
.{ .label = "A", .value = 10 },
.{ .label = "B", .value = 20 },
.{ .label = "C", .value = 15 },
})
.barWidth(5);
chart.render(area, buf);
// Sparkline
const Sparkline = zcatui.widgets.Sparkline;
const sparkline = Sparkline.init(&.{1, 4, 2, 8, 5, 3, 9, 2});
sparkline.render(area, buf);
```
### Popups and Modals
```zig
const Modal = zcatui.widgets.Modal;
const confirmDialog = zcatui.widgets.confirmDialog;
// Quick confirm dialog
const modal = confirmDialog("Confirm", &.{"Are you sure?"});
modal.render(area, buf);
// Handle button press
if (modal.getFocusedButton() == 0) {
// OK pressed
}
```
### Toast Notifications
```zig
const ToastManager = zcatui.widgets.ToastManager;
var toasts = ToastManager.init();
// Show notifications
toasts.info("Information message");
toasts.success("Operation completed!");
toasts.warning("Warning!");
toasts.showError("Error occurred");
// In render loop
toasts.update();
toasts.render(area, buf);
```
## Terminal Extensions
### Clipboard
```zig
const Clipboard = zcatui.Clipboard;
// Write to clipboard
try Clipboard.write(writer, "Hello clipboard!");
// Read (async - response comes via terminal)
try Clipboard.requestRead(writer);
```
### Hyperlinks
```zig
const Hyperlink = zcatui.Hyperlink;
const link = Hyperlink.init("https://example.com", "Click here");
try link.write(writer);
```
### Notifications
```zig
const notification = zcatui.notification;
try notification.notify(writer, "Build complete!");
try notification.notifyWithTitle(writer, "zcatui", "Task finished");
```
### Images
```zig
const image = zcatui.image;
// Display image (Kitty protocol)
try image.Kitty.displayFile(writer, "/path/to/image.png", .{
.width = 40,
.height = 20,
});
```
## Architecture
```
┌─────────────┐ ┌────────┐ ┌──────────┐
│ Application │───▶│ Buffer │───▶│ Terminal │
│ (widgets) │ │ (diff) │ │ (output) │
└─────────────┘ └────────┘ └──────────┘
```
1. Application renders widgets to a Buffer
2. Buffer is compared (diff) with previous frame
3. Only changes are sent to terminal (efficient)
## Requirements
- Zig 0.15.x
- POSIX terminal (Linux, macOS) or Windows Terminal
- Terminal with ANSI escape sequence support
## License
MIT
## Credits
- Inspired by [ratatui](https://github.com/ratatui/ratatui) (Rust)
- Built with Zig