Skip to content

Repository files navigation

bgraph

btop-style Braille graphing for terminal UIs

Create beautiful, high-resolution filled area graphs in your terminal using Unicode Braille characters. Inspired by btop's smooth CPU/GPU usage graphs.

License: MITMSRV: 1.74+Crates.ioDocs.rs

Features

  • High Resolution - 5 vertical levels per cell; 8x modes for sparklines and braille gauges
  • 🎨 Smooth Gradients - btop-style 5×5 Braille lookup table creates natural transitions
  • 🔧 Simple API - Implement DataSource or wrap closures with FnDataSource
  • 📊 Filled Area Graphs - Beautiful btop-style aesthetic
  • 🎯 Zero-line Support - Optional horizontal reference line
  • 🔄 Flexible Rendering - Braille mode or block character fallback
  • 📦 Ratatui Integration - Widgets + StatefulWidgets for ratatui apps
  • 🧩 Widget Suite - MiniGraph, MiniTimeSeries, Dual/Multi graphs, meters, and gauges

Installation

Add to your Cargo.toml:

[dependencies]
bgraph = "0.1"ratatui = "0.29"

Quick Start

use bgraph::{Graph,DataSource};use ratatui::style::{Color,Style};// Define your data sourcestructSineWave;implDataSourceforSineWave{fnsample(&self,x:f32) -> f32{(x *2.0* std::f32::consts::PI).sin()}}// Create and render graphlet graph = Graph::new(&SineWave).style(Style::default().fg(Color::Cyan)).x_range(0.0,2.0).y_range(-1.5,1.5);// In your ratatui draw loop:
frame.render_widget(graph, area);

Gallery

btop-style dashboard with multi-panel layouts, per-core sparklines, and real-time metrics:

btop-style dashboard demo

Smooth dual graphs with gradient color mapping and position-based coloring:

dual smooth graphs with gradients

Network statistics displaying RX/TX data with mirrored dual graphs and position-gradient coloring:

network dual graph with gradient mode

How It Works

bgraph uses the same technique as btop for creating smooth, filled area graphs:

The Braille Lookup Table

Each character encodes a transition from the previous value to the current value:

 Current Level →
0 1 2 3 4
┌─────────────────────────┐
Prev 0 │ ' ' '⢀' '⢠' '⢰' '⢸' │ (Empty → ...)
Level 1 │ '⡀' '⣀' '⣠' '⣰' '⣸' │ (25% → ...)
↓ 2 │ '⡄' '⣄' '⣤' '⣴' '⣼' │ (50% → ...)
3 │ '⡆' '⣆' '⣦' '⣶' '⣾' │ (75% → ...)
4 │ '⡇' '⣇' '⣧' '⣷' '⣿' │ (Full → ...)
└─────────────────────────┘

Example transitions:

  • '⢀' = 0%→25% (rising from empty)
  • '⣿' = 100%→100% (flat high)
  • '⡇' = 100%→0% (sharp drop)

This creates smooth gradients instead of scatter plots!

Visual Example

Sine wave with btop-style Braille rendering:
⢸⣿⣿⣿⡇ ⢸⣿⣿⣿⡇ ⢸⣿⣿⣿⡇
⢰⣿⣿⣿⣿⣿⡆ ⢰⣿⣿⣿⣿⣿⡆ ⢰⣿⣿⣿⣿⣿⡆
⢀⣾⣿⣿⣿⣿⣿⣿⡀⢀⣾⣿⣿⣿⣿⣿⣿⡀⢀⣾⣿⣿⣿⣿⣿⣿⡀
⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄
⣿⣿⣿⣿⡇ ⣿⣿⣿⣿⡇ ⣿⣿⣿⣿⡇

Usage Examples

Using a Closure

use bgraph::{FnDataSource,Graph};let data = vec![0.2,0.5,0.8,1.0,0.7,0.3];let source = FnDataSource::new(move |x| {let idx = (x *(data.len() - 1)asf32)asusize;
data.get(idx).copied().unwrap_or(0.0)});let graph = Graph::new(&source).x_range(0.0,1.0).y_range(0.0,1.2);

Multiple Graphs

structCPUUsage{/* ... */}structMemoryUsage{/* ... */}implDataSourceforCPUUsage{fnsample(&self,x:f32) -> f32{// Return CPU % at time x}}let cpu_graph = Graph::new(&CPUUsage).style(Style::default().fg(Color::Green));let mem_graph = Graph::new(&MemoryUsage).style(Style::default().fg(Color::Yellow));

Custom Styling

use ratatui::style::{Color,Modifier,Style};let graph = Graph::new(&data_source).style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)).show_zero_line(true).zero_line_style(Style::default().fg(Color::DarkGray)).render_mode(RenderMode::Braille);// or Block

Block Mode Fallback

For terminals that don't support Unicode Braille:

