This document explains the crate organization, design decisions, and how the different parts of cTUI work together.
cTUI is organized as a Cargo workspace with multiple specialized crates. This modular architecture provides:
- Clear separation of concerns
- Faster compilation for dependent projects
- Flexible dependency management
- Better API stability for the core types
The foundation of cTUI. Contains low-level primitives for terminal rendering.
Contents:
- Buffer and Cell types for screen representation
- Backend trait for terminal abstraction
- Terminal struct for managing terminal state
- Geometry primitives (
Rect,Position,Size) - Style types (
Color,Modifier,Style) - Component trait for declarative UI elements
- Props system for component configuration
- State management with dispatch pattern
- Event system for input handling
When to use:
- Building custom widget libraries
- Creating minimal applications
- Extending cTUI's capabilities
use ctui_core::{
Buffer, Cell, Rect, Style, Color,
Component, Event, Terminal,
};Built-in widget library with a comprehensive set of pre-built components.
Contents:
- Block, Paragraph, Text, Line
- Input, Form, Editor
- List, Table, Tree
- Tabs, Modal, Scrollable
- ProgressBar, Spinner, Gauge
- Chart, Sparkline, Canvas
- Checkbox, Radio, Select, Slider
- Markdown, Code, Diff
When to use:
- Building standard TUI applications
- Need ready-to-use widgets
- Prototyping quickly
use ctui_components::{
Block, Paragraph, List, Table,
Button, Input, ProgressBar,
};Flexbox-inspired layout engine for terminal UIs.
Contents:
- Flex direction (row, column)
- Justify content (main axis alignment)
- Align items (cross axis alignment)
- Gap between children
- Grid layout with rows/columns
- Absolute positioning with z-index
- Layout validation
When to use:
- Complex layouts
- Responsive designs
- Custom layout algorithms
use ctui_layout::{
Layout, FlexDirection, JustifyContent,
AlignItems, Constraint, Grid,
};Animation primitives and easing functions.
Contents:
- Easing functions (linear, ease-in, ease-out, elastic, bounce)
- Interpolation primitives for value blending
- Keyframe animations with playback modes
- Spring physics for natural motion
- Animation sequences and groups
- Global animation management
When to use:
- Creating animated UIs
- Smooth transitions
- Interactive feedback
use ctui_animate::{
EasingFunction, KeyframeAnimation,
PlaybackMode, SpringAnimation,
};Theming system with built-in presets.
Contents:
- Color types (Named, Indexed, RGB)
- Style properties
- Theme tokens
- Component themes
- Elevation and shadow system
- Built-in themes (Dark, Light, Tokyo Night, Dracula, Catppuccin, Nord, Gruvbox)
- Theme validation and accessibility checking
When to use:
- Customizing app appearance
- Supporting dark/light modes
- Ensuring accessibility
use ctui_theme::{
Theme, Style, Color, Modifier,
ThemeLoader, AccessibilityAudit,
};
let dark = Theme::dark();
let dracula = Theme::dracula();
let tokyo = Theme::tokyo_night();Procedural macros for reducing boilerplate.
Contents:
#[component]attribute macro
What it generates:
- Original struct (unchanged)
- Props struct with same fields
- Component implementation with defaults
use ctui_macros::component;
#[component]
struct Button {
label: String,
#[prop(default = false)]
disabled: bool,
}
// Generates ButtonProps and Component implCLI tool and project generator.
Contents:
- Project scaffolding
- Template system (basic, counter, todo-app)
- Cargo integration
cargo install ctui-cli
ctui new my-app --template counterIntegration tests and test utilities.
Contents:
- Test harness
- Snapshot testing helpers
- Mock backends
ctui (main crate - re-exports everything)
├── ctui-core (foundation)
├── ctui-components → ctui-core
├── ctui-layout → ctui-core
├── ctui-animate → ctui-core
├── ctui-theme → ctui-core
├── ctui-macros (proc-macro crate)
└── ctui-cli
- ctui-core: Foundation for all other crates
- ctui-components: Depends on core for widget traits
- ctui-layout: Depends on core for geometry types
- ctui-animate: Depends on core for timing
- ctui-theme: Depends on core for style types
cTUI uses a React-style component model:
- Components are functions that return UI descriptions
- State is managed through hooks (
use_state,use_effect,use_async) - Props flow down, events flow up
- Diff algorithm updates only what changed
The diff algorithm compares virtual DOM trees directly:
- No intermediate allocations during diffing
- Cell-based updates only for changed cells
- Batched event processing
- Lazy component re-rendering
Built on Tokio for async operations:
- Non-blocking event handling
- Seamless async integration
- Thread-safe state management
- Works with any async runtime
Leverage Rust's type system:
- Props are strongly typed
- Component state is type-checked
- Events are typed messages
- Compile-time error detection
These types are guaranteed to remain stable:
Buffer,CellRect,Position,SizeStyle,Color,ModifierEvent,KeyEvent,MouseEventComponenttrait
These may change between minor versions:
- Individual widget implementations
- Animation easing functions
- Theme format
- CLI commands
Behind feature flags:
#[component]macro extensions- WebAssembly support
- Plugin system
When adding new features:
- Core primitives →
ctui-core - New widgets →
ctui-components - Layout features →
ctui-layout - Animations →
ctui-animate - Theme support →
ctui-theme - Developer tools →
ctui-cli
If you're coming from ratatui or similar:
// Ratatui (imperative)
fn ui(f: &mut Frame, app: &App) {
let block = Block::default().title("Counter");
f.render_widget(block, f.size());
}
// cTUI (declarative)
#[component]
fn Counter() -> impl Component {
let (count, set_count) = use_state(0);
Column::new()
.child(Text::new(&format!("Count: {}", count)))
.child(Button::new("+").on_click(move || set_count(count + 1)))
}If you're familiar with React patterns:
use_state→ React'suseStateuse_effect→ React'suseEffectuse_async→ Custom hook for asyncComponenttrait → React component- Props → React props
- Independent crate versioning
- WebAssembly support
- Plugin system
- Additional themes
- More animation primitives