Skip to main content

Crate blaeck

Crate blaeck 

Source
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:

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 characters
  • layout — 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.rs for multiple signals
  • Understanding internals: Read ARCHITECTURE.md, then renderer.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::blinking_dot;
pub use components::breadcrumbs;
pub use components::breadcrumbs;
pub use components::breadcrumbs_path;
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::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::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
Print an element to stdout and return.