use bgraph::RenderMode;let graph = Graph::new(&data_source).render_mode(RenderMode::Block).wave_char('█');

API Reference

DataSource Trait

pubtraitDataSource{fnsample(&self,x:f32) -> f32;}

Implement this to provide data to the graph.

Graph Widget

implGraph<'_>{pubfnnew(data:&dynDataSource) -> Self;pubfnx_range(self,start:f32,end:f32) -> Self;pubfny_range(self,min:f32,max:f32) -> Self;pubfnstyle(self,style:Style) -> Self;pubfnrender_mode(self,mode:RenderMode) -> Self;pubfnwave_char(self,c:char) -> Self;pubfnshow_zero_line(self,show:bool) -> Self;pubfnzero_line_style(self,style:Style) -> Self;pubfngradient(self,gradient:ColorGradient) -> Self;pubfngradient_mode(self,mode:GradientMode) -> Self;pubfninvert_y(self,invert:bool) -> Self;// Fill from top down}

RenderMode Enum

pubenumRenderMode{Braille,// High-resolution filled area (default)Block,// Simple block characters}

GradientMode Enum

pubenumGradientMode{Value,// Color by data value (default)Position,// Color by row Y position (btop-style)}

ColorGradient

implColorGradient{pubfnnew() -> Self;pubfntwo_point(start:Color,end:Color) -> Self;pubfnthree_point(start:Color,mid:Color,end:Color) -> Self;pubfnadd_stop(self,position:f32,color:Color) -> Self;pubfnget_color(&self,value:f32) -> Color;pubfnprecompute(&self) -> [Color;101];}

Examples

Run the included examples:

# Simple sine wave
cargo run --example simple
# Multi-panel demo showcasing all features
cargo run --example demo

Demo Features

The demo example cycles through 7 panels showcasing all widgets, including the dense btop-style dashboard with per-core sparklines, memory graphs, disk meters, and braille gauges. See HOWTO-DEMO.md for panel-by-panel details.

Comparison with Other Approaches

ApproachResolutionEffectUse Case
bgraph (Braille)5 levels/cellFilled areabtop-style graphs, high detail
Block chars1 cellSimple barsBasic charts, compatibility
Scatter plotVariablePoint cloudScientific data

Gradient Color Mapping

Create heat-map effects like btop by mapping values to colors:

use bgraph::{Graph,ColorGradient,GradientMode};use ratatui::style::Color;// Convenience constructors for common patternslet gradient = ColorGradient::three_point(Color::Rgb(80,140,200),// Cool blue (0%)Color::Rgb(255,180,80),// Warm orange (50%)Color::Rgb(255,80,80),// Hot red (100%));// Or build manually with add_stop()let gradient = ColorGradient::new().add_stop(0.0,Color::Green).add_stop(0.5,Color::Yellow).add_stop(1.0,Color::Red);let graph = Graph::new(&cpu_data).gradient(gradient).y_range(0.0,100.0);

Gradient Modes

Two coloring modes are available:

use bgraph::GradientMode;// Value mode (default): color by data value at each position// More information-dense - color changes reflect actual valueslet graph = Graph::new(&data).gradient(gradient.clone()).gradient_mode(GradientMode::Value);// Position mode (btop-style): color by vertical row position// Top rows get "hot" colors, bottom rows get "cool" colors// More intuitive - "higher = hotter" physically matches the graphlet graph = Graph::new(&data).gradient(gradient.clone()).gradient_mode(GradientMode::Position);

Pre-computed Gradient Tables

For performance-critical code, pre-compute the gradient lookup table:

let gradient = ColorGradient::three_point(Color::Blue,Color::Yellow,Color::Red);// Pre-compute 101 colors (0-100%)let table:[Color;101] = gradient.precompute();// Fast lookup by percentagelet color = table[75];// Color at 75%

Roadmap

  • Gradient color support (like btop's heat maps) ✅
  • Dual graph support (side-by-side/stacked like btop) ✅
  • Horizontal scrolling time series ✅
  • Multiple data series on one graph ✅
  • Position-based gradient mode (btop-style) ✅
  • Gradient convenience constructors ✅

License

MIT

Credits

This library implements the Braille-based graphing technique pioneered by btop, a resource monitor by aristocratos.

The original C++ implementation in btop introduced the brilliant 5×5 Braille lookup table approach for creating smooth, filled area graphs in the terminal. This Rust library adapts that technique for use in ratatui applications.

btop Copyright © 2021 Jakob P. Liljenberg (aristocratos) bgraph adapts the graphing technique under MIT License

Thank you to aristocratos for the inspiration and innovation!

Minimum Supported Rust Version (MSRV)

bgraph requires Rust 1.74.0 or later.

Safety

This crate uses #![deny(unsafe_code)] and contains no unsafe code.

About

A smooth graphing widget for ratatui based on the braille character graphs featured in `btop`

Resources

Code of conduct

Contributing

Stars

33 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages