Immediate Mode GUI Library for Zig
RowCommitInfo now includes: - is_injected: bool (was this an injected row) - injection_index: ?usize (where it was injected) buildCommitInfo() copies these from RowEditBuffer. VirtualAdvancedTable sets result.injection_committed and result.injection_row_idx when committing an injected row, for both Tab navigation and selection change commits. This allows the panel to know when to INSERT vs UPDATE and handle the special case of locally injected rows. |
||
|---|---|---|
| .claude/commands | ||
| docs | ||
| examples | ||
| ios | ||
| src | ||
| web | ||
| .gitignore | ||
| build.zig | ||
| build.zig.zon | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| README.md | ||
| REFERENCE.md | ||
| VERIFIED_FEATURES.md | ||
| ZIG_VERSION_NOTES.md | ||
zcatgui
Immediate Mode GUI Library for Zig - Software-rendered, cross-platform, SSH-compatible.
Features
- Immediate Mode - Explicit state, no callbacks, no threading issues
- Software Rendering - Works everywhere, including over SSH (X11 forwarding)
- Macro System - Record and replay user actions (unique feature)
- 35 Widgets - From basic (Button, Label) to advanced (Table, Tree, Charts)
- 5 Themes - Dark, Light, High Contrast, Nord, Dracula
- Accessibility - ARIA-like roles and states for screen readers
- Zero Runtime Dependencies - Only SDL2 for windowing
Quick Start
const zcatgui = @import("zcatgui");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var ctx = try zcatgui.Context.init(allocator);
defer ctx.deinit();
while (ctx.running) {
ctx.beginFrame();
if (zcatgui.button(&ctx, "Click me!")) {
// Handle click
}
ctx.endFrame();
}
}
Widgets (35 total)
Basic
- Label - Static text with alignment options
- Button - Primary, normal, danger variants
- Checkbox - Boolean toggle
- RadioButton - Mutually exclusive selection
Input
- TextInput - Single-line text entry with cursor
- TextArea - Multi-line text editor
- NumberInput - Numeric input with validation
- Slider - Horizontal/vertical value slider
- AutoComplete - ComboBox with fuzzy matching
Selection
- Select - Dropdown selection
- List - Scrollable selectable list
- Tree - Hierarchical tree view
Data
- Table - Editable with sorting, validation, dirty tracking
- LineChart - Line graphs with multiple series
- BarChart - Bar graphs with grouping
- PieChart - Pie/donut charts with labels
- Sparkline - Compact inline charts
Layout
- Panel - Container with title, collapsible
- HSplit/VSplit - Draggable split panels
- Tabs - Tab container with keyboard navigation
- ScrollArea - Scrollable content region
- Modal - Dialog boxes (alert, confirm, input)
Feedback
- Progress - Bar, circle, spinner with animations
- Tooltip - Hover tooltips with smart positioning
- Toast - Non-blocking notifications
- Badge - Status labels with variants
Navigation
- Menu - Dropdown menus with submenus
- ContextMenu - Right-click menus
Special
- Image - Image display with scaling
- Icon - Icon rendering
- ColorPicker - Color selection
- Calendar - Date selection
- RichText - Styled text rendering
Unique Features
Macro System
Record user actions as keyboard events and replay them:
var recorder = zcatgui.MacroRecorder.init(allocator);
// Start recording
recorder.start();
// ... user interacts with UI ...
// Stop and save
const events = recorder.stop();
try recorder.save("my_macro.macro");
// Later, replay
var player = zcatgui.MacroPlayer.init();
player.play(events, ctx.injectEvent, 50); // 50ms delay between events
Lego Panels Architecture
Build complex UIs from reusable autonomous panels:
const panels = zcatgui.panels;
var search_panel = panels.SearchFilterPanel.init(allocator, config);
var data_panel = panels.DataTablePanel.init(allocator, table_config);
// Panels communicate via DataManager
var manager = panels.DataManager.init(allocator);
manager.register("search", &search_panel);
manager.register("data", &data_panel);
Table with Dirty Tracking
Track changes for database sync:
var table_state = zcatgui.widgets.TableState.init();
// After user edits
if (table_state.isDirty()) {
const changes = table_state.getDirtyRows();
for (changes) |row_idx| {
// Sync to database
}
table_state.clearDirty();
}
Themes
const theme = zcatgui.Style.ThemeManager.init();
// Switch themes at runtime
theme.setTheme(.dark);
theme.setTheme(.light);
theme.setTheme(.high_contrast);
theme.setTheme(.nord);
theme.setTheme(.dracula);
Performance
- FrameArena - O(1) per-frame allocator with automatic reset
- ObjectPool - Reuse frequently allocated objects
- Virtual Scrolling - Handle millions of items efficiently
- Dirty Rectangles - Partial redraws for efficiency
Building
# Build library
zig build
# Run tests
zig build test
# Build examples
zig build hello
zig build widgets-demo
zig build table-demo
Requirements
- Zig 0.15.2
- SDL2 (for windowing)
Project Structure
zcatgui/
├── src/
│ ├── zcatgui.zig # Main entry point
│ ├── core/ # Context, Layout, Style, Input
│ ├── widgets/ # All 35 widgets
│ ├── render/ # Software renderer, fonts, effects
│ ├── backend/ # SDL2 backend
│ ├── macro/ # Macro recording/playback
│ ├── panels/ # Lego Panels architecture
│ └── utils/ # Performance utilities
├── examples/ # Demo applications
└── docs/ # Documentation
Comparison
| Feature | zcatgui | DVUI | Dear ImGui |
|---|---|---|---|
| Language | Zig | Zig | C++ |
| Rendering | Software | Software/GPU | GPU |
| SSH Compatible | Yes | Partial | No |
| Macro System | Yes | No | No |
| Table Dirty Tracking | Yes | No | No |
| Widgets | 35 | 33 | 30+ |
Related Projects
- zcatui - TUI (Terminal UI) library for Zig (sister project)
License
MIT License - See LICENSE for details.
Contributing
Issues and pull requests welcome at the project repository.