Back to Ratatui

v0.27.0

src/content/docs/highlights/v0.27.md

latest8.5 KB
Original Source

https://github.com/ratatui/ratatui/releases/tag/v0.27.0

⚠️ See the breaking changes for this release.

LineGauge: Background Styles 📊

LineGauge::gauge_style is now deprecated in favor of filled_style and unfilled_style methods which makes it possible to set the foreground/background styles for different states.

rust
let gauge = LineGauge::default()
    .filled_style(Style::default().fg(Color::Green))
    .unfilled_style(Style::default().fg(Color::White))
    .ratio(0.43);

We also added a Line Gauge example:

<video controls> <source src="https://github.com/ratatui/ratatui/assets/5149215/5fb2ce65-8607-478f-8be4-092e08612f5b" type="video/mp4"> Your browser does not support the video tag. </video>

List: Navigation Methods 🧭

You can now navigate in the List widget by using the following methods!

rust
let mut state = ListState::default();
state.select_first();
state.select_next();
state.select_previous();
state.select_last();

It also clamps the selected index to the bounds of the list when navigating.


Text: Conversion From Display 🔄

Text, Span and Line now supports conversion from any type that implements the Display trait!

rust
let text = "line1\nline2".to_text();
let span = (6.66).to_span();
let line = 42.to_line();

This has been made possible with the newly added ToText, ToSpan and ToLine traits respectfully.


Palette Colors 🎨

⚠️ This is behind the "palette" feature flag.

You can now use colors from the palette crate in Ratatui!

rust
use palette::{LinSrgb, Srgb};
use ratatui::style::Color;

let color = Color::from(Srgb::new(1.0f32, 0.0, 0.0));
let color = Color::from(LinSrgb::new(1.0f32, 0.0, 0.0));

New Border Sets 🖼️

border::EMPTY

It uses an empty space symbol (░)

rust
let block = Block::bordered().title("Title").border_set(border::EMPTY);
text
░░░░░░░░
░░    ░░
░░ ░░ ░░
░░ ░░ ░░
░░    ░░
░░░░░░░░

This is useful for when you need to allocate space for the border and apply the border style to a block without actually drawing a border. This makes it possible to style the entire title area or a block rather than just the title content.

border::FULL

It uses a full block symbol (█)

rust
let block = Block::bordered().title("Title").border_set(border::FULL);
text
████
█xx█
█xx█
████

Re-export Backends 📤

crossterm, termion, and termwiz can now be accessed as ratatui::{crossterm, termion, termwiz} respectively.

This makes it possible to just add the Ratatui crate as a dependency and use the backend of choice without having to add the backend crates as dependencies.

To update existing code, replace all instances of crossterm:: with ratatui::crossterm::, termion:: with ratatui::termion::, and termwiz:: with ratatui::termwiz::.

Example for crossterm:

diff
-use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind};
+use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind};

And then you can remove crossterm from Cargo.toml!


Update Prelude 📜

Based on a suggestion on Reddit we made changes to the prelude module.

Note: This module allows you to easily use ratatui without a huge amount of imports! e.g. use ratatui::prelude::*;

The following items have been removed from the prelude:

  • style::Styled - this trait is useful for widgets that want to support the Stylize trait, but it adds complexity as widgets have two style methods and a set_style method.
  • symbols::Marker - this item is used by code that needs to draw to the Canvas widget, but it's not a common item that would be used by most users of the library.
  • terminal::{CompletedFrame, TerminalOptions, Viewport} - these items are rarely used by code that needs to interact with the terminal, and they're generally only ever used once in any app.

The following items have been added to the prelude:

  • layout::{Position, Size} - these items are used by code that needs to interact with the layout system. These are newer items that were added in the last few releases, which should be used more liberally.

Tracing Example 🔍

Wondering how to debug TUI apps? Tried println and it didn't work? We got you covered!

We added an example that demonstrates how to log to a file:


We added a proof-of-concept example for using hyperlinks in the terminal.

The code is available here.


Cell: New methods 🔧

You can now create empty Cells like this:

rust
let mut cell = Cell::EMPTY;
assert_eq!(cell.symbol(), " ");

We also added a constant Cell:new method for simplify the construction as follows:

diff
-let mut cell = Cell::default();
-cell.set_symbol("a");
+let cell = Cell::new("a");

Make Stylize::bg() generic 🔄

Previously, Stylize::bg() accepted Color but now accepts Into<Color>. This allows more flexible types from calling scopes, though it can break some type inference in the calling scope.

rust
let srgb_color: Srgb<u8> = Srgb::new(255, 0, 0);
foo.bg(srgb_color);

Writer Methods on Backends 🖋️

crossterm and termion backends now have writer() and writer_mut() methods for obtain access to the underlying writer.

This is useful e.g. if you want to see what has been written so far.

rust
let terminal = Terminal::new(CrosstermBackend::new(Vec::<u8>::new()));
let ui = |frame| { ... };

terminal.draw(ui);

let crossterm_backend = terminal.backend();
let buffer = crossterm_backend.writer();

Add Missing VHS Tapes 📼

We were missing demos for some of our examples. They are now added!

Constraint explorer example:

Minimal example:


List: Remove deprecated start_corner() 🚫

List::start_corner was deprecated back in v0.25.

Use List::direction and ListDirection instead:

diff
- list.start_corner(Corner::TopLeft);
- list.start_corner(Corner::TopRight);
// This is not an error, BottomRight rendered top to bottom previously
- list.start_corner(Corner::BottomRight);
// all becomes
+ list.direction(ListDirection::TopToBottom);
diff
- list.start_corner(Corner::BottomLeft);
// becomes
+ list.direction(ListDirection::BottomToTop);

layout::Corner is also removed entirely.


Padding: Deprecate zero() 🚫

It is now a constant!

diff
-Padding::zero()
+Padding::ZERO

Buffer: Improve Performance ⚡️

Buffer::filled now moves the cell instead of taking a reference:

diff
-Buffer::filled(area, &Cell::new("X"));
+Buffer::filled(area, Cell::new("X"));

Rect: Improve Performance ⚡️

Margin needs to be passed without reference now:

diff
-let area = area.inner(&Margin {
+let area = area.inner(Margin {
     vertical: 0,
     horizontal: 2,
 });

Other 💼

  • Position and Size now implements Display (#1162)
  • Remove newlines when converting strings to Lines (#1191)
    • Line::from("a\nb") now returns a Line with two Spans instead of one
  • Ensure that zero-width characters are rendered correctly (#1165)
  • Respect area width while rendering &str and String (#1177)
  • Improve benchmark consistency (#1126)

"I can't believe it! A real gourmet kitchen, and I get to watch!" – Remy