v0.28.0
https://github.com/ratatui/ratatui/releases/tag/v0.28.0
β οΈ See the breaking changes for this release.
Crossterm 0.28.0 β¬οΈ
Crossterm is updated to version
0.28.0, which is a
semver incompatible version with the previous version (0.27.0). Ratatui re-exports the version of
crossterm that it is compatible with under ratatui::crossterm, which can be used to avoid
incompatible versions in your dependency list.
See this issue for more information.
Chart: Add GraphType::Bar π
We have introduced a new variant to GraphType, named Bar, which is designed to draw a bar for
each point in the dataset:
let chart = Chart::new(vec![Dataset::default() .data(&data) .marker(symbols::Marker::Dot) .graph_type(GraphType::Bar)]);
Async Example π
We added a new example which demonstrates how to use Ratatui with widgets that fetch data asynchronously.
The code is available here.
Barchart: Support Lines π
Previously, Axis::labels accepted a Vec<Span>. To make it more flexible, we have changed it to
accept a vector of any type that can be converted into a [Line] (e.g., &str, String, &Line,
Span, etc.). This means any code using conversion methods that infer the type will need to be
rewritten as follows.
Axis::default().labels(vec!["a".into(), "b".into()])Axis::default().labels(["a", "b"])Terminal: try_draw β¨
We have added a new method to Terminal called try_draw, which functions similarly to
Terminal::draw but allows the render callback to be a function or closure that returns a Result
instead of nothing (()).
This makes it easier to handle fallible rendering methods using the ? operator:
terminal.try_draw(|frame| { some_method_that_can_fail()?; another_fallible_method()?; Ok(())})?;The method returns Result::Ok with a CompletedFrame if successful, or Result::Err with the
std::io::Error that caused the failure.
Terminal: Make terminal module private π
The terminal module is now private and can not be used directly. The types under this module are exported from the root of the crate.
use ratatui::terminal::{CompletedFrame, Frame, Terminal, TerminalOptions, ViewPort};use ratatui::{CompletedFrame, Frame, Terminal, TerminalOptions, ViewPort};This simplifies the public API, making it more user-friendly for those unfamiliar with Rustβs
re-exports and avoiding clashes with other modules named terminal in backend code.
Backend: Add get/set_cursor_position() π
If you implement the Backend trait yourself, you need to update the implementation and add the
get/set_cursor_position methods, which indicates more clearly what about the cursor to set.
These new methods return/accept Into<Position> which can be either a Position or a (u16, u16)
tuple.
backend.set_cursor_position(Position { x: 0, y: 20 })?;let position = backend.get_cursor_position()?;
terminal.set_cursor_position((0, 20))?;let position = terminal.set_cursor_position()?;You can remove the get/set_cursor methods from your implementation as they are deprecated and a
default implementation for them exists.
Buffer: Add cell, cell_mut and index π§©
Buffer used to access elements with buf.get(x, y) or buf.get_mut(x, y). Now, we have added
support for index operators and introduced buf.cell() and buf.cell_mut() methods.
These new methods use Into<Position> for coordinates, making them easier to use and safer by
returning Option<&Cell> and Option<&mut Cell>, which helps avoid panics (yay).
let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10));
// Access cellslet cell = buf[(0, 0)];let cell = buf[Position::new(0, 0)];
// Get symbollet symbol = buf.cell((0, 0)).map(|cell| cell.symbol());let symbol = buf.cell(Position::new(0, 0)).map(|cell| cell.symbol());
// Set symbolbuf[(0, 0)].set_symbol("π");buf[Position::new(0, 0)].set_symbol("π");buf.cell_mut((0, 0)).map(|cell| cell.set_symbol("π"));buf.cell_mut(Position::new(0, 0)).map(|cell| cell.set_symbol("π"));The existing get() and get_mut() methods are now marked as deprecated.
Frame: Rename size() to area() π
It is just the more correct name. π§
Frame::size is now deprecated.
Text: Add Add and AddAssign implementations βοΈ
You can now combine Line, Span, and Text types together while inferring their types!
let line = Span::raw("Red").red() + Span::raw("blue").blue();let line = Line::raw("Red").red() + Span::raw("blue").blue();let line = Line::raw("Red").red() + Line::raw("Blue").blue();let text = Line::raw("Red").red() + Line::raw("Blue").blue();let text = Text::raw("Red").red() + Line::raw("Blue").blue();
let mut line = Line::raw("Red").red();line += Span::raw("Blue").blue();
let mut text = Text::raw("Red").red();text += Line::raw("Blue").blue();
line.extend(vec![Span::raw("1"), Span::raw("2"), Span::raw("3")]);Text: Remove unnecessary lifetime π§
The ToText trait no longer has a
lifetime parameter.
This change simplifies the trait and makes it easier to implement.
List/Table: New Scroll Methods π½
We have implemented new scroll_down_by(u16) and scroll_up_by(u16) methods for both ListState
and TableState, which allow you to scroll through the items by a specified number of positions.
let mut state = ListState::default();state.select(Some(2));state.scroll_down_by(4);assert_eq!(state.selected, Some(6));
let mut state = TableState::default();state.select(Some(3));state.scroll_up_by(3);assert_eq!(state.selected, Some(0));Table: Navigation Methods π§
You can now navigate in the Table widget by using the following methods!
let mut state = TableState::default();state.select_first();state.select_next();state.select_previous();state.select_last();This is the equivalent API as in ListState.
Tracking Benchmarks β²οΈ
We started using Bencher.dev to track benchmarks over time and easily catch any regressions.
You can view our benchmarks at https://bencher.dev/console/projects/ratatui.
For discussions about future improvements, check out the tracking issue.
Check Semver Violations π¦
We have started experimenting with
cargo-semver-checks in our CI to lint our API
for semver violations!
See the PR for related discussion.
Other πΌ
- Return
SizefromBackend::sizeinstead ofRect(#1254) - Remove unnecessary synchronization in
Layoutcache (#1245)Layout::init_cacheno longer returns bool and takes aNonZeroUsizeinstead ofusize
- Remove unnecessary allocations when creating
Lines (#1237) - Avoid extra allocations when rendering
List&Table(#1244 & #1242) - Add
Size::ZEROandPosition::ORIGINconstants toLayout(#1253) - Enable serde for
Margin,Position,RectandSize(#1255) - Prevent area mismatch in
TestBackend(changes the serde representation) (#1252) - Allow removing all the axis labels in
Chart(#1282) - Only apply style to first line when rendering a
Line(#1247) - Ensure emojis are rendered (#1258)
- Add Code of Conduct (#1279)
βIf you are what you eat, then I only want to eat the good stuff.β β Remy