Expand description
Blaeck - A declarative, component-based terminal UI library for Rust.
Blaeck provides an Ink-like API for building terminal user interfaces with flexbox layout, inline rendering (not fullscreen), and 35+ components.
§Quick Start (Reactive API)
The recommended way to build interactive UIs is with the reactive API, which uses signals and hooks similar to React:
use blaeck::prelude::*;
use blaeck::reactive::*;
fn counter(cx: Scope) -> Element {
let count = use_state(cx.clone(), || 0);
let count_handler = count.clone();
use_input(cx, move |key| {
if key.is_char(' ') {
count_handler.set(count_handler.get() + 1);
}
});
element! {
Box(border_style: BorderStyle::Round, padding: 1.0) {
Text(content: format!("Count: {}", count.get()), color: Color::Green)
}
}
}
fn main() -> std::io::Result<()> {
ReactiveApp::run(counter)
}See reactive module for the full API and more examples.
§Two Paradigms
Blaeck offers two ways to build UIs:
§1. Reactive/Declarative (Recommended)
Use reactive::ReactiveApp with hooks like use_state and use_input.
State changes automatically trigger re-renders. This is the preferred approach
for most applications.
Pros:
- Cleaner mental model - state and UI are declaratively connected
- Automatic re-rendering when state changes
- No manual state management boilerplate
- Familiar to React/Solid.js developers
Examples: reactive_counter.rs, reactive_list.rs
§2. Imperative (Advanced)
Use App with explicit state management (typically RefCell or similar).
You manually control when and how state changes and re-renders occur.
When to use:
- Integration with existing imperative codebases
- Fine-grained control over render timing
- Cases where the reactive model doesn’t fit
Examples: interactive.rs, form_demo.rs
use blaeck::prelude::*;
use blaeck::App;
use std::cell::RefCell;
let state = RefCell::new(0);
App::new()?.run(
|_app| element! { Text(content: format!("Count: {}", state.borrow())) },
|_app, key| {
if key.is_char(' ') {
*state.borrow_mut() += 1;
}
},
)?;§Static Rendering
For one-shot rendering without interactivity, use Blaeck directly:
use blaeck::prelude::*;
use blaeck::Blaeck;
let mut blaeck = Blaeck::new(std::io::stdout())?;
blaeck.render(element! {
Box(border_style: BorderStyle::Round, padding: 1.0) {
Text(content: "Hello, Blaeck!", color: Color::Green)
}
})?;
blaeck.unmount()?;§Architecture
See ARCHITECTURE.md in the repository root for the full mental model.
Data flow: element! macro → Element tree → Layout (Taffy) → Output grid → Terminal
Key modules (read in this order):
reactive— Signals-based reactive system (start here for new apps)renderer— Main render engine, orchestrates everything- [
element] — Element tree and Component trait log_update— Ink-style inline rendering (the clever bit)output— Virtual 2D grid for styled characterslayout— Flexbox, CSS Grid, and positioning via Taffy
§Where to Start
- New to Blaeck: Start with
examples/reactive_counter.rs - Interactive apps: See
examples/reactive_list.rsfor multiple signals - Understanding internals: Read
ARCHITECTURE.md, thenrenderer.rs - Adding components: Study
components/box_component.rs
§Async Support
Enable the async feature for tokio-based async runtime:
blaeck = { version = "0.1", features = ["async"] }This provides [async_runtime::AsyncApp] for apps that need to integrate
with async operations like D-Bus, HTTP requests, or other I/O.
Re-exports§
pub use animation::lerp_rgb;pub use animation::lerp_u8;pub use animation::AnimationTimer;pub use animation::BlinkPattern;pub use animation::Easing;pub use animation::IndicatorStyle;pub use app::App;pub use app::AppConfig;pub use app::AppResult;pub use app::ExitReason;pub use buffer::Buffer;pub use buffer::Cell;pub use components::alert;pub use components::animated_indicator;pub use components::animated_indicator_colored;pub use components::badge;pub use components::badge;pub use components::badge_bracket;pub use components::bar_chart;pub use components::bar_chart_with_values;pub use components::blink;pub use components::blink;pub use components::blink_or;pub use components::blink_pattern;pub use components::blinking_dot;pub use components::checkbox;pub use components::checkbox;pub use components::confirm_modal;pub use components::confirm_prompt;pub use components::countdown;pub use components::countdown_with_thresholds;pub use components::diff_lines;pub use components::divider;pub use components::divider;pub use components::divider_with_label;pub use components::error_modal;pub use components::flex_spacer;pub use components::git_branch;pub use components::gradient;pub use components::gradient;pub use components::gradient_preset;pub use components::icons;pub use components::key_hints;pub use components::link;pub use components::link;pub use components::link_url;pub use components::log_box;pub use components::markdown_block;pub use components::progress_bar;pub use components::progress_bar_bracketed;pub use components::pulsing_dot;pub use components::spacer;pub use components::spacer;pub use components::sparkline;pub use components::sparkline;pub use components::sparkline_labeled;pub use components::spinner_frame;pub use components::spinner_frame_interval;pub use components::status_error;pub use components::status_ok;pub use components::status_warning;pub use components::stopwatch;pub use components::success_modal;pub use components::syntax_highlight;pub use components::syntax_highlight_with_lines;pub use components::timer_display;pub use components::transforms;pub use components::tree_view;pub use components::Autocomplete;pub use components::AutocompleteItem;pub use components::AutocompleteProps;pub use components::AutocompleteState;pub use components::Badge;pub use components::BadgeProps;pub use components::BadgeStyle;pub use components::BarChart;pub use components::BarChartProps;pub use components::BarData;pub use components::BarStyle;pub use components::BorderChars;pub use components::BorderColors;pub use components::BorderSides;pub use components::BorderStyle;pub use components::Box;pub use components::BoxProps;pub use components::BreadcrumbSeparator;pub use components::Breadcrumbs;pub use components::BreadcrumbsProps;pub use components::CellAlign;pub use components::Checkbox;pub use components::CheckboxProps;pub use components::CheckboxStyle;pub use components::ColorStop;pub use components::ColumnWidth;pub use components::Confirm;pub use components::ConfirmProps;pub use components::ConfirmStyle;pub use components::Crumb;pub use components::Diff;pub use components::DiffLine;pub use components::DiffLineType;pub use components::DiffProps;pub use components::DiffStyle;pub use components::Divider;pub use components::DividerProps;pub use components::DividerStyle;pub use components::FilterMode;pub use components::Gradient;pub use components::GradientPreset;pub use components::GradientProps;pub use components::Indent;pub use components::IndentProps;pub use components::KeyHint;pub use components::KeyHintSeparator;pub use components::KeyHintStyle;pub use components::KeyHints;pub use components::KeyHintsProps;pub use components::LineNumberStyle;pub use components::Link;pub use components::LinkProps;pub use components::LogBox;pub use components::LogBoxProps;pub use components::LogLine;pub use components::Markdown;pub use components::MarkdownProps;pub use components::Modal;pub use components::ModalButton;pub use components::ModalProps;pub use components::ModalStyle;pub use components::MultiSelect;pub use components::MultiSelectItem;pub use components::MultiSelectProps;pub use components::MultiSelectState;pub use components::MultiSelectStyle;pub use components::Newline;pub use components::NewlineProps;pub use components::Progress;pub use components::ProgressChars;pub use components::ProgressProps;pub use components::ProgressStyle;pub use components::Row;pub use components::RowStyle;pub use components::Select;pub use components::SelectIndicator;pub use components::SelectItem;pub use components::SelectProps;pub use components::SelectState;pub use components::Spacer;pub use components::SpacerProps;pub use components::Sparkline;pub use components::SparklineProps;pub use components::SparklineStyle;pub use components::Spinner;pub use components::SpinnerProps;pub use components::SpinnerStyle;pub use components::Static;pub use components::StaticItem;pub use components::StaticProps;pub use components::StatusBar;pub use components::StatusBarProps;pub use components::StatusSegment;pub use components::StatusSeparator;pub use components::SyntaxHighlight;pub use components::SyntaxHighlightProps;pub use components::SyntaxTheme;pub use components::Tab;pub use components::TabDivider;pub use components::TabStyle;pub use components::Table;pub use components::TableCell;pub use components::TableProps;pub use components::TableState;pub use components::Tabs;pub use components::TabsProps;pub use components::TabsState;pub use components::Text;pub use components::TextInput;pub use components::TextInputProps;pub use components::TextInputState;pub use components::TextProps;pub use components::TextWrap;pub use components::TimeFormat;pub use components::Timer;pub use components::TimerMode;pub use components::TimerProps;pub use components::Transform;pub use components::TransformFn;pub use components::TransformProps;pub use components::TreeConnectors;pub use components::TreeNode;pub use components::TreeState;pub use components::TreeStyle;pub use components::TreeView;pub use components::TreeViewProps;pub use components::ValueFormat;pub use element::Component;pub use element::Element;pub use focus::FocusCallback;pub use focus::FocusEvent;pub use focus::FocusId;pub use focus::FocusManager;pub use focus::FocusState;pub use input::match_key;pub use input::poll_key;pub use input::read_key;pub use input::Arrow;pub use input::InputHandler;pub use input::Key;pub use input::KeyMatcher;pub use layout::AlignContent;pub use layout::AlignItems;pub use layout::AlignSelf;pub use layout::FlexDirection;pub use layout::FlexWrap;pub use layout::GridAutoFlow;pub use layout::GridPlacement;pub use layout::JustifyContent;pub use layout::LayoutResult;pub use layout::LayoutStyle;pub use layout::LayoutTree;pub use layout::Overflow;pub use layout::Position;pub use layout::TrackSize;pub use log_update::LogUpdate;pub use output::Output;pub use output::OutputResult;pub use renderer::Blaeck;pub use style::rgb_to_256;pub use style::supports_truecolor;pub use style::Color;pub use style::Modifier;pub use style::Style;pub use timeline::Act;pub use timeline::Animatable;pub use timeline::LoopBehavior;pub use timeline::PlayingTimeline;pub use timeline::Spring;pub use timeline::SpringTrack;pub use timeline::StaggerConfig;pub use timeline::StaggerOrder;pub use timeline::StaggerTrack;pub use timeline::Timeline;pub use timeline::TimelineDebugInfo;pub use timeline::TimelineState;pub use timeline::Track;
Modules§
- animation
- Animation utilities for Blaeck.
- app
- Imperative application runtime with manual state management.
- buffer
- Buffer module for terminal rendering.
- components
- Built-in components for Blaeck.
- element
- Component and Element types for building declarative terminal UIs.
- focus
- Focus management for interactive elements.
- input
- Input handling for interactive terminal applications.
- layout
- Layout engine - wrapper around Taffy for flexbox/grid/block layout.
- log_
update - Inline rendering with line tracking and erasure.
- output
- Virtual output grid for terminal rendering.
- prelude
- Prelude module with commonly used types.
- reactive
- Reactive/signals-based API for Blaeck.
- renderer
- Blaeck renderer for terminal UIs.
- style
- Style primitives for terminal UI rendering.
- timeline
- Declarative animation timeline system.
Macros§
- element
- Re-export the element! macro from blaeck-macros. Used to declare an element and its properties.
Enums§
- Display
- Sets the layout used for the children of this node
Functions§
- Print an element to stdout and return.