PackageTrack
Sign in Get early access

ratatui

A library that's all about cooking up terminal user interfaces

0.30.2 46M downloads/mo #1297 most downloaded on crates.io ratatui/ratatui

What this package is like to depend on

Last release 2 months ago

19 Jun 2026

Release timing varies

gaps range from 2 weeks to 5 months

Nearly every release is documented

notes for 18 of 19 stable releases

Nothing withdrawn

no release was ever pulled

4 years old

87 releases · first in 2023

5 releases in the last 12 months

see the full history below

Release timeline

87 releases · Feb 2023 to Jun 2026
2024 2025 2026
Release Pre-release

Releases

latest 60 of 87
  1. 0.30.2 19 Jun 2026
    Release notes

    We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨‍🍳🐀

    Release highlights: https://ratatui.rs/highlights/v0302/

    ⚠️ List of breaking changes can be found here.

    Features

    • 90639c1 (uncategorized) Add Termina backend by @joshka in #2561

      Summary

      • add the ratatui-termina backend crate using the published termina
        crate
      • expose the backend through the termina feature and Ratatui
        prelude/backend re-exports
      • add a small Termina event-loop example and wire the backend into CI,
        xtask, README generation, and docs

      Refs #1784

      Validation

      • cargo +nightly fmt
      • cargo check -p ratatui-termina --all-features --all-targets
      • cargo check -p ratatui --no-default-features --features termina
      • cargo check -p xtask
      • cargo check -p release-header
      • cargo xtask check-backend termina
      • cargo xtask test-backend termina
      • cargo xtask rdme --check
      • markdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md

    Bug Fixes

    • fce3c80 (widgets) Require thread-safe shadow effects by @joshka in #2584

      Summary

      • require custom shadow effects to preserve the auto traits expected by
        Block-backed widgets
      • document the CellEffect auto-trait contract
      • add a public widget regression test for the affected ratatui::widgets
        re-exports

      Fixes #2583


    • e306ce6 (buffer) Create updates for "uncovered" cells by @benjajaja in #2587

      When a wide cell from the previous buffer is replaced by a short/normal
      cell, the trailing cell does not get an update if its content does not
      change. But if the wide cell has a background (or other) style, the
      terminal did render the trailing cell with that style.

      Force trailing cells to update if background, underline, or modifiers
      are different than the wide cell. We can ignore foreground.

      Fixes #2585 (see that for the detailed visual reports)

    • 81e667f (scrollbar) Keep a large thumb within the track at the end by @satyakwok in #2594

      Closes #2582.

      Problem

      When the content is shorter than the viewport, the thumb is large
      relative to the track. With the position at the end, part_lengths
      clamped thumb_start to track_length - 1 while thumb_length was
      clamped independently to [1, track_length], so thumb_start + thumb_length could exceed track_length.

      bar_symbols lays out begin + track_start + thumb + track_end + end
      and zips it against the cells of the area. When the thumb overruns the
      track, track_end saturates to 0 but the thumb still emits more cells
      than the track can hold, so the trailing end symbol is pushed past the
      end of the area. The last visible cell ends up being a thumb () where
      the end arrow () should be.

      Concretely, for the issue's repro (VerticalRight, content_length = 9, position = 8, height 24): track is 22, thumb_length = 17,
      thumb_start = 6, and 6 + 17 = 23 > 22.

      This is a regression from v0.30.0, where thumb_length was derived as
      thumb_end - thumb_start and therefore always fit within the track.

      Fix

      Clamp thumb_start to track_length - thumb_length (instead of
      track_length - 1) so the thumb always fits within the track and the
      end symbol is preserved.

      Test

      Two regression tests, both fail on main and pass with the fix:

      • thumb_stays_within_track_for_large_thumb_at_end checks
        part_lengths directly with the issue's parameters — asserts
        thumb_start + thumb_length <= track_length and that the parts sum to
        the track length.
      • render_scrollbar_keeps_end_symbol_for_large_thumb renders the #2582
        case (both arrows, large thumb at the end) and asserts the end symbol is
        drawn rather than overwritten by a thumb cell.

      All existing scrollbar tests still pass.

    Miscellaneous Tasks

    • c75d778 (ci) Add cargo-udeps dependency check by @joshka in #2599

      Adds cargo xtask udeps and runs it from CI as a required job.

      This complements cargo-machete rather than replacing it. cargo-machete
      is a fast static source scan, which is why it missed the package-level
      unused deps fixed in #2598 when the same dependency names were still
      referenced by example crates. cargo-udeps compiles the workspace and
      checks rustc dep-info, so it can catch unused dependency declarations
      for the package being checked.

      To make the new job pass, this also removes the remaining true-positive
      unused dev-deps and records explicit cargo-udeps ignores for current
      false positives / intentional cases: ratatui-core critical-section,
      ratatui-crossterm's duplicate crossterm version feature shape, and
      ratatui-termwiz's doc-example-only ratatui dev-dependency.

      I searched existing issues and PRs for udeps / cargo-udeps / "cargo
      udeps". I did not find prior ratatui discussion about adopting
      cargo-udeps; the only hits were Dependabot PR bodies for
      taiki-e/install-action release notes mentioning cargo-udeps version
      updates, for example #1971, #2095, #2194, and #2522.

      Validation:- cargo xtask udeps

      • cargo xtask format --check

    • 4a63d41 (uncategorized) Remove unused dependencies by @KikiKian in #2598

      Audit removes these dependencies that are not used:

      ratatui/Cargo.toml — Removed from [dev-dependencies]:

      • futures
      • rand_chacha
      • tokio
      • tracing
      • tracing-appender
      • tracing-subscriber

      ratatui-core/Cargo.toml — Moved from [dependencies] →
      [dev-dependencies]:

      • indoc

    Continuous Integration

    • 36854ef (uncategorized) Add auto-merge required gate by @joshka in #2596

      Summary

      This makes GitHub auto-merge usable for Ratatui PRs once maintainers are
      happy with the change but CI is still running.

      The workflow change adds a single aggregate required job to the main
      CI workflow. The repository now has auto-merge
      enabled

      and an ensure checks pass
      ruleset
      that requires that required status context on main.

      Why

      Without a required status context, GitHub's auto-merge button is not
      useful for the maintainer flow we want. The goal is to let a maintainer
      review a PR, decide it is ready, click auto-merge, and move on without
      coming back later just to check whether the remaining jobs finished.

      This does not relax the merge policy. GitHub's own auto-merge behavior
      is to merge only after all required reviews and required status checks
      are satisfied. This change gives GitHub a stable required status to wait
      on automatically.

      Precedent

      I have been using this same auto-merge pattern in
      ratatui/tui-widgets, where
      it has worked well for the intended maintainer flow: once a PR looks
      ready, I can enable auto-merge and let GitHub merge it after the
      remaining checks and review requirements are satisfied.

      How it works

      The new required job depends on the main CI jobs in
      .github/workflows/ci.yml and always runs after them. It fails if any
      required dependency fails, is cancelled, or is skipped.

      The repository ruleset requires only this aggregate required context
      instead of requiring every individual matrix job separately. That gives
      GitHub one stable status to wait on while preserving the existing CI
      coverage.

      Things to know

      • Auto-merge is opt-in per PR. Maintainers still choose when to click
        it.
      • It does not skip review requirements, status checks, labels, or any
        other protection rule.
      • A PR with auto-merge enabled can still show as blocked while checks or
        required reviews are pending. That is expected.
      • If something needs to merge normally, maintainers can still use the
        regular merge path or an allowed ruleset bypass. This is a convenience
        path, not a hard blocker.
      • Existing open PRs may need a rebase or synchronize event after this
        lands so they pick up the new required workflow job.
      • If a new required CI job is added later, it should be added to the
        required.needs list or it will not be represented by the aggregate
        gate.
      • Jobs that are intentionally allowed to fail should be handled
        carefully before adding them to required.needs, because skipped,
        cancelled, and failed dependencies make the aggregate fail.

      Current PR state

      Auto-merge is already enabled on this PR. If you approve it and the
      required checks pass, GitHub will squash-merge it automatically;
      approving it is enough to let the PR merge once the remaining
      requirements are satisfied.

      GitHub docs

      Validation

      • ruby -e 'require "yaml"; YAML.load_file(".github/workflows/ci.yml"); puts "ok"'
      • actionlint .github/workflows/ci.yml
      • Verified ratatui/ratatui has allow_auto_merge: true
      • Verified the active ensure checks pass ruleset requires status
        context required
      • Verified this PR has squash auto-merge enabled and is blocked pending
        checks/review

    New Contributors

    • @satyakwok made their first contribution in #2594
    • @KikiKian made their first contribution in #2598

    Full Changelog: ratatui-v0.30.1...ratatui-v0.30.2

    Open source →
    Release notes

    We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨‍🍳🐀

    Release highlights: https://ratatui.rs/highlights/v0302/

    ⚠️ List of breaking changes can be found here.

    Features

    • 90639c1 (uncategorized) Add Termina backend by @joshka in #2561

      Summary

      • add the ratatui-termina backend crate using the published termina crate
      • expose the backend through the termina feature and Ratatui prelude/backend re-exports
      • add a small Termina event-loop example and wire the backend into CI, xtask, README generation, and docs

      Refs #1784

      Validation

      • cargo +nightly fmt
      • cargo check -p ratatui-termina --all-features --all-targets
      • cargo check -p ratatui --no-default-features --features termina
      • cargo check -p xtask
      • cargo check -p release-header
      • cargo xtask check-backend termina
      • cargo xtask test-backend termina
      • cargo xtask rdme --check
      • markdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md

    Bug Fixes

    • fce3c80 (widgets) Require thread-safe shadow effects by @joshka in #2584

      Summary

      • require custom shadow effects to preserve the auto traits expected by Block-backed widgets
      • document the CellEffect auto-trait contract
      • add a public widget regression test for the affected ratatui::widgets re-exports

      Fixes #2583


    • e306ce6 (buffer) Create updates for "uncovered" cells by @benjajaja in #2587

      When a wide cell from the previous buffer is replaced by a short/normal cell, the trailing cell does not get an update if its content does not change. But if the wide cell has a background (or other) style, the terminal did render the trailing cell with that style.

      Force trailing cells to update if background, underline, or modifiers are different than the wide cell. We can ignore foreground.

      Fixes #2585 (see that for the detailed visual reports)

    • 81e667f (scrollbar) Keep a large thumb within the track at the end by @satyakwok in #2594

      Closes #2582.

      Problem

      When the content is shorter than the viewport, the thumb is large relative to the track. With the position at the end, part_lengths clamped thumb_start to track_length - 1 while thumb_length was clamped independently to [1, track_length], so thumb_start + thumb_length could exceed track_length.

      bar_symbols lays out begin + track_start + thumb + track_end + end and zips it against the cells of the area. When the thumb overruns the track, track_end saturates to 0 but the thumb still emits more cells than the track can hold, so the trailing end symbol is pushed past the end of the area. The last visible cell ends up being a thumb () where the end arrow () should be.

      Concretely, for the issue's repro (VerticalRight, content_length = 9, position = 8, height 24): track is 22, thumb_length = 17, thumb_start = 6, and 6 + 17 = 23 > 22.

      This is a regression from v0.30.0, where thumb_length was derived as thumb_end - thumb_start and therefore always fit within the track.

      Fix

      Clamp thumb_start to track_length - thumb_length (instead of track_length - 1) so the thumb always fits within the track and the end symbol is preserved.

      Test

      Two regression tests, both fail on main and pass with the fix:

      • thumb_stays_within_track_for_large_thumb_at_end checks part_lengths directly with the issue's parameters — asserts thumb_start + thumb_length <= track_length and that the parts sum to the track length.
      • render_scrollbar_keeps_end_symbol_for_large_thumb renders the #2582 case (both arrows, large thumb at the end) and asserts the end symbol is drawn rather than overwritten by a thumb cell.

      All existing scrollbar tests still pass.

    Miscellaneous Tasks

    • c75d778 (ci) Add cargo-udeps dependency check by @joshka in #2599

      Adds cargo xtask udeps and runs it from CI as a required job.

      This complements cargo-machete rather than replacing it. cargo-machete is a fast static source scan, which is why it missed the package-level unused deps fixed in #2598 when the same dependency names were still referenced by example crates. cargo-udeps compiles the workspace and checks rustc dep-info, so it can catch unused dependency declarations for the package being checked.

      To make the new job pass, this also removes the remaining true-positive unused dev-deps and records explicit cargo-udeps ignores for current false positives / intentional cases: ratatui-core critical-section, ratatui-crossterm's duplicate crossterm version feature shape, and ratatui-termwiz's doc-example-only ratatui dev-dependency.

      I searched existing issues and PRs for udeps / cargo-udeps / "cargo udeps". I did not find prior ratatui discussion about adopting cargo-udeps; the only hits were Dependabot PR bodies for taiki-e/install-action release notes mentioning cargo-udeps version updates, for example #1971, #2095, #2194, and #2522.

      Validation:- cargo xtask udeps

      • cargo xtask format --check

    • 4a63d41 (uncategorized) Remove unused dependencies by @KikiKian in #2598

      Audit removes these dependencies that are not used:

      ratatui/Cargo.toml — Removed from [dev-dependencies]:

      • futures
      • rand_chacha
      • tokio
      • tracing
      • tracing-appender
      • tracing-subscriber

      ratatui-core/Cargo.toml — Moved from [dependencies] → [dev-dependencies]:

      • indoc

    Continuous Integration

    • 36854ef (uncategorized) Add auto-merge required gate by @joshka in #2596

      Summary

      This makes GitHub auto-merge usable for Ratatui PRs once maintainers are happy with the change but CI is still running.

      The workflow change adds a single aggregate required job to the main CI workflow. The repository now has auto-merge enabled and an ensure checks pass ruleset that requires that required status context on main.

      Why

      Without a required status context, GitHub's auto-merge button is not useful for the maintainer flow we want. The goal is to let a maintainer review a PR, decide it is ready, click auto-merge, and move on without coming back later just to check whether the remaining jobs finished.

      This does not relax the merge policy. GitHub's own auto-merge behavior is to merge only after all required reviews and required status checks are satisfied. This change gives GitHub a stable required status to wait on automatically.

      Precedent

      I have been using this same auto-merge pattern in ratatui/tui-widgets, where it has worked well for the intended maintainer flow: once a PR looks ready, I can enable auto-merge and let GitHub merge it after the remaining checks and review requirements are satisfied.

      How it works

      The new required job depends on the main CI jobs in .github/workflows/ci.yml and always runs after them. It fails if any required dependency fails, is cancelled, or is skipped.

      The repository ruleset requires only this aggregate required context instead of requiring every individual matrix job separately. That gives GitHub one stable status to wait on while preserving the existing CI coverage.

      Things to know

      • Auto-merge is opt-in per PR. Maintainers still choose when to click it.
      • It does not skip review requirements, status checks, labels, or any other protection rule.
      • A PR with auto-merge enabled can still show as blocked while checks or required reviews are pending. That is expected.
      • If something needs to merge normally, maintainers can still use the regular merge path or an allowed ruleset bypass. This is a convenience path, not a hard blocker.
      • Existing open PRs may need a rebase or synchronize event after this lands so they pick up the new required workflow job.
      • If a new required CI job is added later, it should be added to the required.needs list or it will not be represented by the aggregate gate.
      • Jobs that are intentionally allowed to fail should be handled carefully before adding them to required.needs, because skipped, cancelled, and failed dependencies make the aggregate fail.

      Current PR state

      Auto-merge is already enabled on this PR. If you approve it and the required checks pass, GitHub will squash-merge it automatically; approving it is enough to let the PR merge once the remaining requirements are satisfied.

      GitHub docs

      Validation

      • ruby -e 'require "yaml"; YAML.load_file(".github/workflows/ci.yml"); puts "ok"'
      • actionlint .github/workflows/ci.yml
      • Verified ratatui/ratatui has allow_auto_merge: true
      • Verified the active ensure checks pass ruleset requires status context required
      • Verified this PR has squash auto-merge enabled and is blocked pending checks/review

    New Contributors

    • @satyakwok made their first contribution in #2594
    • @KikiKian made their first contribution in #2598

    Full Changelog: https://github.com/ratatui/ratatui/compare/ratatui-v0.30.1...ratatui-v0.30.2

    Open source →
  2. 0.30.1 05 Jun 2026
    Release notes

    "Rats, we're rats; we're the rats." – Rat Movie

    We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨‍🍳🐀

    Release highlights: https://ratatui.rs/highlights/v0301/

    ⚠️ List of breaking changes can be found here.

    Features

    • 74d6a84 (block) Support shadows by orhun in #2481

      Introduce Block::shadow(...) with a new Shadow type that supports:

      • presets: overlay, block, light_shade, medium_shade,
        dark_shade
      • custom symbols via Shadow::symbol(...)
      • custom effects via Shadow::custom(...)
      use ratatui::layout::Offset;
      use ratatui::style::Stylize;
      use ratatui::widgets::{Block, Shadow};
      
      let popup = Block::bordered().title("Popup").shadow(
          Shadow::dark_shade()
              .black()
              .on_white()
              .offset(Offset::new(2, 1)),
      );

      Results in:

      ┌Popup─────┐
      │content   │▒
      └──────────┘▒
        ▒▒▒▒▒▒▒▒▒▒▒
      

      fixes #1892


    • 4d30420 (buffer) Add CellDiffOption::AlwaysUpdate to force cell updates by sxyazi in #2480

      When this option is used, the cells are updated even when content is identical.

      Follow-up for #1605

      Trying to resolve #1116

    • 39c32c6 (buffer) Add cell diff options by benjajaja in #1605

      Problem:Escape sequences always cause a cell to count as "multiwidth",
      even when it doesn't render wider than one cell, or not as wide as the
      escape sequence would be computed as.

      Solution:Convert skip:bool to enum. Add enum option ForceWidth to
      force a cell width for diffing.

      When using the option, this also fixes some bug where diffing is not
      idempotent and causes a diff operation for (symbol.len() - 1) times.

      There are three new specific test cases:

      1. Rendering hyperlinks by squeezing the escape sequence into the first
        cell and forcing the width to the unicode width of the text part.
        This is much easier to implement for a Link widget, as it would only
        need to get the unicode-width once and not iterate over graphemes
        like Spans must do.
      2. Rendering hyperlinks by squeezing the opening sequence into the first
        cell with the first grapheme and forcing the width to that of the
        first grapheme. Then rendering each grapheme as usual. Then squeezing
        the closing sequence into the last cell with the last grapheme and
        forcing the width to that of the last grapheme.
        This is harder to implement for a Link widget, as it would have to
        iterate over graphemes with their width like Spans do.
      3. Kitty image sequence with utf-8 placeholders, similar to 2 but with
        known constant grapheme widths.

      Link widget that leverages this

      https://github.com/benjajaja/tui-link

      It would be cooler if we could just add something like .link(url) to
      Spans, because it would much simpler to insert some link and leverage
      all the Line/Text/Paragraph wrapping and whatnot. With a custom widget
      you need to take care of the Area where you'd want to render it, so
      it's not that clean. But we could iterate on this later, if even
      possible.

    • 6faaddb (core) Implement from slice for line and text by NoOPeEKS in #2371

      This PR adds the following implementations of the From trait for Line
      and Text structs:

      • Implements From<&[T]> where T is Into<Span> for Line, allowing using
        of slices to construct Lines.
      • Implements From<&[T]> where T is Into<Line> for Text, allowing using
        of slices of various types to construct Texts.

      closes #2279

    • 5fc6ab8 (core) Support layout-cache in no_std environments by junkdog in #2399

      this enables "layout-cache" for no_std builds; it's meant for embedded
      environments, where the layout engine otherwise consumes all CPU,
      capping the framerate at around ~10fps. the same app can refresh 300-500
      times per second with layout cache enabled.

      i had to add layout-cache = ["dep:critical-section"] to all builds -
      it's pretty tiny and shouldn't leave a trace in std-builds. the
      alternative is to add an extra layer of features for layout-cache with
      std and no_std, but it pollutes the feature space.


    • ee4b7a9 (crossterm) Add the missing hidden modifier by sxyazi in #2413

      Fixes sxyazi/yazi#3724, see
      sxyazi/yazi#3724 (comment) for a
      reproducer.

      This PR adds the missing Modifier::HIDDEN style and introduces a
      queue_modifier_diff to test ModifierDiff::queue().

      It also fixes a bug where CrosstermAttribute::Bold and
      CrosstermAttribute::Dim would be emitted twice when resetting
      intensity. For example:

      #[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold])]

      would become:

      #[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold, CrosstermAttribute::Bold])]

    • 9d9239a (examples) Add volatility-surface 3D visualization by floor-licker in #2322

      A design demonstration of a 3D volatility surface rendering using
      Braille canvas with interactive rotation and zoom controls. I built this
      for myself for an app I'm currently building but just wanted to share it
      with the community as well to inspire more 3D perspective terminal
      widgets in the future.

      Final Demo

      Description

      Adds a new example demonstrating 3D visualization techniques in the
      terminal. There aren't many examples showing how to represent 3D objects
      in 2D terminal space so my goal is just to demonstrate more advanced
      Canvas and Braille rendering techniques for 3D graphics. The example
      visualizes an implied volatility surface which is a common financial
      visualization using interactive rotation and zoom controls. You can run
      the interactive demo for yourself with cargo run -p volatility-surface

      demo.mov

      <img width="659" height="432" alt="image"

      src="https://github.com/user-attachments/assets/68698cb0-c5d5-4b41-a3c3-65ec8fff12f5"
      />

      Technical Highlights

      • Demonstrates how to implement perspective projection in a terminal
      • Shows advanced use of Canvas widget with Marker::Braille
      • Example of smooth animation patterns and state management
      • Self-contained with synthetic data generation (no external APIs)

    • ae975c7 (examples) Allow overlap spacing in explorer by joshka in #2316

      Store spacing as i16 so negative values map to Spacing::Overlap, and
      show overlap in the axis label.

    • 1e0ab0c (ratatui-crossterm) Add IntoCrossterm for Style by 0xferrous in #2323

    • 101a63e (render) Add function for applying buffer by musjj in #2566

      Add a public API for applying and flushing the terminal buffer.

      A minimal usage will look something like this:

      use ratatui::Terminal;
      use ratatui::backend::CrosstermBackend;
      use ratatui::buffer::Buffer;
      use ratatui::widgets::Widget;
      
      let backend = CrosstermBackend::new(io::stdout());
      let mut terminal = Terminal::new(backend)?;
      
      terminal.autoresize()?;
      
      let mut custom_buffer = Buffer::default();
      custom_buffer.resize(terminal.get_frame().area());
      custom_buffer.reset();
      
      "Hello World!".render(custom_buffer.area, &mut custom_buffer);
      
      terminal.current_buffer_mut().merge(&custom_buffer);
      terminal.apply_buffer()?;

      My primary motivation for this PR is to improve the ECS ergonomics in
      bevy_ratatui. But this
      should be useful for anyone who wants to commit incremental writes to
      the buffer without having to do everything in one monolithic
      Terminal::draw
      closure.


    • 09a3027 (symbol) Add custom marker by BenFradet in #2356

    • f9d066f (table) Let Cells span multiple columns by karkhaz in #2150

      Add a 'column_span' field to table cells. The default value
      is 1; larger values will cause cells to span over multiple columns,
      being rendered over all columns plus the spaces between them.

      Fixes #1568.

    • a5b08d6 (widgets) Add Fill widget by Metbcy in #2520

      Adds a new Fill widget that paints every cell within its area with a
      single repeated symbol and style. Integrates with Stylize so the whole
      chain works as expected:

      use ratatui::widgets::{Fill, Widget};
      use ratatui::style::Stylize;
      
      Fill::new("X").blue().bold().render(area, buf);

      Implements Widget (for both Fill and &Fill) and Styled, accepts
      anything that converts into a Cow<'a, str>, and degrades gracefully on
      empty / multi-grapheme symbols.


    • 9094fd2 (widgets) Add line shape with filled area for Canvas and Chart by bananaofhappiness in #2426

      This commit adds filled area-chart rendering for both Canvas and Chart.

      You can now render a line and fill the area between that line and a baseline Y value, which helps highlight magnitude/volume trends.

      • In Canvas, use FilledLine.
      • In Chart, use GraphType::Area and set the baseline via Dataset::fill_to_y(f64).

      The f64 baseline is now configured on Dataset (not in GraphType), so GraphType stays a simple enum variant.

      Under the hood, line rasterization in canvas was refactored to share a reusable Bresenham point iterator, and FilledLine builds on that to paint vertical spans from each line point to fill_to_y.

      Some screenshots with and without this new type:

      // In Canvas
      use ratatui::widgets::canvas::FilledLine;
      
      Canvas::default()
          .paint(|ctx| {
              ctx.draw(&FilledLine::new(0.0, 0.0, 10.0, 5.0, 0.0, Color::Red));
          });
      
      // In Chart
      let dataset = Dataset::default()
          .data(&data)
          .graph_type(GraphType::Area)
          .fill_to_y(0.0); // fill to y = 0
      
      Chart::new(vec![dataset]);

    • 0a87882 (uncategorized) Add impl From<u16> for Padding and Margin by JayanAXHF in #2438

    • 556cc7b (uncategorized) Add comment for inner area to popup example by Its-Just-Nans in #2309

    • 01a15f9 (uncategorized) Add AsRef impls for widget types by joshka in #2297

    Bug Fixes

    • d12bb83 (barchart) Handle empty horizontal charts by fallintoplace in #2553

      Fixes #2552

      This makes the BarChart constructors ignore empty groups, matching the
      existing .data(...) builder behavior. Without this,

      BarChart::horizontal(Vec::<Bar>::new()) stores one empty group,
      proceeds into horizontal rendering, skips the bar loop, and then
      underflows when computing the group label row from bar_y - self.bar_gap.

      The fix normalizes constructor input through a shared non_empty_groups
      helper for new, horizontal, and grouped. Empty horizontal charts
      now render nothing instead of panicking, and constructor behavior is
      consistent with .data(...).


    • 6396b1c (block) Saturate block edge arithmetic by joshka in #2488

      Motivation

      • Block border and title layout used unchecked u16 arithmetic in
        several places.
      • In debug builds that can panic on tiny or edge-case geometry; in
        release builds the same arithmetic wraps.
      • The original report came from merge-border rendering on tiny areas,
        but the same pattern appeared in title layout and spacing helpers as
        well.

      Description

      • Use saturating arithmetic in Block::inner, render_sides,
        render_corners, titles_area, and vertical_space.
      • Clamp rendered title widths to u16 for layout arithmetic.
      • Replace unchecked title-width accumulation and cursor-advance math
        with bounded arithmetic.
      • Add debug-only regression tests covering empty areas, maximal padding,
        title-area edge cases, and very large title widths.

      Testing

      • Ran cargo test -p ratatui-widgets block::tests.

      Codex
      Task

    • 9143b83 (buffer) Diff for trailing cells when only style changes by gcavelier in #2308

      this PR closes #2307 by preventing unnecessary diff updates for trailing
      cells when only style changes.

      This PR was generated by Claude, and validated by me.

      Summary

      This PR fixes a visual artifact bug where block borders would appear
      offset when rendered over a widget that had a foreground color style
      applied to the entire area.

      The Fix

      - if !next_trailing.skip && prev_trailing != next_trailing {
      + // Only emit update if the SYMBOL changed, not just the style.
      + // The style of hidden trailing cells is not visible, so style
      + // differences alone should not trigger updates that can cause
      + // cursor positioning issues on some terminals.
      + if !next_trailing.skip && prev_trailing.symbol() != next_trailing.symbol() {

      This aligns the code with the documented intent: only emit updates when
      the symbol (visible content) changes, not when only the style
      changes.

      Changes

      File Change
      ratatui-core/src/buffer/buffer.rs:526-530 Compare only symbol, not
      full cell
      ratatui-core/src/buffer/buffer.rs:1376-1425 Add regression test

      Test Added

      #[test]
      fn diff_ignores_style_only_changes_in_trailing_cells() {
          // Verifies that trailing cells with same symbol but different style
          // do NOT generate diff updates
      }

      Why This Is Safe

      1. Trailing cells are hidden - they are visually covered by the wide
        character
      2. Style is invisible - the fg/bg color of a hidden cell has no
        visual effect
      3. Symbol changes still trigger updates - if the symbol changes
        (e.g., from " " to "x"), the update is still emitted
      4. Aligns with documented intent - the original comment says
        "non-blank content", not "different style"

      Related

      • The existing test diff_clears_trailing_cell_for_wide_grapheme
        verifies that symbol changes DO trigger updates
      • This fix complements that behavior by ensuring style-only changes do
        NOT trigger updates
    • e6b71f2 (build) Correct rust-toolchain->rust-version on cargo-deny-action by sermuns in #2471

      closes #2470

    • 65c5202 (changelog) Fix typo by joshka in #2300

    • 43bbaae (clippy) Fix beta clippy errors by Logan-Ruf in #2433

      Noticed these errors on my other PR and figured I could just fix them
      real quick.

      closes #2432

    • 957fbb0 (core) Use correct width for halfwidth dakuten/handakuten by orhun in #2499

      unicode-width reports U+FF9E/U+FF9F as zero-width, but terminals render
      them as 1 cell.
      Adjusts CellWidth trait accordingly for fixing this behavior.

      fixes #2188

    • d7646c7 (core) Avoid overflow in BufferDiff forced-width advance by joshka in #2487

      Motivation

      • Prevent arithmetic overflow when advancing self.pos for
        CellDiffOption::ForcedWidth(NonZeroU16) in
        ratatui-core/src/buffer/diff.rs, which could panic in debug or wrap in
        release and cause an iterator hang/DoS.

      Description

      • Replace the unchecked self.pos += width.get().saturating_sub(1) with
        a saturating addition via self.pos = self.pos.saturating_add(width.get().saturating_sub(1) as usize) to
        avoid overflow while preserving existing iterator semantics.

      Testing

      • Ran cargo test -p ratatui-core buffer::diff --lib and the buffer
        diff tests completed successfully (10 passed, 0 failed).

      Codex
      Task

    • 77f8006 (core) Avoid cursor position queries during resize by orhun in #2485

      Terminal::resize() now clears without calling get_cursor_position(),
      so that CPR (Cursor position report) calls does not interfere with
      stdin.

      Fixes #2483


    • 18aa467 (examples) Make line-gauge example compatible with macos sequoia's terminal.app by lazo4 in #2474

      Part of the fix for #1972

      Summary

      This fix makes the line-gauge example compatible with the macos
      sequoia Terminal.app which doesn't support truecolor. It reuses the
      is_true_color_supported introduced in #2211 by ffex and uses a color
      theme instead of hardcoding the colors.

      Result on macos sequoia

      Before:

      After:

      Notes

      This is my first open source contribution, thanks to @ffex for letting
      me help on this issue

    • ce2c228 (examples) Change flex example colors for MacOS default terminal by ffex in #2211

      Part of the fix for #1972

      Summary

      This fix introduces a function to check if we are in a terminal without
      truecolor(24-bit) and changes the default colors to appear fine of the
      flex example.

      Notes

      The function "is_true_color_supported” is an old problem and there is no
      common way to determine if a terminal supports or not the truecolor.

      This is the main reason why the function detects specifically the
      Terminal.app version before the Tahoe. If there are other known
      terminals with this problem, we can add it to this function.


    • ef72dba (examples) Fix import for widget examples by orhun in #2422

      closes #2299

    • 88441cf (terminal) Fix inline viewport resizing issues by clearing the screen by wyvernbw in #2355

      adds a check to the autoresize function to clear the entire screen and
      move the inline viewport to the top when the window shrinks horizontally
      in order to avoid line wrapping issues.

      Other libraries like ink purge the history as well, but the
      backend::ClearType type does not support that. Without this if the
      user scrolls up they will see previous broken renders. This should work
      well with all terminal emulators and multiplexers.

      fixes #2086

    • 91b6fb7 (tests) Use the correct type for the cell diff test by orhun in #2472

      fixes the CI!

    • 4493742 (widgets) Handle single y-axis label by fallintoplace in #2550

      Fixes #2549.

      This prevents Chart from panicking when the Y axis is configured with
      exactly one label. The X-axis rendering path already skips label
      placement when fewer than two labels are provided; this applies the same
      guard to Y-axis labels before the spacing calculation divides by
      labels_len - 1.

      This also updates the Axis::labels docs so they describe the new

      behavior:fewer than two labels are not rendered instead of causing a
      panic.

    • 0bdebd6 (widgets) Prevent chart scaling overflow by fallintoplace in #2546

      Summary

      Fixes #2545.

      This changes BarChart and Sparkline scaling to use a u128 intermediate
      before division, then caps the scaled ticks at the drawable area. That
      prevents debug-build panics and release-build wrapping when public u64
      chart values are large.

      Validation

      • cargo test -p ratatui-widgets barchart::tests
      • cargo test -p ratatui-widgets sparkline::tests
      • cargo check -p ratatui-widgets --all-features
      • cargo clippy -p ratatui-widgets --all-targets --all-features -- -D warnings
      • cargo test -p ratatui-widgets
    • e27a22a (widgets) Inherit the text alignment for Paragraph by 7Bpencil in #2369

      Paragraph didn't take into account alignment of the text it was created
      from:

      let lines = vec![
          Line::from("one"),
          Line::from("double"),
          Line::from("quadruple"),
      ];
      let text = Text::from(lines).centered();
      
      // used to be rendered left-aligned, now centered
      let paragraph = Paragraph::new(text).block(block);

      Now the Paragraph inherits the text alignment.

    • b5c0831 (widgets) Avoid panic if Clear area is outside of buffer by 7Bpencil in #2368

      If Clear area is at least partially outside of buffer, panic "index
      outside of buffer" happens on Widget::render

      Demo source code
      use crossterm::event::{self, Event, KeyModifiers};
      use ratatui::{
          layout::Rect,
          text::Line,
          widgets::{Block, Borders, Clear, Paragraph},
          DefaultTerminal, Frame,
      };
      use std::iter;
      
      fn main() {
          ratatui::run(app);
      }
      
      fn app(terminal: &mut DefaultTerminal) {
          loop {
              if let Event::Key(key_event) = event::read().expect("failed to read event") {
                  if key_event.kind.is_press()
                      && key_event.modifiers.contains(KeyModifiers::CONTROL)
                      && key_event.code.is_char('c')
                  {
                      break;
                  }
              }
              terminal.draw(render).expect("failed to draw frame");
          }
      }
      
      fn render(frame: &mut Frame) {
          {
              let width = frame.area().width;
              let area = Rect::new(0, 0, width, 10);
              let line = Line::from("W".repeat(area.width as usize));
              let lines: Vec<Line> = iter::repeat_n(line, area.height as usize).collect();
              frame.render_widget(Paragraph::new(lines), area);
          }
          {
              let area = Rect::new(50, 2, 20, 5);
              let block = Block::default()
                  .title_top(Line::from("Popup-with-Clear").centered())
                  .borders(Borders::ALL);
              let lines = vec![
                  Line::from("one"),
                  Line::from

    Note truncated.

    Open source →
    Release notes

    "Rats, we're rats; we're the rats." – Rat Movie

    We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨‍🍳🐀

    Release highlights: https://ratatui.rs/highlights/v0301/

    ⚠️ List of breaking changes can be found here.

    Features

    • 74d6a84 (block) Support shadows by @orhun in #2481

      Introduce Block::shadow(...) with a new Shadow type that supports:

      • presets: overlay, block, light_shade, medium_shade, dark_shade
      • custom symbols via Shadow::symbol(...)
      • custom effects via Shadow::custom(...)
      use ratatui::layout::Offset;
      use ratatui::style::Stylize;
      use ratatui::widgets::{Block, Shadow};
      
      let popup = Block::bordered().title("Popup").shadow(
          Shadow::dark_shade()
              .black()
              .on_white()
              .offset(Offset::new(2, 1)),
      );
      

      Results in:

      ┌Popup─────┐
      │content   │▒
      └──────────┘▒
        ▒▒▒▒▒▒▒▒▒▒▒
      

      fixes #1892


    • 4d30420 (buffer) Add CellDiffOption::AlwaysUpdate to force cell updates by @sxyazi in #2480

      When this option is used, the cells are updated even when content is identical.

      Follow-up for https://github.com/ratatui/ratatui/pull/1605

      Trying to resolve https://github.com/ratatui/ratatui/issues/1116

    • 39c32c6 (buffer) Add cell diff options by @benjajaja in #1605

      Problem:Escape sequences always cause a cell to count as "multiwidth", even when it doesn't render wider than one cell, or not as wide as the escape sequence would be computed as.

      Solution:Convert skip:bool to enum. Add enum option ForceWidth to force a cell width for diffing.

      When using the option, this also fixes some bug where diffing is not idempotent and causes a diff operation for (symbol.len() - 1) times.

      There are three new specific test cases:

      1. Rendering hyperlinks by squeezing the escape sequence into the first cell and forcing the width to the unicode width of the text part. This is much easier to implement for a Link widget, as it would only need to get the unicode-width once and not iterate over graphemes like Spans must do.
      2. Rendering hyperlinks by squeezing the opening sequence into the first cell with the first grapheme and forcing the width to that of the first grapheme. Then rendering each grapheme as usual. Then squeezing the closing sequence into the last cell with the last grapheme and forcing the width to that of the last grapheme. This is harder to implement for a Link widget, as it would have to iterate over graphemes with their width like Spans do.
      3. Kitty image sequence with utf-8 placeholders, similar to 2 but with known constant grapheme widths.

      Link widget that leverages this

      https://github.com/benjajaja/tui-link

      It would be cooler if we could just add something like .link(url) to Spans, because it would much simpler to insert some link and leverage all the Line/Text/Paragraph wrapping and whatnot. With a custom widget you need to take care of the Area where you'd want to render it, so it's not that clean. But we could iterate on this later, if even possible.

    • 6faaddb (core) Implement from slice for line and text by @NoOPeEKS in #2371

      This PR adds the following implementations of the From trait for Line and Text structs:

      • Implements From<&[T]> where T is Into<Span> for Line, allowing using of slices to construct Lines.
      • Implements From<&[T]> where T is Into<Line> for Text, allowing using of slices of various types to construct Texts.

      closes #2279

    • 5fc6ab8 (core) Support layout-cache in no_std environments by @junkdog in #2399

      this enables "layout-cache" for no_std builds; it's meant for embedded environments, where the layout engine otherwise consumes all CPU, capping the framerate at around ~10fps. the same app can refresh 300-500 times per second with layout cache enabled.

      i had to add layout-cache = ["dep:critical-section"] to all builds - it's pretty tiny and shouldn't leave a trace in std-builds. the alternative is to add an extra layer of features for layout-cache with std and no_std, but it pollutes the feature space.


    • ee4b7a9 (crossterm) Add the missing hidden modifier by @sxyazi in #2413

      Fixes https://github.com/sxyazi/yazi/issues/3724, see https://github.com/sxyazi/yazi/issues/3724#issuecomment-3970129744 for a reproducer.

      This PR adds the missing Modifier::HIDDEN style and introduces a queue_modifier_diff to test ModifierDiff::queue().

      It also fixes a bug where CrosstermAttribute::Bold and CrosstermAttribute::Dim would be emitted twice when resetting intensity. For example:

      #[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold])]
      

      would become:

      #[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold, CrosstermAttribute::Bold])]
      

    • 9d9239a (examples) Add volatility-surface 3D visualization by @floor-licker in #2322

      A design demonstration of a 3D volatility surface rendering using Braille canvas with interactive rotation and zoom controls. I built this for myself for an app I'm currently building but just wanted to share it with the community as well to inspire more 3D perspective terminal widgets in the future.

      Final Demo

      Description

      Adds a new example demonstrating 3D visualization techniques in the terminal. There aren't many examples showing how to represent 3D objects in 2D terminal space so my goal is just to demonstrate more advanced Canvas and Braille rendering techniques for 3D graphics. The example visualizes an implied volatility surface which is a common financial visualization using interactive rotation and zoom controls. You can run the interactive demo for yourself with cargo run -p volatility-surface

      https://github.com/user-attachments/assets/aa32a864-54a8-4c67-a3c9-432dd29373fd

      <img width="659" height="432" alt="image"

      src="https://github.com/user-attachments/assets/68698cb0-c5d5-4b41-a3c3-65ec8fff12f5" />

      Technical Highlights

      • Demonstrates how to implement perspective projection in a terminal
      • Shows advanced use of Canvas widget with Marker::Braille
      • Example of smooth animation patterns and state management
      • Self-contained with synthetic data generation (no external APIs)

    • ae975c7 (examples) Allow overlap spacing in explorer by @joshka in #2316

      Store spacing as i16 so negative values map to Spacing::Overlap, and show overlap in the axis label.

    • 1e0ab0c (ratatui-crossterm) Add IntoCrossterm<ContentStyle> for Style by @0xferrous in #2323

    • 101a63e (render) Add function for applying buffer by @musjj in #2566

      Add a public API for applying and flushing the terminal buffer.

      A minimal usage will look something like this:

      use ratatui::Terminal;
      use ratatui::backend::CrosstermBackend;
      use ratatui::buffer::Buffer;
      use ratatui::widgets::Widget;
      
      let backend = CrosstermBackend::new(io::stdout());
      let mut terminal = Terminal::new(backend)?;
      
      terminal.autoresize()?;
      
      let mut custom_buffer = Buffer::default();
      custom_buffer.resize(terminal.get_frame().area());
      custom_buffer.reset();
      
      "Hello World!".render(custom_buffer.area, &mut custom_buffer);
      
      terminal.current_buffer_mut().merge(&custom_buffer);
      terminal.apply_buffer()?;
      

      My primary motivation for this PR is to improve the ECS ergonomics in bevy_ratatui. But this should be useful for anyone who wants to commit incremental writes to the buffer without having to do everything in one monolithic Terminal::draw closure.


    • 09a3027 (symbol) Add custom marker by @BenFradet in #2356

    • f9d066f (table) Let Cells span multiple columns by @karkhaz in #2150

      Add a 'column_span' field to table cells. The default value is 1; larger values will cause cells to span over multiple columns, being rendered over all columns plus the spaces between them.

      Fixes #1568.

    • a5b08d6 (widgets) Add Fill widget by @Metbcy in #2520

      Adds a new Fill widget that paints every cell within its area with a single repeated symbol and style. Integrates with Stylize so the whole chain works as expected:

      use ratatui::widgets::{Fill, Widget};
      use ratatui::style::Stylize;
      
      Fill::new("X").blue().bold().render(area, buf);
      

      Implements Widget (for both Fill and &Fill) and Styled, accepts anything that converts into a Cow<'a, str>, and degrades gracefully on empty / multi-grapheme symbols.


    • 9094fd2 (widgets) Add line shape with filled area for Canvas and Chart by @bananaofhappiness in #2426

      This commit adds filled area-chart rendering for both Canvas and Chart.

      You can now render a line and fill the area between that line and a baseline Y value, which helps highlight magnitude/volume trends.

      • In Canvas, use FilledLine.
      • In Chart, use GraphType::Area and set the baseline via Dataset::fill_to_y(f64).

      The f64 baseline is now configured on Dataset (not in GraphType), so GraphType stays a simple enum variant.

      Under the hood, line rasterization in canvas was refactored to share a reusable Bresenham point iterator, and FilledLine builds on that to paint vertical spans from each line point to fill_to_y.

      Some screenshots with and without this new type: <img width="1460" height="879" alt="изображение" src="https://github.com/user-attachments/assets/c7b534b1-2afb-49c7-9c56-178e6ba9e844" /> <img width="1460" height="881" alt="изображение" src="https://github.com/user-attachments/assets/53592e2c-ee89-4481-9099-be06480d305a" />

      // In Canvas
      use ratatui::widgets::canvas::FilledLine;
      
      Canvas::default()
          .paint(|ctx| {
              ctx.draw(&FilledLine::new(0.0, 0.0, 10.0, 5.0, 0.0, Color::Red));
          });
      
      // In Chart
      let dataset = Dataset::default()
          .data(&data)
          .graph_type(GraphType::Area)
          .fill_to_y(0.0); // fill to y = 0
      
      Chart::new(vec![dataset]);
      

    • 0a87882 (uncategorized) Add impl From<u16> for Padding and Margin by @JayanAXHF in #2438

    • 556cc7b (uncategorized) Add comment for inner area to popup example by @Its-Just-Nans in #2309

    • 01a15f9 (uncategorized) Add AsRef impls for widget types by @joshka in #2297

    Bug Fixes

    • d12bb83 (barchart) Handle empty horizontal charts by @fallintoplace in #2553

      Fixes #2552

      This makes the BarChart constructors ignore empty groups, matching the existing .data(...) builder behavior. Without this,

      BarChart::horizontal(Vec::<Bar>::new()) stores one empty group, proceeds into horizontal rendering, skips the bar loop, and then underflows when computing the group label row from bar_y - self.bar_gap.

      The fix normalizes constructor input through a shared non_empty_groups helper for new, horizontal, and grouped. Empty horizontal charts now render nothing instead of panicking, and constructor behavior is consistent with .data(...).


    • 6396b1c (block) Saturate block edge arithmetic by @joshka in #2488

      Motivation

      • Block border and title layout used unchecked u16 arithmetic in several places.
      • In debug builds that can panic on tiny or edge-case geometry; in release builds the same arithmetic wraps.
      • The original report came from merge-border rendering on tiny areas, but the same pattern appeared in title layout and spacing helpers as well.

      Description

      • Use saturating arithmetic in Block::inner, render_sides, render_corners, titles_area, and vertical_space.
      • Clamp rendered title widths to u16 for layout arithmetic.
      • Replace unchecked title-width accumulation and cursor-advance math with bounded arithmetic.
      • Add debug-only regression tests covering empty areas, maximal padding, title-area edge cases, and very large title widths.

      Testing

      • Ran cargo test -p ratatui-widgets block::tests.

      Codex Task

    • 9143b83 (buffer) Diff for trailing cells when only style changes by @gcavelier in #2308

      this PR closes #2307 by preventing unnecessary diff updates for trailing cells when only style changes.

      This PR was generated by Claude, and validated by me.

      Summary

      This PR fixes a visual artifact bug where block borders would appear offset when rendered over a widget that had a foreground color style applied to the entire area.

      The Fix

      - if !next_trailing.skip && prev_trailing != next_trailing {
      + // Only emit update if the SYMBOL changed, not just the style.
      + // The style of hidden trailing cells is not visible, so style
      + // differences alone should not trigger updates that can cause
      + // cursor positioning issues on some terminals.
      + if !next_trailing.skip && prev_trailing.symbol() != next_trailing.symbol() {
      

      This aligns the code with the documented intent: only emit updates when the symbol (visible content) changes, not when only the style changes.

      Changes

      File Change
      ratatui-core/src/buffer/buffer.rs:526-530 Compare only symbol, not
      full cell
      ratatui-core/src/buffer/buffer.rs:1376-1425 Add regression test

      Test Added

      #[test]
      fn diff_ignores_style_only_changes_in_trailing_cells() {
          // Verifies that trailing cells with same symbol but different style
          // do NOT generate diff updates
      }
      

      Why This Is Safe

      1. Trailing cells are hidden - they are visually covered by the wide character
      2. Style is invisible - the fg/bg color of a hidden cell has no visual effect
      3. Symbol changes still trigger updates - if the symbol changes (e.g., from " " to "x"), the update is still emitted
      4. Aligns with documented intent - the original comment says "non-blank content", not "different style"

      Related

      • The existing test diff_clears_trailing_cell_for_wide_grapheme verifies that symbol changes DO trigger updates
      • This fix complements that behavior by ensuring style-only changes do NOT trigger updates
    • e6b71f2 (build) Correct rust-toolchain->rust-version on cargo-deny-action by @sermuns in #2471

      closes #2470

    • 65c5202 (changelog) Fix typo by @joshka in #2300

    • 43bbaae (clippy) Fix beta clippy errors by @Logan-Ruf in #2433

      Noticed these errors on my other PR and figured I could just fix them real quick.

      closes #2432

    • 957fbb0 (core) Use correct width for halfwidth dakuten/handakuten by @orhun in #2499

      unicode-width reports U+FF9E/U+FF9F as zero-width, but terminals render them as 1 cell. Adjusts CellWidth trait accordingly for fixing this behavior.

      fixes #2188

    • d7646c7 (core) Avoid overflow in BufferDiff forced-width advance by @joshka in #2487

      Motivation

      • Prevent arithmetic overflow when advancing self.pos for CellDiffOption::ForcedWidth(NonZeroU16) in ratatui-core/src/buffer/diff.rs, which could panic in debug or wrap in release and cause an iterator hang/DoS.

      Description

      • Replace the unchecked self.pos += width.get().saturating_sub(1) with a saturating addition via self.pos = self.pos.saturating_add(width.get().saturating_sub(1) as usize) to avoid overflow while preserving existing iterator semantics.

      Testing

      • Ran cargo test -p ratatui-core buffer::diff --lib and the buffer diff tests completed successfully (10 passed, 0 failed).

      Codex Task

    • 77f8006 (core) Avoid cursor position queries during resize by @orhun in #2485

      Terminal::resize() now clears without calling get_cursor_position(), so that CPR (Cursor position report) calls does not interfere with stdin.

      Fixes #2483


    • 18aa467 (examples) Make line-gauge example compatible with macos sequoia's terminal.app by @lazo4 in #2474

      Part of the fix for #1972

      Summary

      This fix makes the line-gauge example compatible with the macos sequoia Terminal.app which doesn't support truecolor. It reuses the is_true_color_supported introduced in #2211 by @ffex and uses a color theme instead of hardcoding the colors.

      Result on macos sequoia

      Before: <img width="566" height="138" alt="Capture d’écran 2026-04-06 à 11 47 07" src="https://github.com/user-attachments/assets/1ea37832-8a07-40b0-b0ab-aa77476ef9eb" /> After: <img width="561" height="120" alt="Capture d’écran 2026-04-06 à 11 46 45" src="https://github.com/user-attachments/assets/4bd50bc1-68f9-4601-b361-f610abf8629d" />

      Notes

      This is my first open source contribution, thanks to @ffex for letting me help on this issue

    • ce2c228 (examples) Change flex example colors for MacOS default terminal by @ffex in #2211

      Part of the fix for #1972

      Summary

      This fix introduces a function to check if we are in a terminal without truecolor(24-bit) and changes the default colors to appear fine of the flex example.

      Notes

      The function "is_true_color_supported” is an old problem and there is no common way to determine if a terminal supports or not the truecolor.

      This is the main reason why the function detects specifically the Terminal.app version before the Tahoe. If there are other known terminals with this problem, we can add it to this function.


    • ef72dba (examples) Fix import for widget examples by @orhun in #2422

      closes #2299

    • 88441cf (terminal) Fix inline viewport resizing issues by clearing the screen by @wyvernbw in #2355

      adds a check to the autoresize function to clear the entire screen and move the inline viewport to the top when the window shrinks horizontally in order to avoid line wrapping issues.

      Other libraries like ink purge the history as well, but the backend::ClearType type does not support that. Without this if the user scrolls up they will see previous broken renders. This should work well with all terminal emulators and multiplexers.

      fixes #2086

    • 91b6fb7 (tests) Use the correct type for the cell diff test by @orhun in #2472

      fixes the CI!

    • 4493742 (widgets) Handle single y-axis label by @fallintoplace in #2550

      Fixes #2549.

      This prevents Chart from panicking when the Y axis is configured with exactly one label. The X-axis rendering path already skips label placement when fewer than two labels are provided; this applies the same guard to Y-axis labels before the spacing calculation divides by labels_len - 1.

      This also updates the Axis::labels docs so they describe the new

      behavior:fewer than two labels are not rendered instead of causing a panic.

    • 0bdebd6 (widgets) Prevent chart scaling overflow by @fallintoplace in #2546

      Summary

      Fixes #2545.

      This changes BarChart and Sparkline scaling to use a u128 intermediate before division, then caps the scaled ticks at the drawable area. That prevents debug-build panics and release-build wrapping when public u64 chart values are large.

      Validation

      • cargo test -p ratatui-widgets barchart::tests
      • cargo test -p ratatui-widgets sparkline::tests
      • cargo check -p ratatui-widgets --all-features
      • cargo clippy -p ratatui-widgets --all-targets --all-features -- -D warnings
      • cargo test -p ratatui-widgets
    • e27a22a (widgets) Inherit the text alignment for Paragraph by @7Bpencil in #2369

      Paragraph didn't take into account alignment of the text it was created from:

      let lines = vec![
          Line::from("one"),
          Line::from("double"),
          Line::from("quadruple"),
      ];
      let text = Text::from(lines).centered();
      
      // used to be rendered left-aligned, now centered
      let paragraph = Paragraph::new(text).block(block);
      

      Now the Paragraph inherits the text alignment.

    • b5c0831 (widgets) Avoid panic if Clear area is outside of buffer by @7Bpencil in #2368

      If Clear area is at least partially outside of buffer, panic "index outside of buffer" happens on Widget::render

      <details>

      <summary>Demo source code</summary>

      use crossterm::event::{self, Event, KeyModifiers};
      use ratatui::{
          layout::Rect,
          text::Line,
          widgets::{Block, Borders, Clear, Paragraph},
          DefaultTerminal, Frame,
      };
      use std::iter;
      
      fn main() {
          ratatui::run(app);
      }
      
      fn app(terminal: &mut DefaultTerminal) {
          loop {
              if let Event::Key(key_event) = event::read().expect("failed to read event") {
                  if key_event.kind.is_press()
                      && key_event.modifiers.contains(KeyModifiers::CONTROL)
                      && key_event.code.is_char('c')
                  {
                      break;
                  }
              }
              terminal.draw(render).expect("failed to draw frame");
          }
      }
      
      fn render(frame: &mut Frame) {
          {
              let width = frame.area().width;
              let area = Rect::new(0, 0, width, 10);
              let line = Line::from("W".repeat(area.width as usize));
              let lines: Vec<Line> = iter::repeat_n(line, area.height as usize).collect();
              frame.render_widget(Paragraph::new(lines), area);
          }
          {
              let area = Rect::new(50, 2, 20, 5);
              let block = Block::default()
                  .title_top(Line::from("Popup-with-Clear").centered())
                  .borders(Borders::ALL);
              let lines = vec![
                  Line::from("one"),
                  Line::from("double"),
                  Line::from("quadruple"),
              ];
              frame.render_widget(Clear, area);
              frame.render_widget(Paragraph::new(lines).block(block).centered(), area);
          }
          {
              let area = Rect::new(80, 2, 20, 5);
              let block = Block::default()
                  .title_top(Line::from("Popup").centered())
                  .borders(Borders::ALL);
              let lines = vec![
                  Line::from("one"),
                  Line::from("double"),
                  Line::from("quadruple"),
              ];
              frame.render_widget(Paragraph::new(lines).block(block).centered(), area);
          }
      }
      

      </details>

      Before the fix:

      https://github.com/user-attachments/assets/cebae1df-87b2-48ae-9456-7ad8cb72035c

      After the fix:

      https://github.com/user-attachments/assets/9e0170f3-9c71-4a28-96b3-3f4b7db8ed37

    • 1ce29d6 (uncategorized) Decouple std from serde and palette features by @december1981 in #2460

      The std feature now passes through to the deps rather than requiring std to use serde / palette.

    • 2a0b4b2 (uncategorized) Ensure consistent thumb size when scrolling by @kdheepak in #2352

      This PR removes the use of f64 for calculating scrollbar thumb size and uses integer rounding (rounding up instead of the default rounding down) instead. Using integer rounding seems to fix the problem of thumb size not being consistent.

      Fixes #2351

    • 4986b28 (uncategorized) Allow ratatui-widgets to be used without default features by @jakobhellermann in #2350

      Previously, ratatui-widgets was always included with default features.

      Additionally, the std feature would always enable the time crate.

      Fixing this gets rid of a few crates: deranged, num-conv, time-core, time.

    • 720303e (uncategorized) Align clear() semantics with contract by @joshka in #2320

    • d2b0ce1 (uncategorized) Fix the dependency on time by @asomers in #2306

      ratatui-widgets uses time's Month::length(), which requires time-0.3.37 or later.

    Refactor

    • d754c5e (app) Simplify render function in the scrollbar example by @marianomarciello in #2388

      Divide the render function into two functions for vertical and horizontal scroll.

    • 629e4b2 (core) Reintroduce Cell::skip as a deprecated field by @junkdog in #2437

      as discussed in https://github.com/ratatui/ratatui/pull/1605#discussion_r2933338973 - this brings back Cell::skip as a deprecated field in order to avoid breaking the API in a patch release. in terms of noise; the diff() is left pretty intact, but had to #[allow(deprecated)] in a couple of places.

      Cell::skip vs CellDiffOption

      CellDiffOption::ForcedWidth takes precedence over Cell::skip, and

      CellDiffOption::skip is already skip - so Cell::skip can only override when CellDiffOption::None is set. i believe this is the correct behavior, but probably good to have another pair of eyes on it. @benjajaja maybe has some input too.

      PartialEq and Hash for Cell::skip

      Cell::skip is part of PartialEq and Hash as normal fields. another option would be to treat CellDiffOption::None as

      CellDiffOption::Skip when Cell::skip is set, and only consider the effective CellDiffOption for the trait impls.


    • ca5c109 (core) Introduce CellWidth trait for cell width computation by @junkdog in #2400

      this PR introduces a CellWidth trait for calculating the cell width/span, implemented for &str and Cell.

      The impl for Cell respects the new CellDiffOption::ForcedWidth. All width calculations are prefixed with a check if the symbol is ascii before calling symbol.width(); this micro-optimization probably won't do much on computers, but it helps on embedded.

      As discussed recently in #1605, this also changes the `CellDiffOption::ForcedWidth(type) from NonZeroUsize to NonZeroU16.


    • 9ac167d (style) Add descriptive panic for Color::Reset anstyle conversion by @singhh-piyush in #2423

      Color::Reset has no equivalent in anstyle::Color. Previously, converting Color::Reset.into() fell through to the catch-all arm in From<Color> for anstyle::Color, which called

      AnsiColor::try_from(color).unwrap() and panicked with the message: called Result::unwrap() on an Err value: Ansi.

      This replaces the opaque unwrap() with an explicit, immediately understandable panic: "Color::Reset has no equivalent in anstyle".

      Fixes #2341

    • f093b02 (uncategorized) Satisfy beta Clippy buffer debug lint by @joshka in #2562

      Remove a redundant borrow in Buffer's Debug implementation

    Documentation

    • f8b42ad (breaking-changes) Update header for 0.30.0 by @orhun in #2295

    • e82b3b7 (buffer) Run the doctests for Buffer by @orhun in #2319

      addresses https://github.com/ratatui/ratatui/pull/2314#pullrequestreview-3621576941

      the doctest was not running at all... (due to fn foo)

    • d8c86c3 (canvas) Add usage example for Line widget by @ramadhan-dev-bright in #2473

      Added a doc-tested example for the Line struct in canvas to improve documentation and help new users understand how to render lines with color.

    • 83c1579 (changelog) Fix doubled words in two entries by @adv0r in #2578

      Typo:in inin and and andand in CHANGELOG.md

    • fff27e8 (contributing) Add packages needed to run xtasks by @alabhyajindal in #2409

      Fixes #2408


    • be718d0 (ratatui-core) Fix terminal rendering grammar by @Zacxxx in #2555

    • 095b47d (ratatui-crossterm) Fix doubled article in module docs by @adv0r in #2564

      Dear maintainer — AI-authored PR by Composer under @adv0r. Methodology + opt-out at tokens-for-good. A one-line "no thanks" → auto-apology + auto-close + permanent blacklist. Silent close treated the same. Your time matters more than this contribution.

      Typo:See the the [Examples]See the [Examples] in ratatui-crossterm/src/lib.rs.

    • 160b177 (ratatui-termwiz) Fix doubled article in module docs by @adv0r in #2565

      Dear maintainer — AI-authored PR by Composer under @adv0r. Methodology + opt-out at tokens-for-good. A one-line "no thanks" → auto-apology + auto-close + permanent blacklist. Silent close treated the same. Your time matters more than this contribution.

      Typo:See the the [Examples]See the [Examples] in ratatui-termwiz/src/lib.rs.

    • 8ce5513 (sparkline) Fix typo in doc comment by @adv0r in #2554

    • e6529fd (terminal) Improve terminal and setup docs for app authors by @joshka in #2461

      Summary

      This updates the terminal and setup docs to better match the rendering behavior Ratatui actually implements, while also making the docs.rs path clearer for application authors.

      The main docs changes are split into two commits:

      1. docs: align terminal docs with behavior
      • align Terminal, viewport, frame, and flush docs with the real render pipeline
        • clarify the boundary between Terminal::flush and Backend::flush
        • improve examples for fullscreen, inline, and fixed viewport usage
      1. docs: improve terminal docs for app authors
      • improve setup-path guidance across ratatui, ratatui-core, and backend crates
        • clarify viewport choice, escape hatches, and common edge cases
      • reduce duplication so crate-level docs explain choices while method docs hold detailed contracts

      A small follow-up also fixes the crate-doc heading hierarchy in ratatui-core and ratatui-crossterm so the generated READMEs no longer need markdownlint-disable-next-line heading-increment suppressions.

      Verification

      • cargo test -p ratatui --doc
      • cargo test -p ratatui-core --doc
      • cargo test -p ratatui-crossterm --doc
      • cargo test -p ratatui-termion --doc
      • cargo test -p ratatui-termwiz --doc
      • cargo test --workspace --all-targets --no-run
      • cargo doc -p ratatui --no-deps
      • cargo doc -p ratatui-core --no-deps
      • cargo xtask format --check
      • cargo xtask readme --check

      Note:cargo doc -p ratatui-core --no-deps still reports pre-existing warnings outside this pass in layout and text docs. The terminal-doc warnings introduced during this work were fixed.


    • 744dc36 (uncategorized) Remove duplicate word in color and backend module by @lphuc2250gma in #2535

      Two one-line typo fixes for duplicated "the" in doc-comments:

      • ratatui-core/src/style/color.rs — "/// the the older serialization implementation of Color are also able to be deserialized." → "...the older serialization..."
      • ratatui-core/src/backend.rs — "//! See the the [Examples] directory for more examples." → "//! See the [Examples] directory for more examples."

      No code/behavior change.

    • 3df8c20 (uncategorized) Ask issue authors about PR willingness by @joshka in #2317

      Add a contribution question to the bug report and feature request templates so maintainers know whether the reporter wants to work on a fix/PR or needs guidance.

    • 53d925a (uncategorized) Add Documentation on the Map Projection / CRS by @C-Loftus in #2324

    • 64d964b (uncategorized) Update Terminal docs by @joshka in #2312

      Summary

      • Improve Terminal Rustdocs to better explain typical app setup, the rendering pipeline, and how diff-based rendering works (including full redraw behavior on viewport size changes).
      • Clarify viewport concepts and behavior in Viewport/Terminal docs, with a more complete inline section (anchoring, scrolling, resize behavior).
      • Reorder Terminal::draw / Terminal::try_draw closer to constructors so the primary rendering entry points are easier to find.

      Notes

      • Docs-only change; no public API or runtime behavior changes.
      • No new tests in this PR.

      Test Plan

      • cargo +nightly fmt
      • cargo +nightly docs-rs -p ratatui-core
      • cargo test -p ratatui-core --doc --features std
    • 8d73d47 (uncategorized) Fix comment to reflect correct symbol in assertion by @homebrewmellow in #2314

    • fbd5621 (uncategorized) Fix misspellings by @cgzones in #2310

    Performance

    • dcea52b (core) Eliminate per-frame Vec allocation in Terminal::flush by @junkdog in #2416

      what and how

      this PR removes the Vec<(u16, u16, &Cell)> allocation in Terminal::flush when calling Buffer::diff. a new method, Buffer::diff_iter is instead used by Terminal::flush.

      the existing diff implementation has moved to the BufferDiff iterator.

      why (who cares?)

      it's the mice. on embedded devices, allocating a short-lived, contiguous block of up to 40-50kb is problematic due to heap fragmentation in combination with tiny heaps. the requirements for a full refresh over 1200 terminal cells is 37.5kb+vec growth padding, but since we're dealing with a contiguous block of memory, the actual memory requirements are considerably higher, depending on user-land allocation patterns.


    Testing

    • b696ea3 (core) Split Terminal into submodules and expand test coverage by @joshka in #2315

      • Split the Terminal implementation into focused submodules to improve readability and maintainability.
      • Add characterization tests covering Terminal initialization, buffer lifecycle, resizing and autoresize behavior, and rendering paths.
      • Add inline viewport tests for compute_inline_size and insert_before in both fallback and scrolling-regions modes, including an end-to-end draw -> insert_before -> draw scenario scenario.
      • Extend TestBackend cursor plumbing to support the new terminal tests and assert cursor/ behavior.

    Miscellaneous Tasks

    • 746e9c9 (build) Add symlinks from each crate dir to root LICENSE by @martinvonz in #2370

      AFAICT, each crate directory must have its own LICENSE file for it to become part of the published crate. This patch therefore adds LICENSE symlinks from each crate directory to the root LICENSE file. This matches what e.g. clap does (https://github.com/clap-rs/clap).

      Since ratatui-macros/LICENSE already exists and with different copyright holders than in the root LICENSE file, I left it unchanged.

    • 7b66bd4 (ci) Use latest released cargo-machete action by @sermuns in #2469

    • b6dfafd (markdown) Fix linting issues reported by xtask lint by @Logan-Ruf in #2435

    • fba4448 (ratatui) Unleash the rats v0.30.1

    • 0b03fe4 (toml) Migrate from taplo to tombi by @joshka in #2501

      Summary

      This migrates the repo's TOML tooling from Taplo to Tombi.

      The main motivation is maintenance and installability:

      • Ratatui previously used Taplo for TOML formatting.
      • Taplo's maintenance future has been uncertain; see https://github.com/tamasfe/taplo/issues/715.
      • Taplo's current release artifacts are not friendly to cargo-binstall, which means some setups fall back to building from source.
      • That source-build path is awkward for CI and was also a blocker while exploring a future Docker/devcontainer setup because of image size and install cost.

      Tombi is actively maintained, publishes prebuilt binaries, and has a VS Code extension that lets us keep editor behavior aligned with CI.

      What Changed

      Tooling and CI

      • Replace taplo with tombi in cargo xtask format.
      • Use tombi-toml/setup-tombi in the formatting CI job.
      • Replace .taplo.toml with tombi.toml.

      Formatting policy

      • Keep the existing 100-column TOML line width.
      • Disable schema-driven top-level table ordering for Cargo.toml.
      • Disable the corresponding tables-out-of-order lint for Cargo.toml.

      Why disable Cargo schema ordering:

      Why disable the Cargo lint warning:

      • The VS Code warning came from Tombi's tables-out-of-order lint rather than from formatting.
      • Since we are intentionally preserving the existing Cargo manifest section order, we also disable that lint for Cargo.toml to keep diagnostics aligned with the formatter configuration.
      • Related docs: https://tombi-toml.github.io/tombi/docs/configuration/.

      Installation note

      • Tombi is better positioned for binary installs than Taplo today, but it is still not fully in the generic cargo-binstall / taiki-e/install-action path.
      • Relevant upstream context:
      • binary naming / generic installer compatibility: https://github.com/tombi-toml/tombi/issues/1164
      • crates.io publishing for cargo-binstall fallback: https://github.com/tombi-toml/tombi/issues/1686
      • earlier crates.io publishing discussion: https://github.com/tombi-toml/tombi/issues/632
      • In practice, this still leaves some rough edges around the generic Rust installer path, but Tombi already has usable prebuilt binaries and an official installer action, which is a better place for Ratatui than Taplo's current install story.
      • CI now uses tombi-toml/setup-tombi with a pinned version, which avoids the GitHub token path by not asking the action to resolve latest at runtime.

      Docs and editor setup

      • Update contributor docs to point to Tombi's repo, docs, and installation guide.
      • Note that the repo previously used Taplo and link the upstream maintenance discussion at https://github.com/tamasfe/taplo/issues/715.
      • Add VS Code extension recommendations for rust-lang.rust-analyzer and tombi-toml.tombi.
      • Add committed VS Code workspace settings for shared repo defaults, mainly so the workspace can define formatter behavior that matches CI, including TOML formatter selection and nightly rustfmt args.
      • Add a dedicated formatting section to CONTRIBUTING.md covering Rust formatting, TOML formatting, nightly rustfmt, and the VS Code workspace override workaround.

      Why Commit VS Code Settings

      This PR adds committed VS Code workspace settings for shared repo defaults only.

      The goal is to:

      • recommend the expected extensions
      • make local editor formatting behave more like CI
      • avoid formatter drift between editor usage and the repo's checked-in tooling

      This is not intended to standardize everyone's full editor setup.

      Nightly rustfmt

      The repo already uses unstable rustfmt options in rustfmt.toml, so formatting Rust code with cargo xtask format works best with nightly Rust. This is already how CI behaves.

      The docs now call this out more clearly:

      • install nightly if you want local formatting to match CI
      • the reason is to pick up the unstable formatting options configured in rustfmt.toml

      For contributors who cannot or do not want to install nightly, the docs also point to a workaround: use a personal VS Code workspace file with override settings instead of changing the tracked workspace config.

      Notes From Implementation

      • Tombi v0.9.19 added config support to disable schema-defined ordering per schema, which let us preserve existing Cargo.toml section order cleanly.
      • The tables-out-of-order warning seen in VS Code came from Tombi lint, not formatting, so that needed a separate config change.
      • After disabling Cargo section ordering, the remaining TOML churn was much smaller and mostly mechanical.

      Files of Interest

      • .github/workflows/ci.yml
      • xtask/src/commands/format.rs
      • tombi.toml
      • .vscode/settings.json
      • .vscode/extensions.json
      • CONTRIBUTING.md

      Verification

      • cargo xtask format --check
      • cargo metadata --format-version 1
      • markdownlint-cli2 CONTRIBUTING.md
    • ed46fef (uncategorized) Update versions

    • f30bab9 (uncategorized) Ignore licker as typo

    • c7746e9 (uncategorized) Bump MSRV to 1.88.0 by @orhun in #2396

    • b0a7703 (uncategorized) Escape usernames in changelog with backticks by @kdheepak in #2377

      This PR escapes all github usernames in the CHANGELOG.md file by adding a backtick before and after the username.

      e.g.:Before

      1dc18bf (calendar) Add width and height functions by @joshka in #2198
      

      After

      1dc18bf (calendar) Add width and height functions by `@joshka` in #2198
      

      This change should prevent unnecessary tags in PRs and forks, at least until the next release is made with git cliff changes from release-plz

    • 0031fc6 (uncategorized) Remove @ sign from github release and PR by @kdheepak in #2353

      Previous PR (https://github.com/ratatui/ratatui/pull/2336) didn't solve the problem, and everyone still seems to be getting notifications (e.g. https://github.com/ratatui/ratatui/pull/2348).

      This PR removes the @ for GitHub usernames in the autogenerated PR body by release-plz.

      {{ changelog | replace(from=" by @", to=" by ") }}
      

      The motivation behind this is that GitHub mentions in PR descriptions trigger notifications for every contributor for every release because their username is part of the changelog.

      With this change, in GitHub PR descriptions the changelog will change like so:

      Before

      1dc18bf (calendar) Add width and height functions by @joshka in #2198
      

      After

      1dc18bf (calendar) Add width and height functions by joshka in #2198
      
    • ab5ad3f (uncategorized) Escape username using backticks in changelog by @kdheepak in #2336

      The motivation behind this is that GitHub mentions in PR descriptions trigger notifications for every contributor for every release because their username is part of the changelog.

    New Contributors

    • @musjj made their first contribution in #2566
    • @adv0r made their first contribution in #2578
    • @fallintoplace made their first contribution in #2550
    • @Zacxxx made their first contribution in #2555
    • @lphuc2250gma made their first contribution in #2535
    • @lazo4 made their first contribution in #2474
    • @Metbcy made their first contribution in #2520
    • @bananaofhappiness made their first contribution in #2426
    • @sermuns made their first contribution in #2469
    • @ramadhan-dev-bright made their first contribution in #2473
    • @junkdog made their first contribution in #2437
    • @december1981 made their first contribution in #2460
    • @7Bpencil made their first contribution in #2369
    • @JayanAXHF made their first contribution in #2438
    • @Logan-Ruf made their first contribution in #2435
    • @singhh-piyush made their first contribution in #2423
    • @gcavelier made their first contribution in #2308
    • @ffex made their first contribution in #2211
    • @BenFradet made their first contribution in #2356
    • @wyvernbw made their first contribution in #2355
    • @NoOPeEKS made their first contribution in #2371
    • @alabhyajindal made their first contribution in #2409
    • @martinvonz made their first contribution in #2370
    • @jakobhellermann made their first contribution in #2350
    • @floor-licker made their first contribution in #2322
    • @C-Loftus made their first contribution in #2324
    • @0xferrous made their first contribution in #2323
    • @homebrewmellow made their first contribution in #2314
    • @karkhaz made their first contribution in #2150
    Open source →
  3. 0.30.0 26 Dec 2025
    Release notes

    "Rats don't just survive; they discover; they create. ... I mean, just look at what they do with the terminal!" – Remy & Orhun

    We are excited to announce the biggest release of ratatui so far - a Rust library that's all about cooking up TUIs 👨‍🍳🐀

    🌠 Added "no_std" support for embedded targets, modularized architecture, major widget & layout upgrades!

    Release highlights: https://ratatui.rs/highlights/v030/

    ⚠️ List of breaking changes can be found here.

    Features

    • 90a77aa (direction) Add Direction::perpendicular(self) by @b-guild in #2197

    • 56d5e05 (bar) Update label and text_value to accept Into<> by @Emivvvvv in #1471 [breaking]

      BREAKING CHANGE:label and text_value now accept Into<> types, which breaks type inference.

      - Bar::default().label("foo".into());
      + Bar::default().label("foo");
      
      - Bar::default().text_value("bar".into());
      + Bar::default().text_value("bar");
      
    • b76ad3b (bar) Impl Styled for Bar by @Emivvvvv in #1476

      Related:https://github.com/ratatui/ratatui/issues/683

    • e15fefa (barchar) Add BarChart::grouped constructor by @joshka in #1513

      Add a new constructor to the BarChart widget that allows creating a grouped barchart with multiple groups of bars.

      Also add a new constructor to the BarGroup widget that allows creating a group of bars with a label.

    • 369b18e (barchart) Reduce barchart creation verbosity by @Emivvvvv in #1453

      Adds constructor methods for BarChart, BarGroup, and Bar

    • 1dc18bf (calendar) Add width and height functions by @joshka in #2198

      Fixes https://github.com/ratatui/ratatui/issues/2016


    • f18bcbf (canvas) Add quadrant, sextant and octant markers by @sbarral in #2235 [breaking]

      The octant marker is an alternative to the Braille marker with the same resolution, but offering densely packed, regular pseudo-pixels, without visible bands between rows and columns.

      Quadrant and Sextants are also added to support 2x2 and 2x3.

      Sextant and Octant unicode characters that are less widely supported at the moment, which is why Braille was left as the default.

      BREAKING CHANGE:addition of new variants to Marker and removal of no longer used constants in ratatui::symbols::braille.

    • 26b05de (chart) Render Braille over Blocks in Charts and Canvas by @j-g00da in #2165

      This makes it possible to stack charts, and write text over block symbols in Charts and Canvas while still showing the block symbols behind the text.

    • bf84c62 (core) Add a has_modifier() method to Style by @sxyazi in #2267

      Resolves https://github.com/ratatui/ratatui/issues/2264

    • 2d713d7 (crossterm) Allow multiple crossterm versions by @joshka in #1841

      This commit introduces feature flags to make it possible for widget library authors to depend on a specific version of crossterm without causing version conflicts. This should make it easier for libraries and apps to update crossterm versions more easily.

      The available feature flags are crossterm_0_28 and crossterm_0_29. By default, the latest version is enabled. If a multiple features are enabled we choose the latest version. We will in general support at least the last two major (0.x) versions of crossterm, and will only remove versions in a major version bump.

    • d99984f (layout) Add Flex::SpaceEvenly by @kdheepak in #1952 [breaking]

      Resolves https://github.com/ratatui/ratatui/issues/1951

      BREAKING CHANGE:Old Flex::SpaceAround behavior is available by using

      Flex::SpaceEvenly and new

      Flex::SpaceAround now distributes space evenly around each element except the middle spacers are twice the size of first and last elements

      With this change, the following variants of Flex are supported:

      • Flex::Start: Aligns items to the start; excess space appears at the end.
      • Flex::End: Aligns items to the end; excess space appears at the start.
      • Flex::Center: Centers items with equal space on both sides.
      • Flex::SpaceAround (new): Distributes space around items; space between items is twice the edge spacing.
      • Flex::SpaceBetween: Distributes space evenly between items except no space at the edges.
      • Flex::SpaceEvenly (previously Flex::SpaceAround): Distributes space evenly between items and edges.
      • Flex::Legacy: Preserves legacy behavior, placing all excess space at the end.

      This aligns behavior of Flex with CSS flexbox more closely.

      The following is a screenshot in action:

      <img width="1090" alt="image"

      src="https://github.com/user-attachments/assets/2c7cd797-27bd-4242-a824-4565d369227b" />


    • 9275d34 (layout) Add Offset::new() constructor by @joshka in #1547

    • 7ad9c29 (linegauge) Customized symbols by @sectore in #1601

      With this PR any symbol (&str) can be used to render filled and unfilled parts of LineGauge now. Before that change, only symbols::line::Set was accepted.

      Note:New methods are introduced to define those symbols: filled_symbol and unfilled_symbol. The method line_set is still there, but marked as deprecated.

    • 92a19cb (list) Highlight symbol styling by @airblast-dev in #1595 [breaking]

      Allow styling for List's highlight symbol

      This change makes it so anything that implements Into<Line> can be used as a highlight symbol.

      BREAKING CHANGE:List::highlight_symbol can no longer be used in const context

      BREAKING CHANGE:List::highlight_symbol accepted &str. Conversion methods that rely on type inference will need to be rewritten as the compiler cannot infer the type.

      closes:https://github.com/ratatui/ratatui/issues/1443


    • e89a526 (no_std) Portable-atomic integration for targets with no atomic types by @j-g00da in #2076

      Improves compatibility with no-std targets that don't support atomic types.

      We support three different scenarios depending on the target:

      1. Terminal applications and other std targets (e.g. espidf):
      • std enabled, portable-atomic disabled
      1. Embedded targets with atomic types, bare metal x86, etc.:
      • std disabled portable-atomic disabled
      1. Embedded targets without atomic types (e.g. single-core MCUs):
      • std disabled, portable-atomic enabled

      Turning on portable-atomic together with std will fall back to std atomic.

    • 1399d95 (no_std) Make palette and serde features depends on std by @j-g00da in #1919

    • b32f781 (no_std) Make ratatui-macros no-std by @j-g00da in #1865

    • 3e1c72f (no_std) Make ratatui compatible with #![no_std] by @j-g00da in #1794 [breaking]

      Resolves #1781

      This PR makes it possible to compile ratatui with #![no_std]. Also makes me answer "We Are So Embedded" to "Are We Embedded Yet?"

    • ab48c06 (no_std) Option to disable layout cache for no_std compatibility by @j-g00da in #1795 [breaking]

      Resolves #1780

      BREAKING CHANGE:Disabling default-features will now disable layout cache, which can have a negative impact on performance.

      Layout::init_cache and Layout::DEFAULT_CACHE_SIZE are now only available if layout-cache feature is enabled.

    • 09173d1 (no_std) Make TestBackend::Error Infallible by @j-g00da in #1823 [breaking]

      BREAKING CHANGE:TestBackend now uses core::convert::Infallible for error handling instead of std::io::Error

    • 007713e (no_std) Replace Backend's io::Error usages with associated Error type by @j-g00da in #1778 [breaking]

      Resolves #1775

      BREAKING CHANGE:Custom backends now have to implement Backend::Error and Backend::clear_region. Additionally some generic Backend usage will have to explicitly set trait bounds for Backend::Error.

    • a42a17e (no_std) Make ratatui-widgets no_std by @j-g00da in #1779

      Resolves #1776

    • 5a232a3 (no_std) Remove redundant std usages in ratatui-widgets by @j-g00da in #1762

    • ebe10cd (no_std) Remove redundant std usages in ratatui-core by @j-g00da in #1753

      Resolves https://github.com/ratatui/ratatui/issues/1751

    • 08b08cc (rect) Centering by @janTatesa in #1814

      Resolves #617

    • ff729b7 (scrollbar) Support retrieving the current position of state by @orhun in #1552

      As of now it is possible to change the position of the Scrollbar but not possible to retrieve the position for further use. e.g.

      let mut state = ScrollbarState::default();
      state.next();
      

      This commit adds a new method "current_position" (since position is already taken by the fluent setter) for that purpose:

      let index = state.get_position(); // yay
      

      See #1545 for the concrete usage of this.

    • 4c3c054 (serde) Handle null modifiers in serde Style by @joshka in #2172

      Allow Style's add_modifier and sub_modifier fields to deserialize from null

    • b9da192 (serde) Derive Serialize/Deserialize for alignment enums by @j-g00da in #1957

      Resolves #1954

    • 89b7421 (serde) Derive Serialize/Deserialize for additional structs/enums by @aurreland in #1883

      This PR adds #[derive(Serialize, Deserialize)] to the following structs:

      • Constraint
      • Direction
      • Spacing
      • Layout
      • AccentedPalette
      • NonAccentedPalette
      • Palette
      • Padding
      • Borders
      • BorderType
      • ListDirection
      • ScrollbarOrientation
      • ScrollDirection
      • RenderDirection
      • HighlightSpacing

      Fixes #1877

    • 03f3f6d (style) Allow add/sub modifiers to be omitted in Style serialization. by @rcorre in #2057

      It's really useful that Style supports Deserialize, this allows TUI apps to have configurable theming without much extra code.

      However, deserializing a style currently fails if add_modifier and sub_modifier are not specified. That means the following TOML config:

      [theme.highlight]
      fg = "white"
      bg = "black"
      

      Will fail to deserialize with "missing field add_modifier". It should be possible to omit modifiers and have them default to "none".

    • ee67347 (symbols) Make Marker non-exhaustive by @j-g00da in #2236 [breaking]

      This will allow us to add new markers without causing further breaking changes.

      BREAKING CHANGE:Marker is now non-exhaustive

    • 985cd05 (symbols) Add dashed borders by @theotchlx in #1573

      Adds several new border sets:

      • ratatui::symbols::border::LIGHT_DOUBLE_DASHED
      • ratatui::symbols::border::HEAVY_DOUBLE_DASHED
      • ratatui::symbols::border::LIGHT_TRIPLE_DASHED
      • ratatui::symbols::border::HEAVY_TRIPLE_DASHED
      • ratatui::symbols::border::LIGHT_QUADRUPLE_DASHED
      • ratatui::symbols::border::HEAVY_QUADRUPLE_DASHED

      And corresponding variants to the ratatui::widgets::BorderType enum

      Fixes:https://github.com/ratatui/ratatui/issues/1355

    • 4c301e8 (text) Implement AddAssign for Text by @acuteenvy in #1956

      This makes it possible to add a second Text instance to a first one using the += operator.

      let mut text = Text::from("line 1");
      text += Text::from("line 2");
      

      Style and alignment applied to the second text is ignored (though styles and alignment of lines and spans are copied).

    • ce4856a (widgets) Add the missing constructor to canvas types by @orhun in #1538

      Allows constructing Rectangle, Points and Circle using the new method instead of initializing with the public fields directly.

    • 22610b0 (uncategorized) Support adding an Offset to Position by @joshka in #2239

      Adds Position::offset() and arithmetic ops (Position + Offset and Position - Offset)

      Fixes:https://github.com/ratatui/ratatui/issues/2018

    • 24e3133 (uncategorized) Add Rect::resize() method by @joshka in #2240

      Fixes:https://github.com/ratatui/ratatui/issues/1440

    • 96d097e (uncategorized) Implement Rect ops for moving by @joshka in #1596

      feat:implement Rect ops for moving

      Implemented Add, AddAssign, Sub, and SubAssign on Rect for Offset. This makes it possible to move rects

      let rect = Rect::new(1, 2, 3, 4);
      let moved = rect + Offset(1, 2);
      let moved = rect - Offset(1, 2);
      let moved = rect + Offset(-1, -2);
      

      Additionally Rect, Size, Offset, and Position now all have MIN and MAX consts.

    • e869cb9 (uncategorized) Add Size::area() by @joshka in #2226

      Add Size::area() returning u32 to avoid u16 overflow Fixes https://github.com/ratatui/ratatui/issues/2204

    • b6588fd (uncategorized) Implement From<Size> for (u16, u16) by @0xb002f0 in #2223

    • 75b78be (uncategorized) Add width() impl for tabs by @joshka in #2049

      The purpose of this is to make it easy for apps to easily calculate the total tab width including all dividers and padding.

    • 8188ed3 (uncategorized) Implement UnicodeWidthStr for Text/Line/Span by @joshka in #2030

      You can now calculate the width of any Text/Line/Span using the UnicodeWidthStr trait instead of the width method on the type. This also makes it possible to use the width_cjk() method if needed.

    • c845fec (uncategorized) Add conversion from Size to Rect by @joshka in #2028

      Rect::from(size) returns a new Rect at the origin (0, 0) with the specified Size

    • 017af11 (uncategorized) Preserve block titles when merging borders by @j-g00da in #1977

      Resolves #1939

    • 6dcd53b (uncategorized) Add ergonomic methods for layouting Rects by @joshka in #1909

      This commit introduces new methods for the Rect struct that simplify the process of splitting a Rect into sub-rects according to a given Layout. By putting these methods on the Rect struct, we make it a bit more natural that a layout is applied to the Rect itself, rather than passing a Rect to the Layout struct to be split.

      Adds:- Rect::layout and Rect::try_layout methods that allow splitting a Rect into an array of sub-rects according to a given Layout.

      • Rect::layout_vec method that returns a Vec of sub-rects.
      • Layout::try_areas method that returns an array of sub-rects, with compile-time checks for the number of constraints. This is added mainly for consistency with the new Rect methods.
      use ratatui_core::layout::{Layout, Constraint, Rect};
      let area = Rect::new(0, 0, 10, 10);
      let layout = Layout::vertical([Constraint::Fill(1); 2]);
      
      // Rect::layout() infers the number of constraints at compile time:
      let [top, main] = area.layout(&layout);
      
      // Rect::try_layout() and Layout::try_areas() do the same, but return a
      // Result:
      let [top, main] = area.try_layout(&layout)?;
      let [top, main] = layout.try_areas(area)?;
      
      // Rect::layout_vec() returns a Vec of sub-rects:
      let areas_vec = area.layout_vec(&layout);
      
      // you can also explicitly specify the number of constraints:
      let areas = area.layout::<2>(&layout);
      let areas = area.try_layout::<2>(&layout)?;
      let areas = layout.try_areas::<2>(area)?;
      
    • 0c3872f (uncategorized) Add Rect::outer() by @joshka in #1929

      Fixes:https://github.com/ratatui/ratatui/issues/211

    • 7bc78bc (uncategorized) Add ratatui::run() method by @joshka in #1707

      This introduces a new ratatui::run() method which runs a closure with a terminal initialized with reasonable defaults for most applications. This calls ratatui::init() before running the closure and ratatui::restore() after the closure completes, and returns the result of the closure.

      A minimal hello world example using the new ratatui::run() method:

      fn main() -> Result<(), Box<dyn std::error::Error>> {
          ratatui::run(|terminal| {
              loop {
                  terminal.draw(|frame| frame.render_widget("Hello World!", frame.area()))?;
                  if crossterm::event::read()?.is_key_press() {
                      break Ok(());
                  }
              }
          })
      }
      

      Of course, this also works both with apps that use free methods and structs:

      fn run(terminal: &mut DefaultTerminal) -> Result<(), AppError> { ... }
      
      ratatui::run(run)?;
      
      struct App { ... }
      
      impl App {
          fn new() -> Self { ... }
          fn run(mut self, terminal: &mut DefaultTerminal) -> Result<(), AppError> { ... }
      }
      
      ratatui::run(|terminal| App::new().run(terminal))?;
      
    • b6fbfcd (uncategorized) Add lifetime to symbol sets by @joshka in #1935

      This makes it possible to create symbol sets at runtime with non-static lifetimes.

      Fixes:https://github.com/ratatui/ratatui/issues/1722

    • 488e5f0 (uncategorized) Make border! work without importing Borders by @j-g00da in #1918

      Currently using border! macro requires explicit import of Borders which is unnecessary.

    • 671c2b4 (uncategorized) Support merging the borders of blocks by @j-g00da

      When two borders overlap, they will automatically merge into a single, clean border instead of overlapping.

      This improves visual clarity and reduces rendering glitches around corners.

      For example:

      assert_eq!(Cell::new("┘").merge_symbol("┏", MergeStrategy::Exact).symbol(), "╆");
      
    • 702fff5 (uncategorized) Implement stylize methods directly on Style by @joshka in #1572 [breaking]

      This makes it possible to create constants using the shorthand methods.

      const MY_STYLE: Style = Style::new().blue().on_black();
      

      Rather than implementing Styled for Style and then adding extension methods that implement the Stylize shorthands, this implements the methods as const functions directly on Style.

      BREAKING CHANGE:Style no longer implements Styled. Any calls to methods implemented by the blanket implementation of Stylize are now defined directly on Style. Remove the Stylize import if it is no longer used by your code.

      The reset() method does not have a direct replacement, as it clashes with the existing reset() method. Use Style::reset() rather than some_style.reset()

      Fixes:#1158

    • 4fcd238 (uncategorized) Support no-std for calendar widget by @joshka in #1852

      Removes the CalendarEventStore::today() function in no-std environments

    • 53cdbbc (uncategorized) Enable serde propagation to backend crates (crossterm, termion) by @ArjunKrish7356 in #1812

      This PR propagates the serde feature from the main ratatui crate to the ratatui-crossterm and ratatui-termion backend crates. Solves #1805

    • 6836a69 (uncategorized) Implement styled for other primitives by @aschey in #1684

    • fcb47d6 (uncategorized) Rename Alignment to HorizontalAlignment and add VerticalAlignment by @joshka in #1735 [breaking]

      We don't anticipate removing or deprecating the type alias in the near future, but it is recommended to update your imports to use the new name.

      Added a VerticalAlignment enum to make the API more consistent. We don't have a specific use case for it yet, but it's better to add it now and be able to use it in the future.

      BREAKING-CHANGE:The Alignment enum has been renamed to HorizontalAlignment to better reflect its purpose. A type alias has been added to maintain backwards compatibility, however there are some cases where type aliases are not enough to maintain backwards compatibility. E.g. when using glob imports to import all the enum variants. This should not affect most users, but it is recommended to update your imports to use the new name.

      - use ratatui::layout::Alignment;
      + use ratatui::layout::HorizontalAlignment;
      
      - use Alignment::*;
      + use HorizontalAlignment::*;
      
    • 2714d6b (uncategorized) Add array and tuple RGB color conversion methods by @joshka in #1703

      Other crates (e.g. colorgrad) that deal with colors can convert colors to a tuple of 3 or 4 u8 values. This commit adds conversion methods from these types to a Color::Rgb instance. Any alpha value is ignored.

      Color::from([255, 0, 0]);
      Color::from((255, 0, 0));
      Color::from([255, 0, 0, 255]);
      Color::from((255, 0, 0, 255));
      
    • 50ba965 (uncategorized) Add a new RatatuiMascot widget by @Its-Just-Nans in #1584

      Move the Mascot from Demo2 into a new widget. Make the Rat grey and adjust the other colors.

      frame.render_widget(RatatuiMascot::default(), frame.area());
      
    • 1d28c89 (uncategorized) Add conversions for anstyle by @joshka in #1581

      https://crates.io/crates/anstyle makes it possible to define colors in an interoperable way. This makes it possible for applications to easily load colors from a variety of formats.

      This is gated by the anstyle feature flag which is disabled by default.


    Bug Fixes

    • a89d3d6 (buffer) Clear behavior with VS16 wide emojis by @nornagon in #2063

      This fixes a bug where certain emojis like ⌨️ would sometimes be "overlaid" onto existing content from the buffer, instead of properly clearing.

      example demonstrating bug

      This PR was generated by Codex, and validated by me:

      1. Behavior of the above example code was buggy before this fix (showed overlaying "b" on top of the keyboard emoji), and fixed after.
      2. The U+FE0F check is not strictly required, but I did note that emoji without this char don't exhibit the buggy behavior, even without the fix.

    • ec30390 (canvas) Round coordinates to nearest grid cell by @joshka in #1507

      Previously the canvas coordinates were rounded towards zero, which causes the rendering to be off by one pixel in some cases. It also meant that pixels at the extreme edges of the canvas can only be drawn if the point was exactly on the edge of the canvas. This commit rounds the coordinates to the nearest integer instead. This may change the output for some apps using Canvas / Charts.

    • afd1ce1 (canvas) Lines that start outside the visible grid are now drawn by @renesat in #1501

      Previously lines with points that were outside the canvas bounds were not drawn at all. Now they are clipped to the bounds of the canvas so that the portion of the line within the canvas is draw.

      To facilitate this, a new Painter::bounds() method which returns the bounds of the canvas is added.

      Fixes:https://github.com/ratatui/ratatui/issues/1489

    • 2b0a044 (ci) Add contents write permission to release-plz PR by @marcoieni in #2119

      https://release-plz.dev/docs/github/quickstart#3-setup-the-workflow

      Fixes https://github.com/release-plz/release-plz/issues/2439

    • 18e70d3 (crossterm) Terminal should keep Bold when removing Dim by @MarSik in #1541

      The Dim removal should behave the same as the logic for Bold removal that sends NormalIntensity sequence and then restores Dim when needed.

    • 16b76e3 (demo) Update the width of demo2 tape by @orhun in #2164

      fixes #1721

    • dca331c (demo) Support tab key in demo2 example by @orhun in #1726

      see #1721

      Not sure what caused this - it's been there for a while probably and we didn't realize it since we used demo2-destroy mostly.

    • 0fd4753 (examples) Run the correct example for chart by @orhun in #1679

      fixes #1678

    • 39479e2 (examples) Ensure that example projects are not published by @orhun in #1672

    • 9314312 (layout) Feature flag cache related types by @joshka in #1842

    • 2dd1977 (layout-cache) Import NonZeroUsize only when layout-cache is enabled by @j-g00da in #1839

      This silences unused import warning, when layout-cache is disabled.

    • 564a9d7 (line-gauge) Pad default label to display 3 numbers by @martinetd in #2053

      Display the default label of the LineGauge widget padded to fill 3 cells. This makes it so that the label doesn't shift around when going from a single digit to double / triple digits.

      To maintain the existing behavior, use a custom label by calling .label() on the LineGauge.

    • a692a6e (lint) Apply rust 1.84 clippy suggestions by @joshka in #1612

      The canvas map constants are now statics instead. Fixes https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays

    • 2e54d5e (macros) Use $crate re-export in text macro by @airblast-dev in #1832

    • 79d5165 (no_std) Propagate std feature flag to dependencies by @j-g00da in #1838

      Disables std feature flags in dependencies and only enables them with ratatui and ratatui-core's std feature flag. This partially fixes the issue of still depending on std, when std feature flag is disabled.

    • 00da8c6 (no_std) Provide f64 polyfills for no_std compatibility by @j-g00da in #1840

      Related:https://github.com/rust-lang/rust/issues/137578

    • 3b13240 (scrollbar) Check for area.is_empty() before rendering by @farmeroy in #1529

      This adds the area.is_empty() back into the scrollbar render method. Without it, the widget panics if the height is 0.

    • f57b696 (span) Dont render control characters by @EdJoPaTo in #1312

    • 2ce958e (table) Allow display of additional table row, if row height > 1 by @Lunderberg in #1452

    • 0a25bc1 (tests) Update the stderr snapshot for ratatui-macros by @orhun in #2161

      New 🦀 broke the CI

    • 5fa342c (widgets) Fix centered block title truncation by @ognis1205 in #1973

      Previously block titles that were aligned center were truncated poorly (aligned to the left, and the last non-fitting title would be truncated on the left and right. This now truncates the titles more obviously centered.

    • f919b25 (uncategorized) String_to_string lint is now part of implicit_clone by @joshka in #2173

    • 1fe64de (uncategorized) Include underline color in anstyle conversion by @aschey in #2004

      Underline color wasn't included in the style conversion logic.

    • c1b8528 (uncategorized) Panic when rendering widgets on too small buffer by @j-g00da in #1996

      Fixes panic on overflow on horizontal Barchart and RatatuiMascot and adds proper tests to all widgets.


    • 08b21fa (uncategorized) Fix panic when rendering a Paragraph out of bounds by @jwodder in #1670

      Fixes #1667.

    • 80bc818 (uncategorized) Fix truncation of left aligned block titles by @joshka in #1931

      truncate the right side of left aligned titles rather than the left side of right aligned titles. This is more obvious as the left side of text often contains more important information. And we generally read left to right.

      This change makes centered titles overwrite left aligned titles and right aligned titles overwrite centered or left aligned titles.

      Fixes:https://github.com/ratatui/ratatui/issues/358

    • 21e3b59 (uncategorized) Fix handling of multi-byte chars in bar chart by @joshka in #1934

      The split_at method requires that the split point is at a valid utf8 character boundary.

      Fixes:https://github.com/ratatui/ratatui/issues/1928

    • e1e4004 (uncategorized) Derive copy for list state by @janTatesa in #1921

    • 12cb5a2 (uncategorized) Allow canvas area to exceed u16::MAX by @Daksh14 in #1891

      This allows Canvas grids where the width * height exceeds u16::MAX by converting values to usize earlier in several methods.

      Fixes:https://github.com/ratatui/ratatui/issues/1449

    • 09cc9ef (uncategorized) Typo in changelog by @joshka in #1857

    • c238aca (uncategorized) padding_right() should set right padding instead of left by @sxyazi in #1837

      Fixes https://github.com/ratatui/ratatui/issues/1836

    • c90ba97 (uncategorized) Avoid unnecessary imports in minimal build by @cgzones in #1787

      core::ops::Range is only used with the feature scrolling-regions. Ensure a minimal cargo check reports no warnings.

    • 416ebdf (uncategorized) Correct clippy errors introduced by rust 1.86.0 update by @j-g00da in #1755

      New version of rust (1.86.0) caused CI to fail.

    • 4eac5b2 (uncategorized) Make deprecation notes more helpful by @joshka in #1702

      AI coding assistants use the deprecation notes to automatically suggest fixes. This commit updates the deprecation notes to push those tools to suggest the correct replacement methods and types.

      Specifically, AI tools often suggest using Buffer::get(x, y), because of their training data where this was prevalent. When fixing these deprecations, they often incorrectly suggest using Buffer::get(x, y) instead of Buffer[(x, y)].

    • 35a8642 (uncategorized) Rect::positions() should be empty when width is 0 and height is nonzero by @jwodder in #1669

      Fixes #1666.

    • f5fc819 (uncategorized) Avoid extra line break on whitespace only lines when wrapping paragraphs by @dotdash in #1636

      Currently whitespace only lines produces an extra line break when trimming is disabled, because both the trimmed as well as the non-trimmed line get inserted. Fix this by only inserting the non-trimmed one.

    • 2892bdd (uncategorized) Rust 1.83 clippy lints by @joshka in #1527

      https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes

    • 36e2d1b (uncategorized) Add feature(doc_cfg) when generating docs by @joshka in #1506

    • 4d7704f (uncategorized) Make StatefulWidget and Ref work with unsized State by @thscharler in #1505

      StatefulWidget::State and StatefulWidgetRef::State are now ?Sized.

      This allows implementations of the traits to use unsized types for the State associated type. This is turn is useful when doing things like boxing different stateful widget types with State which implements Any, are slices or any other dynamically sized type.

    • 7b87509 (uncategorized) Typo by @marcoieni in #1480

    Refactor

    • 8d60e96 (examples) Use crossterm event methods by @joshka in #1792

      Crossterm 0.29 introduced methods to easily check / extract the event type. E.g. as_key_press_event() and is_key_press(). This commit updates the examples to use these methods instead of matching on the event type. This makes the code cleaner and easier to read.

      Also does a general cleanup of the event handling code in the examples.

    • 07bec55 (no_std) Make usages of std explicit in ratatui-core. by @ed-2100 in #1782

      This commit does the following:

      • Adds #[no_std] to lib.rs.
      • Adds extern crate std; to lib.rs.
      • Updates ratatui-core to explicitly use items from std and alloc.
      • Prefers use-ing alloc over std when possible.

      Explanation:

      This allows usages of std in ratatui-core to be clearly pointed out and dealt with individually.

      Eventually, when std is to be feature gated, the associated commit will be much cleaner.

    • f132fa1 (table) Small readability improvements by @joshka in #1510

    • c7c3498 (uncategorized) Use saturating_add in Rect::new by @pharrison31415 in #2216

    • 02e53de (uncategorized) Make use of iter::repeat_n() by @cgzones in #1788

      Applied via clippy --fix. Available since 1.82.0.

    • a195d59 (uncategorized) Move xtask commands to small modules by @joshka in #1620

    • 904b0aa (uncategorized) Move symbols to modules by @joshka in #1594

    • 7c8573f (uncategorized) Rearrange selection_spacing code by @raylu in #1540

    • 217c57c (uncategorized) Modularize backends by @orhun in #1508

      Backend code is now moved to ratatui-crossterm, ratatui-termion and ratatui-termwiz. This should be backwards compatible with existing code.

    • e461b72 (uncategorized) Move {Stateful,}Widget{,Ref} types into individual files by @joshka in #1479

      This is a preparatory refactoring for modularization. No user visible changes.

    Documentation

    • 40e96a2 (block) Add collapsed border example by @joshka in #1899

    • d291042 (block) Revise the block example by @orhun in #1520

      • Moves the block example from ratatui to ratatui-widgets
      • Simplifies the example (bordered, styled, custom borders)

      see #1512

    • 0951da5 (breaking-changes) Improve migration guide for Backend::Error by @j-g00da in #1908

      Related:https://github.com/fujiapple852/trippy/pull/1588

    • bbe1cf9 (breaking-changes) Change MSRV to 1.85 by @j-g00da in #1896

      The minimum supported Rust version is now for ratatui v0.30 is 1.85

    • c7912f3 (breaking-changes) Fix header level by @j-g00da in #1825

    • fcde9cb (changelog) Fix typo by @orhun in #1463

    • 73488ab (contributing) Fix link to widgets_block_renders test by @ognis1205 in #2101

      The CONTRIBUTING.md referenced tests/widgets_block.rs, but the correct path is ratatui/tests/widgets_block.rs. Updated the link so that readers can navigate to the test example without 404 error.


    • 0b025db (contributing) Fix grammar by @j-g00da in #1958

    • 1197b2a (contributing) Add note about using nightly for formatting by @joshka in #1816

    • 3ae6bf1 (contributing) Use cargo-xtask for instructions by @orhun in #1509

      • Updates CONTRIBUTING.md about the usage of xtask
      • Removes Makefile.toml
    • 22e3e84 (core) Remove link to Paragraph widget by @orhun in #1683

    • b65788c (examples) Remove duplicated link by @matthiasbeyer in #2212

    • 200b217 (examples) Add VHS tapes and docs for widget examples by @orhun in #2114

      fixes #1982

      Later on I'll figure out an easy way to regenerate this in the CI and possibly do the same for the app examples' VHS tapes. That's why I haven't added a script or mentioned anything in the docs yet (hint: #1721)


    • 861fbdf (examples) Fix a typo by @j-g00da in #1890

      Makes CI typos check pass again

    • 882cc3c (examples) Update app examples with tapes by @orhun in #1673

    • 4393fae (examples) Move scrollbar example to examples folder by @orhun in #1665

    • 9ea70e2 (examples) Move widget-impl example to examples folder by @orhun in #1663

    • 774ab78 (examples) Move widget-ref-container example to examples folder by @orhun in #1664

      see #1512

    • 910d16e (examples) Move user-input example to examples folder by @orhun in #1659

    • dbfb7da (examples) Move table example to examples folder by @orhun in #1657

    • cb2a58a (examples) Move tracing example to examples folder by @orhun in #1658

    • 7e00b64 (examples) Move panic example to examples folder by @orhun in #1655

    • 8127590 (examples) Move modifiers example to examples folder by @orhun in #1654

    • 7c40c0b (examples) Move popup example to examples folder by @orhun in #1656

      see #1512

    • d87354f (examples) Move list example to examples folder by @orhun in #1653

      see #1512

      also renames it to todo-list

    • 621226f (examples) Move inline example to examples folder by @orhun in #1651

    • 9ba7d25 (examples) Move hyperlink example to examples folder by @orhun in #1650

    • bb94d1c (examples) Move minimal example to examples folder by @orhun in #1649

    • 9f399ac (examples) Move gauge example to examples folder by @orhun in #1646

    • 104d6a6 (examples) Move custom-widget example to examples folder by @orhun in #1644

    • fa8ca01 (examples) Move flex example to examples folder by @orhun in #1642

    • f5fde0e (examples) Move constraints example to examples folder by @orhun in #1641

    • fc70288 (examples) Move constraint-explorer example to examples folder by @orhun in #1640

    • 325f961 (examples) Move hello-world example to examples folder by @orhun in #1647

    • 867c4bc (examples) Move colors-rgb example to examples folder by @joshka in #1582

      • docs: move colors-rgb example to examples folder
      • docs: update main examples README

    • 72334ed (layout) Update documentation to point to kasuari solver by @a-kenji in #2003

    • 2be9ccb (layout) Remove unnecessary path prefix by @j-g00da in #1766

    • b669ceb (layout) Change cassowary to kasuari crate reference by @j-g00da in #1765

    • f907c74 (license) Update copyright years by @LVivona in #1639

      Update MIT Licence to copyright year 2025

    • 68b9f67 (readme) Add Built with Ratatui badge for downstream projects by @harilvfs in #1905

    • 088aac1 (readme) Tweak links and badges by @joshka in #1598

    • 6e43672 (readme) Reimagine README.md by @orhun in #1569

      This is the result of the re-imagination of a more suitable README.md. It is simpler and shorter: not giving more information to the user than they actually need.

      Also updates the quickstart code with the up-to-date version and adds link to templates which was missing.


    • 8f28247 (readme) Correct examples links by @HoKim98 in #1484

    • 9f90f74 (readme) Fix broken link by @nilsmartel in #1485

    • 260af68 (readme) Include iocraft as an alternative by @kdheepak in #1483

    • 8e5151f (rect) Fix typo in the Rect::outer function comments by @orhun in #2123

    • 40f13c6 (rect) Update the outdated comment for Rect::area() by @isgin01 in #2100

      The return value of Rect.area() is no longer of u16 type, and the value is not being clumped anymore.

    • ce16692 (release) Fix typo by @j-g00da in #1754

    • 9a930a6 (terminal) Made usage of Terminal::get_frame() clearer by @Blaeriz in #2071

      Closes : https://github.com/ratatui/ratatui/issues/1200


    • b08b4cb (terminal) Add disclaimer

    Open source →
  4. 0.30.0-beta.1 23 Dec 2025 pre-release

    Nothing published for this version

  5. 0.30.0-beta.0 31 Oct 2025 pre-release

    Nothing published for this version

  6. 0.30.0-alpha.5 30 Jun 2025 pre-release

    Nothing published for this version

  7. 0.30.0-alpha.4 19 May 2025 pre-release

    Nothing published for this version

  8. 0.30.0-alpha.3 13 May 2025 pre-release

    Nothing published for this version

  9. 0.30.0-alpha.2 01 Mar 2025 pre-release

    Nothing published for this version

  10. 0.30.0-alpha.1 15 Jan 2025 pre-release

    Nothing published for this version

  11. 0.30.0-alpha.0 27 Nov 2024 pre-release

    Nothing published for this version

  12. 0.29.1-alpha.0 26 Oct 2024 pre-release

    Nothing published for this version

  13. 0.29.0 21 Oct 2024
    Release notes

    "Food will come, Remy. Food always comes to those who love to cook." – Gusteau

    We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨‍🍳🐀

    Release highlights: https://ratatui.rs/highlights/v029/

    ⚠️ List of breaking changes can be found here.

    Features

    • 3a43274 (color) Add hsluv support by @du-ob in #1333

    • 4c4851c (example) Add drawing feature to the canvas example by @orhun in #1429

      fun fact: I had to do 35 pushups for this...


    • e5a7609 (line) Impl From<Cow<str>> for Line by @joshka in #1373 [breaking]

      BREAKING-CHANGES:Line now implements From<Cow<str>

      As this adds an extra conversion, ambiguous inferred values may no longer compile.

      // given:
      struct Foo { ... }
      impl From<Foo> for String { ... }
      impl From<Foo> for Cow<str> { ... }
      
      let foo = Foo { ... };
      let line = Line::from(foo); // now fails due to ambiguous type inference
      // replace with
      let line = Line::from(String::from(foo));
      

      Fixes:https://github.com/ratatui/ratatui/issues/1367


    • 2805ddd (logo) Add a Ratatui logo widget by @joshka in #1307

      This is a simple logo widget that can be used to render the Ratatui logo in the terminal. It is used in the examples/ratatui-logo.rs example, and may be used in your applications' help or about screens.

      use ratatui::{Frame, widgets::RatatuiLogo};
      
      fn draw(frame: &mut Frame) {
          frame.render_widget(RatatuiLogo::tiny(), frame.area());
      }
      
    • d72968d (scrolling-regions) Use terminal scrolling regions to stop Terminal::insert_before from flickering by @nfachan in #1341 [breaking]

      The current implementation of Terminal::insert_before causes the viewport to flicker. This is described in #584 .

      This PR removes that flickering by using terminal scrolling regions (sometimes called "scroll regions"). A terminal can have its scrolling region set to something other than the whole screen. When a scroll ANSI sequence is sent to the terminal and it has a non-default scrolling region, the terminal will scroll just inside of that region.

      We use scrolling regions to implement insert_before. We create a region on the screen above the viewport, scroll that up to make room for the newly inserted lines, and then draw the new lines. We may need to repeat this process depending on how much space there is and how many lines we need to draw.

      When the viewport takes up the entire screen, we take a modified approach. We create a scrolling region of just the top line (could be more) of the viewport, then use that to draw the lines we want to output. When we're done, we scroll it up by one line, into the scrollback history, and then redraw the top line from the viewport.

      A final edge case is when the viewport hasn't yet reached the bottom of the screen. This case, we set up a different scrolling region, where the top is the top of the viewport, and the bottom is the viewport's bottom plus the number of lines we want to scroll by. We then scroll this region down to open up space above the viewport for drawing the inserted lines.

      Regardless of what we do, we need to reset the scrolling region. This PR takes the approach of always resetting the scrolling region after every operation. So the Backend gets new scroll_region_up and scroll_region_down methods instead of set_scrolling_region, scroll_up, scroll_down, and reset_scrolling_region methods. We chose that approach for two reasons. First, we don't want Ratatui to have to remember that state and then reset the scrolling region when tearing down. Second, the pre-Windows-10 console code doesn't support scrolling region

      This PR:

      • Adds a new scrolling-regions feature.
      • Adds two new Backend methods: scroll_region_up and scroll_region_down.
      • Implements those Backend methods on all backends in the codebase.
      • The crossterm and termion implementations use raw ANSI escape sequences. I'm trying to merge changes into those two projects separately to support these functions.
      • Adds code to Terminal::insert_before to choose between insert_before_scrolling_regions and insert_before_no_scrolling_regions. The latter is the old implementation.
      • Adds lots of tests to the TestBackend to for the scrolling-region-related Backend methods.
      • Adds versions of terminal tests that show that insert_before doesn't clobber the viewport. This is a change in behavior from before.
    • dc8d058 (table) Add support for selecting column and cell by @airblast-dev in #1331 [breaking]

      Fixes https://github.com/ratatui-org/ratatui/issues/1250

      Adds support for selecting a column and cell in TableState. The selected column, and cells style can be set by Table::column_highlight_style and Table::cell_highlight_style respectively.

      The table example has also been updated to display the new functionality:

      https://github.com/user-attachments/assets/e5fd2858-4931-4ce1-a2f6-a5ea1eacbecc

      BREAKING CHANGE:The Serialized output of the state will now include the "selected_column" field. Software that manually parse the serialized the output (with anything other than the Serialize implementation on TableState) may have to be refactored if the "selected_column" field is not accounted for. This does not affect users who rely on the Deserialize, or Serialize implementation on the state.

      BREAKING CHANGE:The Table::highlight_style is now deprecated in favor of Table::row_highlight_style.


    • ab6b1fe (tabs) Allow tabs to be deselected by @joshka in #1413 [breaking]

      Tabs::select() now accepts Into<Option<usize>> instead of usize. This allows tabs to be deselected by passing None.

      Tabs::default() is now also implemented manually instead of deriving Default, and a new method Tabs::titles() is added to set the titles of the tabs.

      Fixes:https://github.com/ratatui/ratatui/pull/1412

      BREAKING CHANGE:Tabs::select() now accepts Into<Option<usize>> which breaks any code already using parameter type inference:

      let selected = 1u8;
      - let tabs = Tabs::new(["A", "B"]).select(selected.into())
      + let tabs = Tabs::new(["A", "B"]).select(selected as usize)
      
    • 23c0d52 (text) Improve concise debug view for Span,Line,Text,Style by @joshka in #1410

      Improves https://github.com/ratatui/ratatui/pull/1383

      The following now round trips when formatted for debug. This will make it easier to use insta when testing text related views of widgets.

      Text::from_iter([
          Line::from("Hello, world!"),
          Line::from("How are you?").bold().left_aligned(),
          Line::from_iter([
              Span::from("I'm "),
              Span::from("doing ").italic(),
              Span::from("great!").bold(),
          ]),
      ]).on_blue().italic().centered()
      
    • 60cc15b (uncategorized) Add support for empty bar style to Sparkline by @fujiapple852 in #1326 [breaking]

      • distinguish between empty bars and bars with a value of 0
      • provide custom styling for empty bars
      • provide custom styling for individual bars
      • inverts the rendering algorithm to be item first

      Closes:#1325

      BREAKING CHANGE:Sparkline::data takes IntoIterator<Item = SparklineBar> instead of &[u64] and is no longer const

    • 453a308 (uncategorized) Add overlap to layout by @kdheepak in #1398 [breaking]

      This PR adds a new feature for the existing Layout::spacing method, and introducing a Spacing enum.

      Now Layout::spacing is generic and can take

      • zero or positive numbers, e.g. Layout::spacing(1) (current functionality)
      • negative number, e.g. Layout::spacing(-1) (new)
      • variant of the Spacing (new)

      This allows creating layouts with a shared pixel for segments. When spacing(negative_value) is used, spacing is ignored and all segments will be adjacent and have pixels overlapping. spacing(zero_or_positive_value) behaves the same as before. These are internally converted to Spacing::Overlap or Spacing::Space.

      Here's an example output to illustrate the layout solve from this PR:

      #[test]
      fn test_layout() {
          use crate::layout::Constraint::*;
          let mut terminal = crate::Terminal::new(crate::backend::TestBackend::new(50, 4)).unwrap();
          terminal
              .draw(|frame| {
                  let [upper, lower] = Layout::vertical([Fill(1), Fill(1)]).areas(frame.area());
      
                  let (segments, spacers) = Layout::horizontal([Length(10), Length(10), Length(10)])
                      .flex(Flex::Center)
                      .split_with_spacers(upper);
      
                  for segment in segments.iter() {
                      frame.render_widget(
                          crate::widgets::Block::bordered()
                              .border_set(crate::symbols::border::DOUBLE),
                          *segment,
                      );
                  }
                  for spacer in spacers.iter() {
                      frame.render_widget(crate::widgets::Block::bordered(), *spacer);
                  }
      
                  let (segments, spacers) = Layout::horizontal([Length(10), Length(10), Length(10)])
                      .flex(Flex::Center)
                      .spacing(-1) // new feature
                      .split_with_spacers(lower);
      
                  for segment in segments.iter() {
                      frame.render_widget(
                          crate::widgets::Block::bordered()
                              .border_set(crate::symbols::border::DOUBLE),
                          *segment,
                      );
                  }
                  for spacer in spacers.iter() {
                      frame.render_widget(crate::widgets::Block::bordered(), *spacer);
                  }
              })
              .unwrap();
          dbg!(terminal.backend());
      }
      
      ┌────────┐╔════════╗╔════════╗╔════════╗┌────────┐
      └────────┘╚════════╝╚════════╝╚════════╝└────────┘
      ┌─────────┐╔════════╔════════╔════════╗┌─────────┐
      └─────────┘╚════════╚════════╚════════╝└─────────┘
      

      Currently drawing a border on top of an existing border overwrites it. Future PRs will allow for making the border drawing handle overlaps better.


    • 7bdccce (uncategorized) Add an impl of DoubleEndedIterator for Columns and Rows by @fujiapple852 [breaking]

      BREAKING-CHANGE:The pub modifier has been removed from fields on the

      layout::rect::Columns and layout::rect::Rows iterators. These fields were not intended to be public and should not have been accessed directly.

      Fixes:#1357

    Bug Fixes

    • 4f5503d (color) Hsl and hsluv are now clamped before conversion by @joshka in #1436 [breaking]

      The from_hsl and from_hsluv functions now clamp the HSL and HSLuv values before converting them to RGB. This ensures that the input values are within the expected range before conversion.

      Also note that the ranges of Saturation and Lightness values have been aligned to be consistent with the palette crate. Saturation and Lightness for from_hsl are now in the range [0.0..1.0] while from_hsluv are in the range [0.0..100.0].

      Refs:- https://github.com/Ogeon/palette/discussions/253

      Fixes:https://github.com/ratatui/ratatui/issues/1433

    • b7e4885 (color) Fix doc test for from_hsl by @joshka in #1421

    • 3df685e (rect) Rect::area now returns u32 and Rect::new() no longer clamps area to u16::MAX by @joshka in #1378 [breaking]

      This change fixes the unexpected behavior of the Rect::new() function to be more intuitive. The Rect::new() function now clamps the width and height of the rectangle to keep each bound within u16::MAX. The Rect::area() function now returns a u32 instead of a u16 to allow for larger areas to be calculated.

      Previously, the Rect::new() function would clamp the total area of the rectangle to u16::MAX, by preserving the aspect ratio of the rectangle.

      BREAKING CHANGE:Rect::area() now returns a u32 instead of a u16.

      Fixes:https://github.com/ratatui/ratatui/issues/1375

    • 514d273 (terminal) Use the latest, resized area when clearing by @roberth in #1427

    • 0f48239 (terminal) Resize() now resizes fixed viewports by @Patryk27 in #1353

      Terminal::resize() on a fixed viewport used to do nothing due to an accidentally shadowed variable. This now works as intended.

    • a52ee82 (text) Truncate based on alignment by @Lunderberg in #1432

      This is a follow-up PR to https://github.com/ratatui/ratatui/pull/987, which implemented alignment-aware truncation for the Line widget. However, the truncation only checked the Line::alignment field, and any alignment inherited from a parent's Text::alignment field would not be used.

      This commit updates the truncation of Line to depend both on the individual Line::alignment, and on any alignment inherited from the parent's Text::alignment.

    • 611086e (uncategorized) Sparkline docs / doc tests by @joshka in #1437

    • b9653ba (uncategorized) Prevent calender render panic when terminal height is small by @adrodgers in #1380

      Fixes:#1379

    • da821b4 (uncategorized) Clippy lints from rust 1.81.0 by @fujiapple852 in #1356

    • 68886d1 (uncategorized) Add unstable-backend-writer feature by @Patryk27 in #1352

      https://github.com/ratatui/ratatui/pull/991 created a new unstable feature, but forgot to add it to Cargo.toml, making it impossible to use on newer versions of rustc - this commit fixes it.

    Refactor

    • 6db16d6 (color) Use palette types for Hsl/Hsluv conversions by @orhun in #1418 [breaking]

      BREAKING-CHANGE:Previously Color::from_hsl accepted components as individual f64 parameters. It now accepts a single palette::Hsl value and is gated behind a palette feature flag.

      - Color::from_hsl(360.0, 100.0, 100.0)
      + Color::from_hsl(Hsl::new(360.0, 100.0, 100.0))
      

      Fixes:https://github.com/ratatui/ratatui/issues/1414


    • edcdc8a (layout) Rename element to segment in layout by @kdheepak in #1397

      This PR renames element to segment in a couple of functions in the layout calculations for clarity. element can refer to segments or spacers and functions that take only segments should use segment as the variable names.

    • 1153a9e (uncategorized) Consistent result expected in layout tests by @farmeroy in #1406

      Fixes #1399 I've looked through all the assert_eq and made sure that they follow the expected, result pattern. I wasn't sure if it was desired to actually pass result and expected as variables to the assert_eq statements, so I've left everything that seems to have followed the pattern as is.

    • 20c88aa (uncategorized) Avoid unneeded allocations by @mo8it in #1345

    Documentation

    • b13e2f9 (backend) Added link to stdio FAQ by @Valentin271 in #1349

    • b88717b (constraint) Add note about percentages by @joshka in #1368

    • 381ec75 (readme) Reduce the length by @joshka in #1431

      Motivation for this is that there's a bunch of stuff at the bottom of the Readme that we don't really keep up to date. Instead it's better to link to the places that we do keep this info.

    • 4728f0e (uncategorized) Tweak readme by @joshka in #1419

      Fixes:https://github.com/ratatui/ratatui/issues/1417

    • 4069aa8 (uncategorized) Fix missing breaking changes link by @joshka in #1416

    • 870bc6a (uncategorized) Use Frame::area() instead of size() in examples by @hosseinnedaee in #1361

      Frame::size() is deprecated

    Performance

    • 8db7a9a (uncategorized) Implement size hints for Rect iterators by @airblast-dev in #1420

    Styling

    • e02947b (example) Update panic message in minimal template by @orhun in #1344

    Miscellaneous Tasks

    • 67c0ea2 (block) Deprecate block::Title by @joshka in #1372

      ratatui::widgets::block::Title is deprecated in favor of using Line to represent titles. This removes an unnecessary layer of wrapping (string -> Span -> Line -> Title).

      This struct will be removed in a future release of Ratatui (likely 0.31). For more information see:

      https://github.com/ratatui/ratatui/issues/738

      To update your code:

    
    Block::new().title(Title::from("foo"));
    // becomes any of
    
    Block::new().title("foo");
    
    Block::new().title(Line::from("foo"));
    
    Block::new().title(Title::from("foo").position(Position::TOP));
    // becomes any of
    
    Block::new().title_top("foo");
    
    Block::new().title_top(Line::from("foo"));
    
    Block::new().title(Title::from("foo").position(Position::BOTTOM));
    // becomes any of
    
    Block::new().title_bottom("foo");
    
    Block::new().title_bottom(Line::from("foo"));
    
    • 6515097 (cargo) Check in Cargo.lock by @joshka in #1434

      When kept up to date, this makes it possible to build any git version with the same versions of crates that were used for any version, without it, you can only use the current versions. This makes bugs in semver compatible code difficult to detect.

      The Cargo.lock file is not used by downstream consumers of the crate, so it is safe to include it in the repository (and recommended by the Rust docs).

      See:- https://doc.rust-lang.org/cargo/faq.html#why-have-cargolock-in-version-control

      • https://blog.rust-lang.org/2023/08/29/committing-lockfiles.html
      • https://github.com/rust-lang/cargo/issues/8728
    • c777beb (ci) Bump git-cliff-action to v4 by @orhun in #1350

      See:https://github.com/orhun/git-cliff-action/releases/tag/v4.0.0

    • 69e0cd2 (deny) Allow Zlib license in cargo-deny configuration by @orhun in #1411

    • bc10af5 (style) Make Debug output for Text/Line/Span/Style more concise by @joshka in #1383

      Given:```rust

      Text::from_iter([ Line::from("without line fields"), Line::from("with line fields").bold().centered(), Line::from_iter([ Span::from("without span fields"), Span::from("with span fields") .green() .on_black() .italic() .not_dim(), ]), ])

    
    Debug:```
    Text [Line [Span("without line fields")], Line { style: Style::new().add_modifier(Modifier::BOLD), alignment: Some(Center), spans: [Span("with line fields")] }, Line [Span("without span fields"), Span { style: Style::new().green().on_black().add_modifier(Modifier::ITALIC).remove_modifier(Modifier::DIM), content: "with span fields" }]]
    

    Fixes: https://github.com/ratatui/ratatui/issues/1382


    • f6f7794 (uncategorized) Remove leftover prelude refs / glob imports from example code by @joshka in #1430

      Fixes:https://github.com/ratatui/ratatui/issues/1150

    • 9fd1bee (uncategorized) Make Positions iterator fields private by @joshka in #1424 [breaking]

      BREAKING CHANGE:The Rect Positions iterator no longer has public fields. The rect and current_position fields have been made private as they were not intended to be accessed directly.

    • c32baa7 (uncategorized) Add benchmark for Table by @airblast-dev in #1408

    • 5ad623c (uncategorized) Remove usage of prelude by @joshka in #1390

      This helps make the doc examples more explicit about what is being used. It will also makes it a bit easier to do future refactoring of Ratatui, into several crates, as the ambiguity of where types are coming from will be reduced.

      Additionally, several doc examples have been simplified to use Stylize, and necessary imports are no longer hidden.

      This doesn't remove the prelude. Only the internal usages.

    • f4880b4 (deps) Pin unicode-width to 0.2.0 by @orhun in #1403 [breaking]

      We pin unicode-width to avoid breaking applications when there are breaking changes in the library.

      Discussion in #1271

    Continuous Integration

    • 5635b93 (uncategorized) Add cargo-machete and remove unused deps by @Veetaha in #1362

      https://github.com/bnjbvr/cargo-machete

    New Contributors

    • @roberth made their first contribution in #1427
    • @du-ob made their first contribution in #1333
    • @farmeroy made their first contribution in #1406
    • @adrodgers made their first contribution in #1380
    • @Veetaha made their first contribution in #1362
    • @hosseinnedaee made their first contribution in #1361
    • @Patryk27 made their first contribution in #1352

    Full Changelog: https://github.com/ratatui/ratatui/compare/v0.28.1...v0.29.0

    Open source →
  14. 0.29.0-alpha.0 19 Oct 2024 pre-release

    Nothing published for this version

  15. 0.28.2-alpha.6 12 Oct 2024 pre-release

    Nothing published for this version

  16. 0.28.2-alpha.5 05 Oct 2024 pre-release

    Nothing published for this version

  17. 0.28.2-alpha.4 28 Sep 2024 pre-release

    Nothing published for this version

  18. 0.28.2-alpha.3 21 Sep 2024 pre-release

    Nothing published for this version

  19. 0.28.2-alpha.2 14 Sep 2024 pre-release

    Nothing published for this version

  20. 0.28.2-alpha.1 07 Sep 2024 pre-release

    Nothing published for this version

  21. 0.28.2-alpha.0 31 Aug 2024 pre-release

    Nothing published for this version

  22. 0.28.1 25 Aug 2024
    Release notes

    Features

    • ed51c4b (terminal) Add ratatui::init() and restore() methods by @joshka in #1289

      These are simple opinionated methods for creating a terminal that is useful to use in most apps. The new init method creates a crossterm backend writing to stdout, enables raw mode, enters the alternate screen, and sets a panic handler that restores the terminal on panic.

      A minimal hello world now looks a bit like:

      use ratatui::{
          crossterm::event::{self, Event},
          text::Text,
          Frame,
      };
      
      fn main() {
          let mut terminal = ratatui::init();
          loop {
              terminal
                  .draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
                  .expect("Failed to draw");
              if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
                  break;
              }
          }
          ratatui::restore();
      }
      

      A type alias DefaultTerminal is added to represent this terminal type and to simplify any cases where applications need to pass this terminal around. It is equivalent to: Terminal<CrosstermBackend<Stdout>>

      We also added ratatui::try_init() and try_restore(), for situations where you might want to handle initialization errors yourself instead of letting the panic handler fire and cleanup. Simple Apps should prefer the init and restore functions over these functions.

      Corresponding functions to allow passing a TerminalOptions with a Viewport (e.g. inline, fixed) are also available (init_with_options, and try_init_with_options).

      The existing code to create a backend and terminal will remain and is not deprecated by this approach. This just provides a simple one line initialization using the common options.


    Bug Fixes

    • aed60b9 (terminal) Terminal::insert_before would crash when called while the viewport filled the screen by @nfachan in #1329

      Reimplement Terminal::insert_before. The previous implementation would insert the new lines in chunks into the area between the top of the screen and the top of the (new) viewport. If the viewport filled the screen, there would be no area in which to insert lines, and the function would crash.

      The new implementation uses as much of the screen as it needs to, all the way up to using the whole screen.

      This commit:

      • adds a scrollback buffer to the TestBackend so that tests can inspect and assert the state of the scrollback buffer in addition to the screen
      • adds functions to TestBackend to assert the state of the scrollback
      • adds and updates TestBackend tests to test the behavior of the scrollback and the new asserting functions
      • reimplements Terminal::insert_before, including adding two new helper functions Terminal::draw_lines and Terminal::scroll_up.
      • updates the documentation for Terminal::insert_before to clarify some of the edge cases
      • updates terminal tests to assert the state of the scrollback buffer
      • adds a new test for the condition that causes the bug
      • adds a conversion constructor Cell::from(char)

      Fixes:https://github.com/ratatui/ratatui/issues/999

    • fdd5d8c (text) Remove trailing newline from single-line Display trait impl by @LucasPickering in #1320

    • 2fb0b8a (uncategorized) Fix u16 overflow in Terminal::insert_before. by @nfachan in #1323

      If the amount of characters in the screen above the viewport was greater than u16::MAX, a multiplication would overflow. The multiply was used to compute the maximum chunk size. The fix is to just do the multiplication as a usize and also do the subsequent division as a usize.

      There is currently another outstanding issue that limits the amount of characters that can be inserted when calling Terminal::insert_before to u16::MAX. However, this bug can still occur even if the viewport and the amount of characters being inserted are both less than u16::MAX, since it's dependant on how large the screen is above the viewport.

      Fixes #1322

    Documentation

    • 3631b34 (examples) Add widget implementation example by @joshka in #1147

      This new example documents the various ways to implement widgets in Ratatui. It demonstrates how to implement the Widget trait on a type, a reference, and a mutable reference. It also shows how to use the WidgetRef trait to render boxed widgets.

    • d5477b5 (examples) Use ratatui::crossterm in examples by @joshka in #1315

    • 730dfd4 (examples) Show line gauge in demo example by @montmorill in #1309

    • 9ed85fd (table) Fix incorrect backticks in TableState docs by @airblast-dev in #1342

    • 6d1bd99 (uncategorized) Minor grammar fixes by @matta in #1330

    • 097ee86 (uncategorized) Remove superfluous doc(inline) by @EdJoPaTo in #1310

      It's no longer needed since #1260

    • 3fdb5e8 (uncategorized) Fix typo in terminal.rs by @mrjackwills in #1313

    Testing

    • 0d5f3c0 (uncategorized) Avoid unneeded allocations in assertions by @mo8it in #1335

      A vector can be compared to an array.

    Miscellaneous Tasks

    • 65da535 (ci) Update release strategy by @orhun in #1337

      closes #1232

      Now we can trigger point releases by pushing a tag (follow the instructions in RELEASE.md). This will create a release with generated changelog.

      There is still a lack of automation (e.g. updating CHANGELOG.md), but this PR is a good start towards improving that.

    • 57d8b74 (ci) Use cargo-docs-rs to lint docs by @joshka in #1318

    • 8b624f5 (maintainers) Remove EdJoPaTo by @EdJoPaTo in #1314

    • 23516bc (uncategorized) Rename ratatui-org to ratatui by @joshka in #1334

      All urls updated to point at https://github.com/ratatui

      To update your repository remotes, you can run the following commands:

      git remote set-url origin https://github.com/ratatui/ratatui
      

    Build

    • 0256269 (uncategorized) Simplify Windows build by @joshka in #1317

      Termion is not supported on Windows, so we need to avoid building it.

      Adds a conditional dependency to the Cargo.toml file to only include termion when the target is not Windows. This allows contributors to build using the --all-features flag on Windows rather than needing to specify the features individually.

    New Contributors

    • @nfachan made their first contribution in #1329
    • @LucasPickering made their first contribution in #1320
    • @montmorill made their first contribution in #1309

    Full Changelog: https://github.com/ratatui/ratatui/compare/v0.28.0...v0.28.1

    Open source →
  23. 0.28.1-alpha.2 24 Aug 2024 pre-release

    Nothing published for this version

  24. 0.28.1-alpha.1 17 Aug 2024 pre-release

    Nothing published for this version

  25. 0.28.1-alpha.0 10 Aug 2024 pre-release

    Nothing published for this version

  26. 0.28.0 07 Aug 2024
    Release notes

    "If you are what you eat, then I only want to eat the good stuff." – Remy

    We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 🐭

    In this version, we have upgraded to Crossterm 0.28.0, introducing enhanced functionality and performance improvements. New features include GraphType::Bar, lines in bar charts, and enhanced scroll/navigation methods. We have also refined the terminal module and added brand new methods for cursor positions and text operations.

    Release highlights: https://ratatui.rs/highlights/v028/

    ⚠️ List of breaking changes can be found here.

    Features

    • 8d4a102 (barchart) Allow axes to accept Lines by @joshka in #1273 [breaking]

      Fixes:https://github.com/ratatui/ratatui/issues/1272

    • a23ecd9 (buffer) Add Buffer::cell, cell_mut and index implementations by @joshka in #1084

      Code which previously called buf.get(x, y) or buf.get_mut(x, y) should now use index operators, or be transitioned to buff.cell() or buf.cell_mut() for safe access that avoids panics by returning Option<&Cell> and Option<&mut Cell>.

      The new methods accept Into<Position> instead of x and y coordinates, which makes them more ergonomic to use.

      let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10));
      
      let cell = buf[(0, 0)];
      let cell = buf[Position::new(0, 0)];
      
      let symbol = buf.cell((0, 0)).map(|cell| cell.symbol());
      let symbol = buf.cell(Position::new(0, 0)).map(|cell| cell.symbol());
      
      buf[(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 marked as deprecated. These are fairly widely used and we will leave these methods around on the buffer for a longer time than our normal deprecation approach (2 major release)

      Addresses part of: https://github.com/ratatui/ratatui/issues/1011


    • afe1534 (chart) Accept IntoIterator for axis labels by @EdJoPaTo in #1283 [breaking]

      BREAKING CHANGES: #1273 is already breaking and this only advances the already breaking part

    • 5b51018 (chart) Add GraphType::Bar by @joshka in #1205

    • f97e07c (frame) Replace Frame::size() with Frame::area() by @EdJoPaTo in #1293

      Area is the more correct term for the result of this method. The Frame::size() method is marked as deprecated and will be removed around Ratatui version 0.30 or later.

      Fixes:https://github.com/ratatui/ratatui/pull/1254#issuecomment-2268061409

    • 5b89bd0 (layout) Add Size::ZERO and Position::ORIGIN constants by @EdJoPaTo in #1253

    • b2aa843 (layout) Enable serde for Margin, Position, Rect, Size by @EdJoPaTo in #1255

    • 36d49e5 (table) Select first, last, etc to table state by @robertpsoane in #1198

      Add select_previous, select_next, select_first & select_last to TableState

      Used equivalent API as in ListState

    • 3bb374d (terminal) Add Terminal::try_draw() method by @joshka in #1209

      This makes it easier to write fallible rendering methods that can use the ? operator

      terminal.try_draw(|frame| {
          some_method_that_can_fail()?;
          another_faillible_method()?;
          Ok(())
      })?;
      
    • 3725262 (text) Add Add and AddAssign implementations for Line, Span, and Text by @joshka in #1236

      This enables:

      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")]);
      
    • c34fb77 (text) Remove unnecessary lifetime from ToText trait by @joshka in #1234 [breaking]

      BREAKING CHANGE:The ToText trait no longer has a lifetime parameter. This change simplifies the trait and makes it easier implement.

    • c68ee6c (uncategorized) Add get/set_cursor_position() methods to Terminal and Backend by @EdJoPaTo in #1284 [breaking]

      The 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()?;
      
    • b70cd03 (uncategorized) Add ListState / TableState scroll_down_by() / scroll_up_by() methods by @josueBarretogit in #1267

      Implement new methods scroll_down_by(u16) and scroll_up_by(u16) for both Liststate and Tablestate.

      Closes:#1207

    Bug Fixes

    • 864cd9f (testbackend) Prevent area mismatch by @EdJoPaTo in #1252

      Removes the height and width fields from TestBackend, which can get out of sync with the Buffer, which currently clamps to 255,255.

      This changes the TestBackend serde representation. It should be possible to read older data, but data generated after this change can't be read by older versions.

    • 7e1bab0 (buffer) Dont render control characters by @EdJoPaTo in #1226

    • c08b522 (chart) Allow removing all the axis labels by @EdJoPaTo in #1282

      axis.labels(vec![]) removes all the labels correctly.

      This makes calling axis.labels with an empty Vec the equivalent of not calling axis.labels. It's likely that this is never used, but it prevents weird cases by removing the mix-up of Option::None and Vec::is_empty, and simplifies the implementation code.

    • 03f3124 (paragraph) Line_width, and line_count include block borders by @airblast-dev in #1235

      The line_width, and line_count methods for Paragraph would not take into account the Block if one was set. This will now correctly calculate the values including the Block's width/height.

      Fixes:#1233

    • 3ca920e (span) Prevent panic on rendering out of y bounds by @EdJoPaTo in #1257

    • 84cb164 (terminal) Make terminal module private by @joshka in #1260 [breaking]

      This is a simplification of the public API that is helpful for new users that are not familiar with how rust re-exports work, and helps avoid clashes with other modules in the backends that are named terminal.

      BREAKING CHANGE: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};
      

      Fixes:https://github.com/ratatui/ratatui/issues/1210

    • 29c8c84 (uncategorized) Ignore newlines in Span's Display impl by @SUPERCILEX in #1270

    • cd93547 (uncategorized) Remove unnecessary synchronization in layout cache by @SUPERCILEX in #1245

      Layout::init_cache no longer returns bool and takes a NonZeroUsize instead of usize

      The cache is a thread-local, so doesn't make much sense to require synchronized initialization.

    • b344f95 (uncategorized) Only apply style to first line when rendering a Line by @joshka in #1247

      A Line widget should only apply its style to the first line when rendering and not the entire area. This is because the Line widget should only render a single line of text. This commit fixes the issue by clamping the area to a single line before rendering the text.

    • 7ddfbc0 (uncategorized) Unnecessary allocations when creating Lines by @SUPERCILEX in #1237

    • 84f3341 (uncategorized) Clippy lints from rust 1.80.0 by @joshka in #1238

    Refactor

    • bb68bc6 (backend) Return Size from Backend::size instead of Rect by @EdJoPaTo in #1254 [breaking]

      The Backend::size method returns a Size instead of a Rect. There is no need for the position here as it was always 0,0.

    • e81663b (list) Split up list.rs into smaller modules by @joshka in #1204

    • e707ff1 (uncategorized) Internally use Position struct by @EdJoPaTo in #1256

    • 32a0b26 (uncategorized) Simplify WordWrapper implementation by @tranzystorekk in #1193

    Documentation

    • 6ce447c (block) Add docs about style inheritance by @joshka in #1190

      Fixes:https://github.com/ratatui/ratatui/issues/1129

    • 55e0880 (block) Update block documentation by @leohscl in #1206

      Update block documentation with constructor methods and setter methods in the main doc comment Added an example for using it to surround widgets

      Fixes:https://github.com/ratatui/ratatui/issues/914

    • f2fa1ae (breaking-changes) Add missing code block by @orhun in #1291

    • f687af7 (breaking-changes) Mention removed lifetime of ToText trait by @orhun in #1292

    • d468463 (breaking-changes) Fix the PR link by @orhun in #1294

    • 1b9bdd4 (contributing) Fix minor issues by @EdJoPaTo in #1300

    • 5f7a7fb (examples) Update barcharts gifs by @joshka in #1306

    • fe4eeab (examples) Simplify the barchart example by @joshka in #1079

      The barchart example has been split into two examples: barchart and barchart-grouped. The barchart example now shows a simple barchart with random data, while the barchart-grouped example shows a grouped barchart with fake revenue data.

      This simplifies the examples a bit so they don't cover too much at once.

      • Simplify the rendering functions
      • Fix several clippy lints that were marked as allowed

    • 6e7b4e4 (examples) Add async example by @joshka in #1248

      This example demonstrates how to use Ratatui with widgets that fetch data asynchronously. It uses the octocrab crate to fetch a list of pull requests from the GitHub API. You will need an environment variable named GITHUB_TOKEN with a valid GitHub personal access token. The token does not need any special permissions.

    • 935a718 (examples) Add missing examples to README by @kibibyt3 in #1225

      Resolves:#1014

    • 50e5674 (examples) Fix: fix typos in tape files by @kibibyt3 in #1224

    • 810da72 (examples) Fix hyperlink example tape by @kibibyt3 in #1222

    • 5eeb1cc (github) Create CODE_OF_CONDUCT.md by @joshka in #1279

    • 7c0665c (layout) Fix typo in example by @EmiOnGit in #1217

    • 272d059 (paragraph) Update main docs by @joshka in #1202

    • bb71e5f (readme) Remove MSRV by @EdJoPaTo in #1266

      This notice was useful when the Cargo.toml had no standardized field for this. Now it's easier to look it up in the Cargo.toml and it's also a single point of truth. Updating the README was overlooked for quite some time so it's better to just omit it rather than having something wrong that will be forgotten again in the future.

    • 8857037 (terminal) Fix imports by @EdJoPaTo in #1263

    • 2fd5ae6 (widgets) Document stability of WidgetRef by @joshka in #1288

      Addresses some confusion about when to implement WidgetRef vs impl Widget for &W. Notes the stability rationale and links to an issue that helps explain the context of where we're at in working this out.

    • 716c931 (uncategorized) Document crossterm breaking change by @joshka in #1281

    • f775030 (uncategorized) Update main lib.rs / README examples by @joshka in #1280

    • 8433d09 (uncategorized) Update demo image by @joshka in #1276

      Follow up to https://github.com/ratatui/ratatui/pull/1203

    Performance

    • 663486f (list) Avoid extra allocations when rendering List by @airblast-dev in #1244

      When rendering a List, each ListItem would be cloned. Removing the clone, and replacing Widget::render with WidgetRef::render_ref saves us allocations caused by the clone of the Text<'_> stored inside of ListItem.

      Based on the results of running the "list" benchmark locally; Performance is improved by %1-3 for all render benchmarks for List.

    • 4753b72 (reflow) Eliminate most WordWrapper allocations by @SUPERCILEX in #1239

      On large paragraphs (~1MB), this saves hundreds of thousands of allocations.

      TL;DR:reuse as much memory as possible across next_line calls. Instead of allocating new buffers each time, allocate the buffers once and clear them before reuse.

    • be3eb75 (table) Avoid extra allocations when rendering Table by @airblast-dev in #1242

      When rendering a Table the Text stored inside of a Cell gets cloned before rendering. This removes the clone and uses WidgetRef instead, saving us from allocating a Vec<Line<'_>> inside Text. Also avoids an allocation when rendering the highlight symbol if it contains an owned value.

    • f04bf85 (uncategorized) Add buffer benchmarks by @joshka in #1303

    • e6d2e04 (uncategorized) Move benchmarks into a single benchmark harness by @joshka in #1302

      Consolidates the benchmarks into a single executable rather than having to create a new cargo.toml setting per and makes it easier to rearrange these when adding new benchmarks.

    Styling

    • a80a8a6 (format) Lint markdown by @joshka in #1131

      • chore: Fix line endings for changelog
      • chore: cleanup markdown lints
      • ci: add Markdown linter
      • build: add markdown lint to the makefile

    Testing

    • 32d0695 (buffer) Ensure emojis are rendered by @EdJoPaTo in #1258

    Miscellaneous Tasks

    • 82b70fd (ci) Integrate cargo-semver-checks by @orhun in #1166

      cargo-semver-checks: Lint your crate API changes for semver violations.

    • c245c13 (ci) Onboard bencher for tracking benchmarks by @orhun in #1174

      https://bencher.dev/console/projects/ratatui-org

      Closes:#1092

    • efef0d0 (ci) Change label from breaking change to Type: Breaking Change by @kdheepak in #1243

      This PR changes the label that is auto attached to a PR with a breaking change per the conventional commits specification.

    • 41a9100 (github) Use the GitHub organization team as codeowners by @EdJoPaTo in #1081

      Use GitHub organization team in CODEOWNERS and create MAINTAINERS.md

    • 3e7458f (github) Add forums and faqs to the issue template by @joshka in #1201

    • 45fcab7 (uncategorized) Add rect::rows benchmark by @joshka in #1301

    • edc2af9 (uncategorized) Replace big_text with hardcoded logo by @joshka in #1203

      big_text.rs was a copy of the code from tui-big-text and was getting gradually out of sync with the original crate. It was also rendering something a bit different than the Ratatui logo. This commit replaces the big_text.rs file with a much smaller string representation of the Ratatui logo.

    • c2d3850 (uncategorized) Use LF line endings for CHANGELOG.md instead of CRLF by @joshka in #1269

    • a9fe428 (uncategorized) Update cargo-deny config by @EdJoPaTo in #1265

      Update cargo-deny config (noticed in https://github.com/ratatui/ratatui/pull/1263#pullrequestreview-2215488414)

      See https://github.com/EmbarkStudios/cargo-deny/pull/611

    • ffc4300 (uncategorized) Remove executable flag for rs files by @EdJoPaTo in #1262

    • 7bab9f0 (uncategorized) Add more CompactString::const_new instead of new by @joshka in #1230

    • ccf83e6 (uncategorized) Update labels in issue templates by @joshka in #1212

    Build

    • 379dab9 (uncategorized) Cleanup dev dependencies by @EdJoPaTo in #1231

    Continuous Integration

    • 476ac87 (uncategorized) Split up lint job by @EdJoPaTo in #1264

      This helps with identifying what failed right from the title. Also steps after a failing one are now always executed.

      Also shortens the steps a bit by removing obvious names.

    New Contributors

    • @SUPERCILEX made their first contribution in #1239

    • @josueBarretogit made their first contribution in #1267

    • @airblast-dev made their first contribution in #1242

    • @kibibyt3 made their first contribution in #1225

    • @EmiOnGit made their first contribution in #1217

    • @leohscl made their first contribution in #1206

    • @robertpsoane made their first contribution in #1198

    Full Changelog: https://github.com/ratatui/ratatui/compare/v0.27.0...0.28.0

    Open source →
  27. 0.28.0-alpha.1 03 Aug 2024 pre-release

    Nothing published for this version

  28. 0.28.0-alpha.0 27 Jul 2024 pre-release

    Nothing published for this version

  29. 0.27.1-alpha.3 20 Jul 2024 pre-release

    Nothing published for this version

  30. 0.27.1-alpha.2 13 Jul 2024 pre-release

    Nothing published for this version

  31. 0.27.1-alpha.1 06 Jul 2024 pre-release

    Nothing published for this version

  32. 0.27.1-alpha.0 29 Jun 2024 pre-release

    Nothing published for this version

  33. 0.27.0 24 Jun 2024
    Release notes

    In this version, we have focused on enhancing usability and functionality with new features like background styles for LineGauge, palette colors, and various other improvements including improved performance. Also, we added brand new examples for tracing and creating hyperlinks!

    Release highlights: https://ratatui.rs/highlights/v027/

    ⚠️ List of breaking changes can be found here.

    Features

    • eef1afe (linegauge) Allow LineGauge background styles by @nowNick in #565

      This PR deprecates `gauge_style` in favor of `filled_style` and
      `unfilled_style` which can have its foreground and background styled.
      
      `cargo run --example=line_gauge --features=crossterm`
      

      https://github.com/ratatui/ratatui/assets/5149215/5fb2ce65-8607-478f-8be4-092e08612f5b

      Implements:https://github.com/ratatui/ratatui/issues/424

    • 1365620 (borders) Add FULL and EMPTY border sets by @joshka in #1182

      border::FULL uses a full block symbol, while border::EMPTY uses an empty space. 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.

    use ratatui::{symbols::border, widgets::Block};
    let block = Block::bordered().title("Title").border_set(border::FULL);
    let block = Block::bordered().title("Title").border_set(border::EMPTY);
    
    cargo run --example tracing
    RUST_LOG=trace cargo run --example=tracing
    cat tracing.log
    

    • 1520ed9 (layout) Impl Display for Position and Size by @joshka in #1162

    • 46977d8 (list) Add list navigation methods (first, last, previous, next) by @joshka in #1159 [breaking]

      Also cleans up the list example significantly (see also
      <https://github.com/ratatui/ratatui/issues/1157>)
      

      Fixes:https://github.com/ratatui/ratatui/pull/1159

      BREAKING CHANGE:The List widget now clamps the selected index to the bounds of the list when navigating with first, last, previous, and next, as well as when setting the index directly with select.

    • 10d7788 (style) Add conversions from the palette crate colors by @joshka in #1172

      This is behind the "palette" feature flag.
      
      ```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));
      ```
      
    • 7ef2dae (text) support conversion from Display to Span, Line and Text by @orhun in #1167

      Now you can create `Line` and `Text` from numbers like so:
      
      ```rust
      let line = 42.to_line();
      let text = 666.to_text();
      ```
      
    • 74a32af (uncategorized) Re-export backends from the ratatui crate by @joshka in #1151

      `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::`.
      
    • 3594180 (uncategorized) Make Stylize's .bg(color) generic by @kdheepak in #1103 [breaking]

    • 0b5fd6b (uncategorized) Add writer() and writer_mut() to termion and crossterm backends by @enricozb in #991

      It is sometimes useful to obtain access to the writer if we want to see
      what has been written so far. For example, when using &mut [u8] as a
      writer.
      

    Bug Fixes

    • efa965e (line) Remove newlines when converting strings to Lines by @joshka in #1191

      Line::from("a\nb") now returns a line with two Spans instead of 1

      Fixes:https://github.com/ratatui/ratatui/issues/1111

    • d370aa7 (span) Ensure that zero-width characters are rendered correctly by @joshka in #1165

    • 127d706 (table) Ensure render offset without selection properly by @joshka in #1187

      Fixes:https://github.com/ratatui/ratatui/issues/1179

    • 4bfdc15 (uncategorized) Render of &str and String doesn't respect area.width by @thscharler in #1177

    • e6871b9 (uncategorized) Avoid unicode-width breaking change in tests by @joshka in #1171

      unicode-width 0.1.13 changed the width of \u{1} from 0 to 1.
      Our tests assumed that \u{1} had a width of 0, so this change replaces
      the \u{1} character with \u{200B} (zero width space) in the tests.
      
      Upstream issue (closed as won't fix):
      https://github.com/unicode-rs/unicode-width/issues/55
      
    • 7f3efb0 (uncategorized) Pin unicode-width crate to 0.1.13 by @joshka in #1170

      semver breaking change in 0.1.13
      <https://github.com/unicode-rs/unicode-width/issues/55>
      
      <!-- Please read CONTRIBUTING.md before submitting any pull request. -->
      
    • 42cda6d (uncategorized) Prevent panic from string_slice by @EdJoPaTo in #1140

      https://rust-lang.github.io/rust-clippy/master/index.html#string_slice

    Refactor

    • 73fd367 (block) Group builder pattern methods by @EdJoPaTo in #1134

    • 257db62 (cell) Must_use and simplify style() by @EdJoPaTo in #1124

      <!-- Please read CONTRIBUTING.md before submitting any pull request. -->
      
    • bf20369 (cell) Reset instead of applying default by @EdJoPaTo in #1127

      Using reset is clearer to me what actually happens. On the other case a
      struct is created to override the old one completely which basically
      does the same in a less clear way.
      
    • 7d175f8 (lint) Fix new lint warnings by @EdJoPaTo in #1178

    • cf67ed9 (lint) Use clippy::or_fun_call by @EdJoPaTo in #1138

      https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call

    • 4770e71 (list) Remove deprecated start_corner and Corner by @Valentin271 in #759 [breaking]

      List::start_corner was deprecated in v0.25. Use List::direction and ListDirection instead.

    - 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);
    
    - list.start_corner(Corner::BottomLeft);
    // becomes
    + list.direction(ListDirection::BottomToTop);
    

    layout::Corner is removed entirely.

    • 4f77910 (padding) Add Padding::ZERO as a constant by @EdJoPaTo in #1133

      Deprecate Padding::zero()
      
    • 8061813 (uncategorized) Expand glob imports by @joshka in #1152

      Consensus is that explicit imports make it easier to understand the
      example code. This commit removes the prelude import from all examples
      and replaces it with the necessary imports, and expands other glob
      imports (widget::*, Constraint::*, KeyCode::*, etc.) everywhere else.
      Prelude glob imports not in examples are not covered by this PR.
      
      See https://github.com/ratatui/ratatui/issues/1150 for more details.
      
    • d929971 (uncategorized) Dont manually impl Default for defaults by @EdJoPaTo in #1142

      Replace `impl Default` by `#[derive(Default)]` when its implementation
      equals.
      
    • 8a60a56 (uncategorized) Needless_pass_by_ref_mut by @EdJoPaTo in #1137

      https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut

    • 1de9a82 (uncategorized) Simplify if let by @EdJoPaTo in #1135

      While looking through lints
      [`clippy::option_if_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else)
      found these. Other findings are more complex so I skipped them.
      

    Documentation

    • 1908b06 (borders) Add missing closing code blocks by @orhun in #1195

    • 38bb196 (breaking-changes) Mention LineGauge::gauge_style by @orhun in #1194

      see #565

    • 07efde5 (examples) Add hyperlink example by @joshka in #1063

    • 7fdccaf (examples) Add vhs tapes for constraint-explorer and minimal examples by @joshka in #1164

    • 4f307e6 (examples) Simplify paragraph example by @joshka in #1169

      Related:https://github.com/ratatui/ratatui/issues/1157

    • f429f68 (examples) Remove lifetimes from the List example by @matta in #1132

      Simplify the List example by removing lifetimes not strictly necessary
      to demonstrate how Ratatui lists work. Instead, the sample strings are
      copied into each `TodoItem`. To further simplify, I changed the code to
      use a new TodoItem::new function, rather than an implementation of the
      `From` trait.
      
    • 308c1df (readme) Add links to forum by @joshka in #1188

    • 2f8a936 (uncategorized) Fix links on docs.rs by @EdJoPaTo in #1144

      This also results in a more readable Cargo.toml as the locations of the
      things are more obvious now.
      
      Includes rewording of the underline-color feature.
      
      Logs of the errors: https://docs.rs/crate/ratatui/0.26.3/builds/1224962
      Also see #989
      

    Performance

    • 4ce67fc (buffer) Filled moves the cell to be filled by @EdJoPaTo in #1148 [breaking]

    • 8b447ec (rect) Rect::inner takes Margin directly instead of reference by @EdJoPaTo in #1008 [breaking]

      BREAKING CHANGE:Margin needs to be passed without reference now.

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

    Styling

    • df4b706 (uncategorized) Enable more rustfmt settings by @EdJoPaTo in #1125

    Testing

    • d6587bc (style) Use rstest by @EdJoPaTo in #1136

      <!-- Please read CONTRIBUTING.md before submitting any pull request. -->
      

    Miscellaneous Tasks

    • 7b45f74 (prelude) Add / remove items by @joshka in #1149 [breaking]

      his PR removes the items from the prelude that don't form a coherent
      common vocabulary and adds the missing items that do.
      
      Based on a comment at
      <https://www.reddit.com/r/rust/comments/1cle18j/comment/l2uuuh7/>
      

      BREAKING CHANGE: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.

    • cd64367 (symbols) Add tests for line symbols by @joshka in #1186

    • 8cfc316 (uncategorized) Alphabetize examples in Cargo.toml by @joshka in #1145

    Build

    • 70df102 (bench) Improve benchmark consistency by @EdJoPaTo in #1126

      Codegen units are optimized on their own. Per default bench / release
      have 16 codegen units. What ends up in a codeget unit is rather random
      and can influence a benchmark result as a code change can move stuff
      into a different codegen unit → prevent / allow LLVM optimizations
      unrelated to the actual change.
      
      More details: https://doc.rust-lang.org/cargo/reference/profiles.html
      

    New Contributors

    • @thscharler made their first contribution in #1177
    • @matta made their first contribution in #1132
    • @nowNick made their first contribution in #565
    • @enricozb made their first contribution in #991

    Full Changelog: https://github.com/ratatui/ratatui/compare/v0.26.3...v0.27.0

    Open source →
  34. 0.27.0-alpha.8 22 Jun 2024 pre-release

    Nothing published for this version

  35. 0.27.0-alpha.7 17 Jun 2024 pre-release

    Nothing published for this version

  36. 0.27.0-alpha.5 13 Apr 2024 pre-release

    Nothing published for this version

  37. 0.27.0-alpha.4 06 Apr 2024 pre-release

    Nothing published for this version

  38. 0.27.0-alpha.3 30 Mar 2024 pre-release

    Nothing published for this version

  39. 0.27.0-alpha.2 23 Mar 2024 pre-release

    Nothing published for this version

  40. 0.27.0-alpha.1 16 Mar 2024 pre-release

    Nothing published for this version

  41. 0.27.0-alpha.0 09 Mar 2024 pre-release

    Nothing published for this version

  42. 0.26.3 20 May 2024
    Release notes

    We are happy to announce a brand new Ratatui Forum 🐭 for Rust & TUI enthusiasts.

    This is a patch release that fixes the unicode truncation bug, adds performance and quality of life improvements.

    Release highlights: https://ratatui.rs/highlights/v0263/

    Features

    • 97ee102 (buffer) Track_caller for index_of by @EdJoPaTo in #1046 **

      The caller put in the wrong x/y -> the caller is the cause.
      
    • bf09234 (table) Make TableState::new const by @EdJoPaTo in #1040

    • eb281df (uncategorized) Use inner Display implementation by @EdJoPaTo in #1097

    • ec763af (uncategorized) Make Stylize's .bg(color) generic by @kdheepak in #1099

      This PR makes `.bg(color)` generic accepting anything that can be
      converted into `Color`; similar to the `.fg(color)` method on the same
      trait
      
    • 4d1784f (uncategorized) Re-export ParseColorError as style::ParseColorError by @joshka in #1086

      Fixes:https://github.com/ratatui/ratatui/issues/1085

    Bug Fixes

    • 366cbae (buffer) Fix Debug panic and fix formatting of overridden parts by @EdJoPaTo in #1098

      Fix panic in `Debug for Buffer` when `width == 0`.
      Also corrects the output when symbols are overridden.
      
    • 4392759 (examples) Changed user_input example to work with multi-byte unicode chars by @OkieOth in #1069

      This is the proposed solution for issue #1068. It solves the bug in the
      user_input example with multi-byte UTF-8 characters as input.
      

      Fixes:#1068


    • 20fc0dd (examples) Fix key handling in constraints by @psobolik in #1066

      Add check for `KeyEventKind::Press` to constraints example's event
      handler to eliminate double keys
      on Windows.
      

      Fixes:#1062


    • f4637d4 (reflow) Allow wrapping at zero width whitespace by @kxxt in #1074

    • 699c2d7 (uncategorized) Unicode truncation bug by @joshka in #1089

      - Rewrote the line / span rendering code to take into account how
      multi-byte / wide emoji characters are truncated when rendering into
      areas that cannot accommodate them in the available space
      - Added comprehensive coverage over the edge cases
      - Adds a benchmark to ensure perf
      

      Fixes:https://github.com/ratatui/ratatui/issues/1032

    • b30411d (uncategorized) Termwiz underline color test by @joshka in #1094

      Fixes code that doesn't compile in the termwiz tests when
      underline-color feature is enabled.
      
    • 5f1e119 (uncategorized) Correct feature flag typo for termwiz by @joshka in #1088

      underline-color was incorrectly spelt as underline_color
      
    • 0a16496 (uncategorized) Use to_string to serialize Color by @SleepySwords in #934

      Since deserialize now uses `FromStr` to deserialize color, serializing
      `Color` RGB values, as well as index values, would produce an output
      that would no longer be able to be deserialized without causing an
      error.
      

      Color::Rgb will now be serialized as the hex representation of their value. For example, with serde_json, Color::Rgb(255, 0, 255) would be serialized as "#FF00FF" rather than {"Rgb": [255, 0, 255]}.

      Color::Indexed will now be serialized as just the string of the index. For example, with serde_json, Color::Indexed(10) would be serialized as "10" rather than {"Indexed": 10}.

    Other color variants remain the same.

    Refactor

    • 2cfe82a (buffer) Deprecate assert_buffer_eq! in favor of assert_eq! by @EdJoPaTo in #1007

      - Simplify `assert_buffer_eq!` logic.
      - Deprecate `assert_buffer_eq!`.
      - Introduce `TestBackend::assert_buffer_lines`.
      
      Also simplify many tests involving buffer comparisons.
      
      For the deprecation, just use `assert_eq` instead of `assert_buffer_eq`:
      
      ```diff
      -assert_buffer_eq!(actual, expected);
      +assert_eq!(actual, expected);
      ```
      
      ---
      
      I noticed `assert_buffer_eq!` creating no test coverage reports and
      looked into this macro. First I simplified it. Then I noticed a bunch of
      `assert_eq!(buffer, …)` and other indirect usages of this macro (like
      `TestBackend::assert_buffer`).
      
      The good thing here is that it's mainly used in tests so not many
      changes to the library code.
      
    • baedc39 (buffer) Simplify set_stringn logic by @EdJoPaTo in #1083

    • 9bd89c2 (clippy) Enable breaking lint checks by @EdJoPaTo in #988

      We need to make sure to not change existing methods without a notice.
      But at the same time this also finds public additions with mistakes
      before they are even released which is what I would like to have.
      
      This renames a method and deprecated the old name hinting to a new name.
      Should this be mentioned somewhere, so it's added to the release notes?
      It's not breaking because the old method is still there.
      
    • bef5bcf (example) Remove pointless new method by @EdJoPaTo in #1038

      Use `App::default()` directly.
      
    • f3172c5 (gauge) Fix internal typo by @EdJoPaTo in #1048

    Documentation

    • da1ade7 (github) Update code owners about past maintainers by @orhun in #1073

      As per suggestion in
      https://github.com/ratatui/ratatui/pull/1067#issuecomment-2079766990
      
      It's good for historical purposes!
      
    • 3687f78 (github) Update code owners by @orhun in #1067

      Removes the team members that are not able to review PRs recently (with
      their approval ofc)
      
    • 839cca2 (table) Fix typo in docs for highlight_symbol by @kdheepak in #1108

    • f945a0b (test) Fix typo in TestBackend documentation by @orhun in #1107

    • 828d17a (uncategorized) Add minimal example by @joshka in #1114

    • e95230b (uncategorized) Add note about scrollbar state content length by @Utagai in #1077

    Performance

    • 366c2a0 (block) Use Block::bordered by @EdJoPaTo in #1041

      Block::bordered() is shorter than

      Block::new().borders(Borders::ALL), requires one less import (Borders) and in case Block::default() was used before can even be const.

    • 2e71c18 (buffer) Simplify Buffer::filled with macro by @EdJoPaTo in #1036

      The `vec![]` macro is highly optimized by the Rust team and shorter.
      Don't do it manually.
      
      This change is mainly cleaner code. The only production code that uses
      this is `Terminal::with_options` and `Terminal::insert_before` so it's
      not performance relevant on every render.
      
    • 81b9633 (calendar) Use const fn by @EdJoPaTo in #1039

      Also, do the comparison without `as u8`. Stays the same at runtime and
      is cleaner code.
      
    • c442dfd (canvas) Change map data to const instead of static by @EdJoPaTo in #1037

    • 1706b0a (crossterm) Speed up combined fg and bg color changes by up to 20% by @joshka in #1072

    • 1a4bb1c (layout) Avoid allocating memory when using split ergonomic utils by @tranzystorekk in #1105

      Don't create intermediate vec in `Layout::areas` and
      `Layout::spacers` when there's no need for one.
      

    Styling

    • aa4260f (uncategorized) Use std::fmt instead of importing Debug and Display by @joshka in #1087

      This is a small universal style change to avoid making this change a
      part of other PRs.
      
      [rationale](https://github.com/ratatui/ratatui/pull/1083#discussion_r1588466060)
      

    Testing

    • 3cc29bd (block) Use rstest to simplify test cases by @EdJoPaTo in #1095

    Miscellaneous Tasks

    • 5fbb77a (readme) Use terminal theme for badges by @TadoTheMiner in #1026

      The badges in the readme were all the default theme. Giving them
      prettier colors that match the terminal gif is better. I've used the
      colors from the VHS repo.
      
    • bef2bc1 (cargo) Add homepage to Cargo.toml by @joshka in #1080

    • 76e5fe5 (uncategorized) Revert "Make Stylize's .bg(color) generic" by @kdheepak in #1102

      This reverts commit ec763af8512df731799c8f30c38c37252068a4c4 from #1099
      
    • 64eb391 (uncategorized) Fixup cargo lint for windows targets by @joshka in #1071

      Crossterm brings in multiple versions of the same dep
      
    • 326a461 (uncategorized) Add package categories field by @mcskware in #1035

      Add the package categories field in Cargo.toml, with value
      `["command-line-interface"]`. This fixes the (currently non-default)
      clippy cargo group lint
      [`clippy::cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#/cargo_common_metadata).
      
      As per discussion in [Cargo package categories
      suggestions](https://github.com/ratatui/ratatui/discussions/1034),
      this lint is not suggested to be run by default in CI, but rather as an
      occasional one-off as part of the larger
      [`clippy::cargo`](https://doc.rust-lang.org/stable/clippy/lints.html#cargo)
      lint group.
      

    Build

    • 4955380 (uncategorized) Remove pre-push hooks by @joshka in #1115

    • 28e81c0 (uncategorized) Add underline-color to all features flag in makefile by @joshka in #1100

    • c75aa19 (uncategorized) Add clippy::cargo lint by @joshka in #1053

      Followup to https://github.com/ratatui/ratatui/pull/1035 and
      https://github.com/ratatui/ratatui/discussions/1034
      
      It's reasonable to enable this and deal with breakage by fixing any
      specific issues that arise.
      

    New Contributors

    • @Utagai made their first contribution in #1077
    • @kxxt made their first contribution in #1074
    • @OkieOth made their first contribution in #1069
    • @psobolik made their first contribution in #1066
    • @SleepySwords made their first contribution in #934
    • @mcskware made their first contribution in #1035

    Full Changelog: https://github.com/ratatui/ratatui/compare/v0.26.2...v0.26.3

    Open source →
  43. 0.26.3-alpha.4 18 May 2024 pre-release

    Nothing published for this version

  44. 0.26.3-alpha.3 11 May 2024 pre-release

    Nothing published for this version

  45. 0.26.3-alpha.2 04 May 2024 pre-release

    Nothing published for this version

  46. 0.26.3-alpha.1 27 Apr 2024 pre-release

    Nothing published for this version

  47. 0.26.3-alpha.0 20 Apr 2024 pre-release

    Nothing published for this version

  48. 0.26.2 15 Apr 2024
    Release notes

    This is a patch release that fixes bugs and adds enhancements, including new iterator constructors, List scroll padding, and various rendering improvements. ✨

    Release highlights: https://ratatui.rs/highlights/v0262/

    Features

    • 11b452d (layout) Mark various functions as const by @EdJoPaTo in #951

    • 1cff511 (line) Impl Styled for Line by @joshka in #968

      This adds `FromIterator` impls for `Line` and `Text` that allow creating
      `Line` and `Text` instances from iterators of `Span` and `Line`
      instances, respectively.
      
      ```rust
      let line = Line::from_iter(vec!["Hello".blue(), " world!".green()]);
      let line: Line = iter::once("Hello".blue())
          .chain(iter::once(" world!".green()))
          .collect();
      let text = Text::from_iter(vec!["The first line", "The second line"]);
      let text: Text = iter::once("The first line")
          .chain(iter::once("The second line"))
          .collect();
      ```
      
    • 654949b (list) Add Scroll Padding to Lists by @CameronBarnes in #958

      Introduces scroll padding, which allows the api user to request that a certain number of ListItems be kept visible above and below the currently selected item while scrolling.
      
      ```rust
      let list = List::new(items).scroll_padding(1);
      ```
      

      Fixes:https://github.com/ratatui/ratatui/pull/955

    • 26af650 (text) Add push methods for text and line by @joshka in #998

      Adds the following methods to the `Text` and `Line` structs:
      - Text::push_line
      - Text::push_span
      - Line::push_span
      
      This allows for adding lines and spans to a text object without having
      to call methods on the fields directly, which is useful for incremental
      construction of text objects.
      
    • b5bdde0 (text) Add FromIterator impls for Line and Text by @joshka in #967

      This adds `FromIterator` impls for `Line` and `Text` that allow creating
      `Line` and `Text` instances from iterators of `Span` and `Line`
      instances, respectively.
      
      ```rust
      let line = Line::from_iter(vec!["Hello".blue(), " world!".green()]);
      let line: Line = iter::once("Hello".blue())
          .chain(iter::once(" world!".green()))
          .collect();
      let text = Text::from_iter(vec!["The first line", "The second line"]);
      let text: Text = iter::once("The first line")
          .chain(iter::once("The second line"))
          .collect();
      ```
      
    • 12f67e8 (uncategorized) Impl Widget for &str and String by @kdheepak in #952

      Currently, `f.render_widget("hello world".bold(), area)` works but
      `f.render_widget("hello world", area)` doesn't. This PR changes that my
      implementing `Widget` for `&str` and `String`. This makes it easier to
      render strings with no styles as widgets.
      
      Example usage:
      
      ```rust
      terminal.draw(|f| f.render_widget("Hello World!", f.size()))?;
      ```
      
      ---------
      

    Bug Fixes

    • 0207160 (line) Line truncation respects alignment by @TadoTheMiner in #987

      When rendering a `Line`, the line will be truncated:
      - on the right for left aligned lines
      - on the left for right aligned lines
      - on bot sides for centered lines
      
      E.g. "Hello World" will be rendered as "Hello", "World", "lo wo" for
      left, right, centered lines respectively.
      

      Fixes:https://github.com/ratatui/ratatui/issues/932

    • c56f49b (list) Saturating_sub to fix highlight_symbol overflow by @mrjackwills in #949

      An overflow (pedantically an underflow) can occur if the
      highlight_symbol is a multi-byte char, and area is reduced to a size
      less than that char length.
      
    • b7778e5 (paragraph) Unit test typo by @joshka in #1022

    • 943c043 (scrollbar) Dont render on 0 length track by @EdJoPaTo in #964

      Fixes a panic when `track_length - 1` is used. (clamp panics on `-1.0`
      being smaller than `0.0`)
      
    • 742a5ea (text) Fix panic when rendering out of bounds by @joshka in #997

      Previously it was possible to cause a panic when rendering to an area
      outside of the buffer bounds. Instead this now correctly renders nothing
      to the buffer.
      
    • f6c4e44 (uncategorized) Ensure that paragraph correctly renders styled text by @joshka in #992

      Paragraph was ignoring the new `Text::style` field added in 0.26.0
      

      Fixes:https://github.com/ratatui/ratatui/issues/990

    • 35e971f (uncategorized) Scrollbar thumb not visible on long lists by @ThomasMiz in #959

      When displaying somewhat-long lists, the `Scrollbar` widget sometimes did not display a thumb character, and only the track will be visible.
      

    Refactor

    • 6fd5f63 (lint) Prefer idiomatic for loops by @EdJoPaTo

    • 37b957c (lints) Add lints to scrollbar by @EdJoPaTo

    • c12bcfe (non-src) Apply pedantic lints by @EdJoPaTo in #976

      Fixes many not yet enabled lints (mostly pedantic) on everything that is
      not the lib (examples, benches, tests). Therefore, this is not containing
      anything that can be a breaking change.
      
      Lints are not enabled as that should be the job of #974. I created this
      as a separate PR as it's mostly independent and would only clutter up the
      diff of #974 even more.
      
      Also see
      https://github.com/ratatui/ratatui/pull/974#discussion_r1506458743
      
      ---------
      
    • 8719608 (span) Rename to_aligned_line into into_aligned_line by @EdJoPaTo in #993

      With the Rust method naming conventions these methods are into methods
      consuming the Span. Therefore, it's more consistent to use `into_`
      instead of `to_`.
      
      ```rust
      Span::to_centered_line
      Span::to_left_aligned_line
      Span::to_right_aligned_line
      ```
      
      Are marked deprecated and replaced with the following
      
      ```rust
      Span::into_centered_line
      Span::into_left_aligned_line
      Span::into_right_aligned_line
      ```
      
    • b831c56 (widget-ref) Clippy::needless_pass_by_value by @EdJoPaTo

    • 359204c (uncategorized) Simplify to io::Result by @EdJoPaTo in #1016

      Simplifies the code, logic stays exactly the same.
      
    • 8e68db9 (uncategorized) Remove pointless default on internal structs by @EdJoPaTo in #980

      See #978

    Also remove other derives. They are unused and just slow down compilation.

    • 3be189e (uncategorized) Clippy::thread_local_initializer_can_be_made_const by @EdJoPaTo

      enabled by default on nightly
      
    • 5c4efac (uncategorized) Clippy::map_err_ignore by @EdJoPaTo

    • bbb6d65 (uncategorized) Clippy::else_if_without_else by @EdJoPaTo

    • fdb14dc (uncategorized) Clippy::redundant_type_annotations by @EdJoPaTo

    • 9b3b23a (uncategorized) Remove literal suffix by @EdJoPaTo

      it's not needed and can just be assumed
      

      related:clippy::(un)separated_literal_suffix

    • 58b6e0b (uncategorized) Clippy::should_panic_without_expect by @EdJoPaTo

    • c870a41 (uncategorized) Clippy::many_single_char_names by @EdJoPaTo

    • a6036ad (uncategorized) Clippy::similar_names by @EdJoPaTo

    • 060d26b (uncategorized) Clippy::match_same_arms by @EdJoPaTo

    • fcbea9e (uncategorized) Clippy::uninlined_format_args by @EdJoPaTo

    • 14b24e7 (uncategorized) Clippy::if_not_else by @EdJoPaTo

    • 5ed1f43 (uncategorized) Clippy::redundant_closure_for_method_calls by @EdJoPaTo

    • c8c7924 (uncategorized) Clippy::too_many_lines by @EdJoPaTo

    • e3afe7c (uncategorized) Clippy::unreadable_literal by @EdJoPaTo

    • a1f54de (uncategorized) Clippy::bool_to_int_with_if by @EdJoPaTo

    • b8ea190 (uncategorized) Clippy::cast_lossless by @EdJoPaTo

    • 0de5238 (uncategorized) Dead_code by @EdJoPaTo

      enabled by default, only detected by nightly yet
      
    • df5dddf (uncategorized) Unused_imports by @EdJoPaTo

      enabled by default, only detected on nightly yet
      
    • f1398ae (uncategorized) Clippy::useless_vec by @EdJoPaTo

      Lint enabled by default but only nightly finds this yet
      
    • 525848f (uncategorized) Manually apply clippy::use_self for impl with lifetimes by @EdJoPaTo

    • 660c718 (uncategorized) Clippy::empty_line_after_doc_comments by @EdJoPaTo

    • ab951fa (uncategorized) Clippy::return_self_not_must_use by @EdJoPaTo

    • 3cd4369 (uncategorized) Clippy::doc_markdown by @EdJoPaTo

    • 9bc014d (uncategorized) Clippy::items_after_statements by @EdJoPaTo

    • 36a0cd5 (uncategorized) Clippy::deref_by_slicing by @EdJoPaTo

    • f7f6692 (uncategorized) Clippy::equatable_if_let by @EdJoPaTo

    • 01418eb (uncategorized) Clippy::default_trait_access by @EdJoPaTo

    • 8536760 (uncategorized) Clippy::inefficient_to_string by @EdJoPaTo

    • a558b19 (uncategorized) Clippy::implicit_clone by @EdJoPaTo

    • 5b00e3a (uncategorized) Clippy::use_self by @EdJoPaTo

    • 27680c0 (uncategorized) Clippy::semicolon_if_nothing_returned by @EdJoPaTo

    Documentation

    • 14461c3 (breaking-changes) Typos and markdownlint by @EdJoPaTo in #1009

    • d0067c8 (license) Update copyright years by @orhun in #962

    • 88bfb5a (text) Update Text and Line docs by @joshka in #969

    • 3b002fd (uncategorized) Update incompatible code warning in examples readme by @joshka in #1013

    Performance

    • e02f476 (borders) Allow border!() in const by @EdJoPaTo in #977

      This allows more compiler optimizations when the macro is used.
      
    • 541f0f9 (cell) Use const CompactString::new_inline by @EdJoPaTo in #979

      Some minor find when messing around trying to `const` all the things.
      
      While `reset()` and `default()` can not be `const` it's still a benefit
      when their contents are.
      
    • 65e7923 (scrollbar) Const creation by @EdJoPaTo in #963

      A bunch of `const fn` allow for more performance and `Default` now uses the `const` new implementations.
      
    • 8195f52 (uncategorized) Clippy::needless_pass_by_value by @EdJoPaTo

    • 183c07e (uncategorized) Clippy::trivially_copy_pass_by_ref by @EdJoPaTo

    • a13867f (uncategorized) Clippy::cloned_instead_of_copied by @EdJoPaTo

    • 3834374 (uncategorized) Clippy::missing_const_for_fn by @EdJoPaTo

    Miscellaneous Tasks

    • 125ee92 (docs) Fix: fix typos in crate documentation by @orhun in #1002

    • 38c17e0 (editorconfig) Set and apply some defaults by @EdJoPaTo

    • 07da90a (funding) Add eth address for receiving funds from drips.network by @BenJam in #994

    • 078e97e (github) Add EdJoPaTo as a maintainer by @orhun in #986

    • b0314c5 (uncategorized) Remove conventional commit check for PR by @Valentin271 in #950

      This removes conventional commit check for PRs.
      
      Since we use the PR title and description this is useless. It fails a
      lot of time and we ignore it.
      
      IMPORTANT NOTE: This does **not** mean Ratatui abandons conventional
      commits. This only relates to commits in PRs.
      

    Build

    • 6e6ba27 (lint) Warn on pedantic and allow the rest by @EdJoPaTo

    • c4ce7e8 (uncategorized) Enable more satisfied lints by @EdJoPaTo

      These lints dont generate warnings and therefore dont need refactoring.
      I think they are useful in the future.
      
    • a4e84a6 (uncategorized) Increase msrv to 1.74.0 by @EdJoPaTo [breaking]

      configure lints in Cargo.toml requires 1.74.0
      

      BREAKING CHANGE:rust 1.74 is required now

    New Contributors

    • @TadoTheMiner made their first contribution in #987
    • @BenJam made their first contribution in #994
    • @CameronBarnes made their first contribution in #958
    • @ThomasMiz made their first contribution in #959

    Full Changelog: https://github.com/ratatui/ratatui/compare/v0.26.1...0.26.2

    Open source →
  49. 0.26.2-alpha.2 02 Mar 2024 pre-release

    Nothing published for this version

  50. 0.26.2-alpha.1 24 Feb 2024 pre-release

    Nothing published for this version

  51. 0.26.2-alpha.0 17 Feb 2024 pre-release

    Nothing published for this version

  52. 0.26.1 12 Feb 2024
    Release notes

    This is a patch release that fixes bugs and adds enhancements, including new iterators, title options for blocks, and various rendering improvements. ✨

    Features

    • 74a0511 (rect) Add Rect::positions iterator (#928)

      Useful for performing some action on all the cells in a particular area.
      E.g.,
      
      ```rust
      fn render(area: Rect, buf: &mut Buffer) {
         for position in area.positions() {
              buf.get_mut(position.x, position.y).set_symbol("x");
          }
      }
      ```
      
    • 9182f47 (uncategorized) Add Block::title_top and Block::title_top_bottom (#940)

      This adds the ability to add titles to the top and bottom of a block
      without having to use the `Title` struct (which will be removed in a
      future release - likely v0.28.0).
      
      Fixes a subtle bug if the title was created from a right aligned Line
      and was also right aligned. The title would be rendered one cell too far
      to the right.
      
      ```rust
      Block::bordered()
          .title_top(Line::raw("A").left_aligned())
          .title_top(Line::raw("B").centered())
          .title_top(Line::raw("C").right_aligned())
          .title_bottom(Line::raw("D").left_aligned())
          .title_bottom(Line::raw("E").centered())
          .title_bottom(Line::raw("F").right_aligned())
          .render(buffer.area, &mut buffer);
      // renders
      "┌A─────B─────C┐",
      "│             │",
      "└D─────E─────F┘",
      ```
      
      Addresses part of https://github.com/ratatui/ratatui/issues/738
      

    Bug Fixes

    • 2202059 (block) Fix crash on empty right aligned title (#933)

      - Simplified implementation of the rendering for block.
      - Introduces a subtle rendering change where centered titles that are
        odd in length will now be rendered one character to the left compared
        to before. This aligns with other places that we render centered text
        and is a more consistent behavior. See
        https://github.com/ratatui/ratatui/pull/807#discussion_r1455645954
        for another example of this.
      

      Fixes: https://github.com/ratatui/ratatui/pull/929

    • 14c67fb (list) Highlight symbol when using a multi-bytes char (#924)

      ratatui v0.26.0 brought a regression in the List widget, in which the
      highlight symbol width was incorrectly calculated - specifically when
      the highlight symbol was a multi-char character, e.g. `▶`.
      
    • 0dcdbea (paragraph) Render Line::styled correctly inside a paragraph (#930)

      Renders the styled graphemes of the line instead of the contained spans.
      
    • fae5862 (uncategorized) Ensure that buffer::set_line sets the line style (#926)

      Fixes a regression in 0.26 where buffer::set_line was no longer setting
      the style. This was due to the new style field on Line instead of being
      stored only in the spans.
      
      Also adds a configuration for just running unit tests to bacon.toml.
      
    • fbb5dfa (uncategorized) Scrollbar rendering when no track symbols are provided (#911)

    Refactor

    • c3fb258 (rect) Move iters to module and add docs (#927)

    • e51ca6e (uncategorized) Finish tidying up table (#942)

    • 91040c0 (uncategorized) Rearrange block structure (#939)

    Documentation

    • 61a8278 (canvas) Add documentation to canvas module (#913)

      Document the whole `canvas` module. With this, the whole `widgets`
      module is documented.
      
    • d2d91f7 (changelog) Add sponsors section (#908)

    • 410d08b (uncategorized) Add link to FOSDEM 2024 talk (#944)

    • 1f208ff (uncategorized) Add GitHub Sponsors badge (#943)

    Performance

    • 0963463 (uncategorized) Use drain instead of remove in chart examples (#922)

    Miscellaneous Tasks

    • a4892ad (uncategorized) Fix typo in docsrs example (#946)

    • 18870ce (uncategorized) Fix the method name for setting the Line style (#947)

    • 8fb4630 (uncategorized) Remove github action bot that makes comments nudging commit signing (#937)

      We can consider reverting this commit once this PR is merged:
      https://github.com/1Password/check-signed-commits-action/pull/9
      

    Contributors

    Thank you so much to everyone that contributed to this release!

    Here is the list of contributors who have contributed to ratatui for the first time!

    • @mo8it
    • @m4rch3n1ng
    Open source →
  53. 0.26.1-alpha.1 10 Feb 2024 pre-release

    Nothing published for this version

  54. 0.26.1-alpha.0 03 Feb 2024 pre-release

    Nothing published for this version

  55. 0.26.0 02 Feb 2024
    Release notes

    We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 🐭

    In this version, we have primarily focused on simplifications and quality-of-life improvements for providing a more intuitive and user-friendly experience while building TUIs.

    Release highlights: https://ratatui.rs/highlights/v026/

    ⚠️ List of breaking changes can be found here.

    💖 Consider sponsoring us at https://github.com/sponsors/ratatui!

    Features

    • 79ceb9f (line) Add alignment convenience functions (#856)

      This adds convenience functions `left_aligned()`, `centered()` and
      `right_aligned()` plus unit tests. Updated example code.
      
    • 0df9354 (padding) Add new constructors for padding (#828)

      Adds `proportional`, `symmetric`, `left`, `right`, `top`, and `bottom`
      constructors for Padding struct.
      
      Proportional is
      ```
      /// **NOTE**: Terminal cells are often taller than they are wide, so to make horizontal and vertical
      /// padding seem equal, doubling the horizontal padding is usually pretty good.
      ```
      

      Fixes:https://github.com/ratatui/ratatui/issues/798

    • d726e92 (paragraph) Add alignment convenience functions (#866)

      Added convenience functions left_aligned(), centered() and
      right_aligned() plus unit tests. Updated example code.
      
    • c1ed5c3 (span) Add alignment functions (#873)

      Implemented functions that convert Span into a
      left-/center-/right-aligned Line. Implemented unit tests.
      

      Closes #853

    • b80264d (text) Add alignment convenience functions (#862)

      Adds convenience functions `left_aligned()`, `centered()` and
      `right_aligned()` plus unit tests.
      
    • 23f6938 (block) Add Block::bordered (#736)

      This avoid creating a block with no borders and then settings Borders::ALL. i.e.
      
      ```diff
      - Block::default().borders(Borders::ALL);
      + Block::bordered();
      ```
      
    • ffd5fc7 (color) Add Color::from_u32 constructor (#785)

      Convert a u32 in the format 0x00RRGGBB to a Color.
      
      ```rust
      let white = Color::from_u32(0x00FFFFFF);
      let black = Color::from_u32(0x00000000);
      ```
      
    • 4f2db82 (color) Use the FromStr implementation for deserialization (#705)

      The deserialize implementation for Color used to support only the enum
      names (e.g. Color, LightRed, etc.) With this change, you can use any of
      the strings supported by the FromStr implementation (e.g. black,
      light-red, #00ff00, etc.)
      
    • 1cbe1f5 (constraints) Rename Constraint::Proportional to Constraint::Fill (#880)

      Constraint::Fill is a more intuitive name for the behavior, and it is shorter.

      Resolves #859

    • dfd6db9 (demo2) Add destroy mode to celebrate commit 1000! (#809)

      ```shell
      cargo run --example demo2 --features="crossterm widget-calendar"
      ```
      
      Press `d` to activate destroy mode and Enjoy!
      
      ![Destroy
      Demo2](https://github.com/ratatui/ratatui/blob/1d39444e3dea6f309cf9035be2417ac711c1abc9/examples/demo2-destroy.gif?raw=true)
      
      Vendors a copy of tui-big-text to allow us to use it in the demo.
      
    • 540fd2d (layout) Change Flex::default() (#881) [breaking]

      This PR makes a number of simplifications to the layout and constraint
      features that were added after v0.25.0.
      
      For users upgrading from v0.25.0, the net effect of this PR (along with
      the other PRs) is the following:
      
      - New `Flex` modes have been added.
        - `Flex::Start` (new default)
        - `Flex::Center`
        - `Flex::End`
        - `Flex::SpaceAround`
        - `Flex::SpaceBetween`
        - `Flex::Legacy` (old default)
      - `Min(v)` grows to allocate excess space in all `Flex` modes instead of
      shrinking (except in `Flex::Legacy` where it retains old behavior).
      - `Fill(1)` grows to allocate excess space, growing equally with
      `Min(v)`.
      
      ---
      
      The following contains a summary of the changes in this PR and the
      motivation behind them.
      
      **`Flex`**
      
      - Removes `Flex::Stretch`
      - Renames `Flex::StretchLast` to `Flex::Legacy`
      
      **`Constraint`**
      
      - Removes `Fixed`
      - Makes `Min(v)` grow as much as possible everywhere (except
      `Flex::Legacy` where it retains the old behavior)
      - Makes `Min(v)` grow equally as `Fill(1)` while respecting `Min` lower
      bounds. When `Fill` and `Min` are used together, they both fill excess
      space equally.
      
      Allowing `Min(v)` to grow still allows users to build the same layouts
      as before with `Flex::Start` with no breaking changes to the behavior.
      
      This PR also removes the unstable feature `SegmentSize`.
      
      This is a breaking change to the behavior of constraints. If users want
      old behavior, they can use `Flex::Legacy`.
      
      ```rust
      Layout::vertical([Length(25), Length(25)]).flex(Flex::Legacy)
      ```
      
      Users that have constraint that exceed the available space will probably
      not see any difference or see an improvement in their layouts. Any
      layout with `Min` will be identical in `Flex::Start` and `Flex::Legacy`
      so any layout with `Min` will not be breaking.
      
      Previously, `Table` used `EvenDistribution` internally by default, but
      with that gone the default is now `Flex::Start`. This changes the
      behavior of `Table` (for the better in most cases). The only way for
      users to get exactly the same as the old behavior is to change their
      constraints. I imagine most users will be happier out of the box with
      the new Table default.
      
      Resolves https://github.com/ratatui/ratatui/issues/843
      
      Thanks to `@joshka` for the direction
      
    • bbcfa55 (layout) Add Rect::contains method (#882)

      This is useful for performing hit tests (i.e. did the user click in an
      area).
      
    • 736605e (layout) Add default impl for Position (#869)

    • 1e75596 (layout) Increase default cache size to 500 (#850)

      This is a somewhat arbitrary size for the layout cache based on adding
      the columns and rows on my laptop's terminal (171+51 = 222) and doubling
      it for good measure and then adding a bit more to make it a round
      number. This gives enough entries to store a layout for every row and
      every column, twice over, which should be enough for most apps. For
      those that need more, the cache size can be set with
      `Layout::init_cache()`.
      

      Fixes:https://github.com/ratatui/ratatui/issues/820

    • 2819eea (layout) Add Position struct (#790)

      This stores the x and y coordinates (columns and rows)
      
      - add conversions from Rect
      - add conversion with Size to Rect
      - add Rect::as_position
      
    • 1561d64 (layout) Add Rect -> Size conversion methods (#789)

      - add Size::new() constructor
      - add Rect::as_size()
      - impl From<Rect> for Size
      - document and add tests for Size
      
    • f13fd73 (layout) Add Rect::clamp() method (#749)

      * feat(layout): add a Rect::clamp() method
      
      This ensures a rectangle does not end up outside an area. This is useful
      when you want to be able to dynamically move a rectangle around, but
      keep it constrained to a certain area.
      
      For example, this can be used to implement a draggable window that can
      be moved around, but not outside the terminal window.
      
      ```rust
      let window_area = Rect::new(state.x, state.y, 20, 20).clamp(area);
      state.x = rect.x;
      state.y = rect.y;
      ```
      
      * refactor: use rstest to simplify clamp test
      
      * fix: use rstest description instead of string
      
      test layout::rect::tests::clamp::case_01_inside ... ok
      test layout::rect::tests::clamp::case_02_up_left ... ok
      test layout::rect::tests::clamp::case_04_up_right ... ok
      test layout::rect::tests::clamp::case_05_left ... ok
      test layout::rect::tests::clamp::case_03_up ... ok
      test layout::rect::tests::clamp::case_06_right ... ok
      test layout::rect::tests::clamp::case_07_down_left ... ok
      test layout::rect::tests::clamp::case_08_down ... ok
      test layout::rect::tests::clamp::case_09_down_right ... ok
      test layout::rect::tests::clamp::case_10_too_wide ... ok
      test layout::rect::tests::clamp::case_11_too_tall ... ok
      test layout::rect::tests::clamp::case_12_too_large ... ok
      
      * fix: less ambiguous docs for this / other rect
      
      * fix: move rstest to dev deps
      
    • 98bcf1c (layout) Add Rect::split method (#729)

      This method splits a Rect and returns a fixed-size array of the
      resulting Rects. This allows the caller to use array destructuring
      to get the individual Rects.
      
      ```rust
      use Constraint::*;
      let layout = &Layout::vertical([Length(1), Min(0)]);
      let [top, main] = area.split(&layout);
      ```
      
    • 0494ee5 (layout) Accept Into<Constraint> for constructors (#744)

      This allows Layout constructors to accept any type that implements
      Into<Constraint> instead of just AsRef<Constraint>. This is useful when
      you want to specify a fixed size for a layout, but don't want to
      explicitly create a Constraint::Length yourself.
      
      ```rust
      Layout::new(Direction::Vertical, [1, 2, 3]);
      Layout::horizontal([1, 2, 3]);
      Layout::vertical([1, 2, 3]);
      Layout::default().constraints([1, 2, 3]);
      ```
      
    • 7ab12ed (layout) Add horizontal and vertical constructors (#728)

      * feat(layout): add vertical and horizontal constructors
      
      This commit adds two new constructors to the `Layout` struct, which
      allow the user to create a vertical or horizontal layout with default
      values.
      
      ```rust
      let layout = Layout::vertical([
          Constraint::Length(10),
          Constraint::Min(5),
          Constraint::Length(10),
      ]);
      
      let layout = Layout::horizontal([
          Constraint::Length(10),
          Constraint::Min(5),
          Constraint::Length(10),
      ]);
      ```
      
    • 4278b40 (line) Implement iterators for Line (#896)

      This allows iterating over the `Span`s of a line using `for` loops and
      other iterator methods.
      
      - add `iter` and `iter_mut` methods to `Line`
      - implement `IntoIterator` for `Line`, `&Line`, and `&mut Line` traits
      - update call sites to iterate over `Line` rather than `Line::spans`
      
    • 5d410c6 (line) Implement Widget for Line (#715)

      This allows us to use Line as a child of other widgets, and to use
      Line::render() to render it rather than calling buffer.set_line().
      
      ```rust
      frame.render_widget(Line::raw("Hello, world!"), area);
      // or
      Line::raw("Hello, world!").render(frame, area);
      ```
      
    • c977293 (line) Add style field, setters and docs (#708) [breaking]

      - The `Line` struct now stores the style of the line rather than each
        `Span` storing it.
      - Adds two new setters for style and spans
      - Adds missing docs
      

      BREAKING CHANGE:Line::style is now a field of Line instead of being stored in each Span.

    • bbf2f90 (rect.rs) Implement Rows and Columns iterators in Rect (#765)

      This enables iterating over rows and columns of a Rect. In tern being able to use that with other iterators and simplify looping over cells.
      
    • fe06f0c (serde) Support TableState, ListState, and ScrollbarState (#723)

      TableState, ListState, and ScrollbarState can now be serialized and deserialized
      using serde.
      
      ```rust
      #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
      struct AppState {
          list_state: ListState,
          table_state: TableState,
          scrollbar_state: ScrollbarState,
      }
      
      let app_state = AppState::default();
      let serialized = serde_json::to_string(app_state);
      
      let app_state = serde_json::from_str(serialized);
      ```
      
    • 37c1836 (span) Implement Widget on Span (#709)

      This allows us to use Span as a child of other widgets, and to use
      Span::render() to render it rather than calling buffer.set_span().
      
      ```rust
      frame.render_widget(Span::raw("Hello, world!"), area);
      // or
      Span::raw("Hello, world!").render(frame, area);
      // or even
      "Hello, world!".green().render(frame, area);
      ```
      
    • e1e85aa (style) Add material design color palette (#786)

      The `ratatui::style::palette::material` module contains the Google 2014
      Material Design palette.
      
      See https://m2.material.io/design/color/the-color-system.html#tools-for-picking-colors
      for more information.
      
      ```rust
      use ratatui::style::palette::material::BLUE_GRAY;
      Line::styled("Hello", BLUE_GRAY.c500);
      ```
      
    • bf67850 (style) Add tailwind color palette (#787)

      The `ratatui::style::palette::tailwind` module contains the default
      Tailwind color palette. This is useful for styling components with
      colors that match the Tailwind color palette.
      
      See https://tailwindcss.com/docs/customizing-colors for more information
      on Tailwind.
      
      ```rust
      use ratatui::style::palette::tailwind::SLATE;
      Line::styled("Hello", SLATE.c500);
      ```
      
    • 27e9216 (table) Remove allow deprecated attribute used previously for segment_size ✨ (#875)

    • a489d85 (table) Deprecate SegmentSize on table (#842)

      This adds for table:
      
      - Added new flex method with flex field
      - Deprecated segment_size method and removed segment_size field
      - Updated documentation
      - Updated tests
      
    • c69ca47 (table) Collect iterator of Row into Table (#774) [breaking]

      Any iterator whose item is convertible into `Row` can now be
      collected into a `Table`.
      
      Where previously, `Table::new` accepted `IntoIterator<Item = Row>`, it
      now accepts `IntoIterator<Item: Into<Row>>`.
      

      BREAKING CHANGE:The compiler can no longer infer the element type of the container passed to Table::new(). For example, Table::new(vec![], widths) will no longer compile, as the type of vec![] can no longer be inferred.

    • 2faa879 (table) Accept Text for highlight_symbol (#781)

      This allows for multi-line symbols to be used as the highlight symbol.
      
      ```rust
      let table = Table::new(rows, widths)
          .highlight_symbol(Text::from(vec![
              "".into(),
              " █ ".into(),
              " █ ".into(),
              "".into(),
          ]));
      ```
      
    • e64e194 (table) Implement FromIterator for widgets::Row (#755)

      The `Row::new` constructor accepts a single argument that implements
      `IntoIterator`.  This commit adds an implementation of `FromIterator`,
      as a thin wrapper around `Row::new`.  This allows `.collect::<Row>()`
      to be used at the end of an iterator chain, rather than wrapping the
      entire iterator chain in `Row::new`.
      
    • 803a72d (table) Accept Into<Constraint> for widths (#745)

      This allows Table constructors to accept any type that implements
      Into<Constraint> instead of just AsRef<Constraint>. This is useful when
      you want to specify a fixed size for a table columns, but don't want to
      explicitly create a Constraint::Length yourself.
      
      ```rust
      Table::new(rows, [1,2,3])
      Table::default().widths([1,2,3])
      ```
      
    • f025d2b (table) Add Table::footer and Row::top_margin methods (#722)

      * feat(table): Add a Table::footer method
      
    • f29c73f (tabs) Accept Iterators of Line in constructors (#776) [breaking]

      Any iterator whose item is convertible into `Line` can now be
      collected into `Tabs`.
      
      In addition, where previously `Tabs::new` required a `Vec`, it can now
      accept any object that implements `IntoIterator` with an item type
      implementing `Into<Line>`.
      

      BREAKING CHANGE:Calls to Tabs::new() whose argument is collected from an iterator will no longer compile. For example,

      Tabs::new(["a","b"].into_iter().collect()) will no longer compile, because the return type of .collect() can no longer be inferred to be a Vec<_>.

    • b459228 (termwiz) Add From termwiz style impls (#726)

      Important note: this also fixes a wrong mapping between ratatui's gray
      and termwiz's grey. `ratatui::Color::Gray` now maps to
      `termwiz::color::AnsiColor::Silver`
      
    • 9ba7354 (text) Implement iterators for Text (#900)

      This allows iterating over the `Lines`s of a text using `for` loops and
      other iterator methods.
      
      - add `iter` and `iter_mut` methods to `Text`
      - implement `IntoIterator` for `Text`, `&Text`, and `&mut Text` traits
      - update call sites to iterate over `Text` rather than `Text::lines`
      
    • 68d5783 (text) Add style and alignment (#807)

      Fixes #758, fixes #801

    This PR adds:

    • style and alignment to Text
    • impl Widget for Text
    • replace Text manual draw to call for Widget impl

    All places that use Text have been updated and support its new features expect paragraph which still has a custom implementation.

    • 815757f (widgets) Implement Widget for Widget refs (#833)

      Many widgets can be rendered without changing their state.
      
      This commit implements The `Widget` trait for references to
      widgets and changes their implementations to be immutable.
      
      This allows us to render widgets without consuming them by passing a ref
      to the widget when calling `Frame::render_widget()`.
      
      ```rust
      // this might be stored in a struct
      let paragraph = Paragraph::new("Hello world!");
      
      let [left, right] = area.split(&Layout::horizontal([20, 20]));
      frame.render_widget(&paragraph, left);
      frame.render_widget(&paragraph, right); // we can reuse the widget
      ```
      
      Implemented for all widgets except BarChart (which has an implementation
      that modifies the internal state and requires a rewrite to fix.
      
      Other widgets will be implemented in follow up commits.
      

      Fixes:https://github.com/ratatui/ratatui/discussions/164 Replaces PRs: https://github.com/ratatui/ratatui/pull/122 and

      https://github.com/ratatui/ratatui/pull/16

      Enables:https://github.com/ratatui/ratatui/issues/132 Validated as a viable working solution by:

      https://github.com/ratatui/ratatui/pull/836

    • eb79256 (widgets) Collect iterator of ListItem into List (#775)

      Any iterator whose item is convertible into `ListItem` can now be
      collected into a `List`.
      
      ```rust
      let list: List = (0..3).map(|i| format!("Item{i}")).collect();
      ```
      
    • c8dd879 (uncategorized) Add WidgetRef and StatefulWidgetRef traits (#903)

      The Widget trait consumes self, which makes it impossible to use in a
      boxed context. Previously we implemented the Widget trait for &T, but
      this was not enough to render a boxed widget. We now have a new trait
      called `WidgetRef` that allows rendering a widget by reference. This
      trait is useful when you want to store a reference to one or more
      widgets and render them later. Additionally this makes it possible to
      render boxed widgets where the type is not known at compile time (e.g.
      in a composite layout with multiple panes of different types).
      
      This change also adds a new trait called `StatefulWidgetRef` which is
      the stateful equivalent of `WidgetRef`.
      
      Both new traits are gated behind the `unstable-widget-ref` feature flag
      as we may change the exact name / approach a little on this based on
      further discussion.
      
      Blanket implementation of `Widget` for `&W` where `W` implements
      `WidgetRef` and `StatefulWidget` for `&W` where `W` implements
      `StatefulWidgetRef` is provided. This allows you to render a widget by
      reference and a stateful widget by reference.
      
      A blanket implementation of `WidgetRef` for `Option<W>` where `W`
      implements `WidgetRef` is provided. This makes it easier to render
      child widgets that are optional without the boilerplate of unwrapping
      the option. Previously several widgets implemented this manually. This
      commits expands the pattern to apply to all widgets.
      
      ```rust
      struct Parent {
          child: Option<Child>,
      }
      
      impl WidgetRef for Parent {
          fn render_ref(&self, area: Rect, buf: &mut Buffer) {
              self.child.render_ref(area, buf);
          }
      }
      ```
      
      ```rust
      let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(Greeting), Box::new(Farewell)];
      for widget in widgets {
          widget.render_ref(buf.area, &mut buf);
      }
      assert_eq!(buf, Buffer::with_lines(["Hello        Goodbye"]));
      ```
      
    • 87bf1dd (uncategorized) Replace Rect::split with Layout::areas and spacers (#904)

      In a recent commit we added Rec::split, but this feels more ergonomic as
      Layout::areas. This also adds Layout::spacers to get the spacers between
      the areas.
      
    • dab08b9 (uncategorized) Show space constrained UIs conditionally (#895)

      With this PR the constraint explorer demo only shows space constrained
      UIs instead:
      
      Smallest (15 row height):
      
      <img width="759" alt="image"
      src="https://github.com/ratatui/ratatui/assets/1813121/37a4a027-6c6d-4feb-8104-d732aee298ac">
      
      Small (20 row height):
      
      <img width="759" alt="image"
      src="https://github.com/ratatui/ratatui/assets/1813121/f76e025f-0061-4f09-9c91-2f7b00fcfb9e">
      
      Medium (30 row height):
      
      <img width="758" alt="image"
      src="https://github.com/ratatui/ratatui/assets/1813121/81b070da-1bfb-40c5-9fbc-c1ab44ce422e">
      
      Full (40 row height):
      
      <img width="760" alt="image"
      src="https://github.com/ratatui/ratatui/assets/1813121/7bb8a8c4-1a77-4bbc-a346-c8b5c198c6d3">
      
    • 2a12f7b (uncategorized) Impl Widget for &BarChart (#897)

      BarChart had some internal mutations that needed to be removed to
      implement the Widget trait for &BarChart to bring it in line with the
      other widgets.
      
    • 9ec43ef (uncategorized) Constraint Explorer example (#893)

      Here's a constraint explorer demo put together with `@joshka`
      

      https://github.com/ratatui/ratatui/assets/1813121/08d7d8f6-d013-44b4-8331-f4eee3589cce

    It allows users to interactive explore how the constraints behave with respect to each other and compare that across flex modes. It allows users to swap constraints out for other constraints, increment or decrement the values, add and remove constraints, and add spacing

    It is also a good example for how to structure a simple TUI with several Ratatui code patterns that are useful for refactoring.

    Fixes:https://github.com/ratatui/ratatui/issues/792


    Now user provided spacing gaps always take priority in all Flex modes.

    • dd5ca3a (uncategorized) Better weights for constraints (#889)

      This PR is a split of reworking the weights from #888
      
      This keeps the same ranking of weights, just uses a different numerical
      value so that the lowest weight is `WEAK` (`1.0`).
      
      No tests are changed as a result of this change, and running the
      following multiple times did not cause any errors for me:
      
      ```rust
      for i in {0..100}
      do
       cargo test --lib --
       if [ $? -ne 0 ]; then
       echo "Test failed. Exiting loop."
       break
       fi
      done
      ```
      
    • aeec163 (uncategorized) Change rounding to make tests stable (#888)

      This fixes some unstable tests
      
    • be4fdaa (uncategorized) Change priority of constraints and add split_with_spacers ✨ (#788)

      Follow up to https://github.com/ratatui/ratatui/pull/783
      
      This PR introduces different priorities for each kind of constraint.
      This PR also adds tests that specifies this behavior. This PR resolves a
      number of broken tests.
      
      Fixes https://github.com/ratatui/ratatui/issues/827
      
      With this PR, the layout algorithm will do the following in order:
      
      1. Ensure that all the segments are within the user provided area and
      ensure that all segments and spacers are aligned next to each other
      2. if a user provides a `layout.spacing`, it will enforce it.
      3. ensure proportional elements are all proportional to each other
      4. if a user provides a `Fixed(v)` constraint, it will enforce it.
      5. `Min` / `Max` binding inequality constraints
      6. `Length`
      7. `Percentage`
      8. `Ratio`
      9. collapse `Min` or collapse `Max`
      10. grow `Proportional` as much as possible
      11. grow spacers as much as possible
      
      This PR also returns the spacer areas as `Rects` to the user. Users can
      then draw into the spacers as they see fit (thanks `@joshka` for the
      idea). Here's a screenshot with the modified flex example:
      
      <img width="569" alt="image"
      src="https://github.com/ratatui/ratatui/assets/1813121/46c8901d-882c-43b0-ba87-b1d455099d8f">
      
      This PR introduces a `strengths` module that has "default" weights that
      give stable solutions as well as predictable behavior.
      
    • d713201 (uncategorized) Add Color::from_hsl ✨ (#772)

      This PR adds `Color::from_hsl` that returns a valid `Color::Rgb`.
      
      ```rust
      let color: Color = Color::from_hsl(360.0, 100.0, 100.0);
      assert_eq!(color, Color::Rgb(255, 255, 255));
      
      let color: Color = Color::from_hsl(0.0, 0.0, 0.0);
      assert_eq!(color, Color::Rgb(0, 0, 0));
      ```
      
      HSL stands for Hue (0-360 deg), Saturation (0-100%), and Lightness
      (0-100%) and working with HSL the values can be more intuitive. For
      example, if you want to make a red color more orange, you can change the
      Hue closer toward yellow on the color wheel (i.e. increase the Hue).
      

      Related #763

    • 405a125 (uncategorized) Add wide and tall proportional border set (#848)

      Adds `PROPORTIONAL_WIDE` and `PROPORTIONAL_TALL` border sets.
      

      symbols::border::PROPORTIONAL_WIDE

    ▄▄▄▄
    █xx█
    █xx█
    ▀▀▀▀
    

    symbols::border::PROPORTIONAL_TALL

    █▀▀█
    █xx█
    █xx█
    █▄▄█
    

    Fixes:https://github.com/ratatui/ratatui/issues/834

    • 9df6ceb (uncategorized) Table column calculation uses layout spacing ✨ (#824)

      This uses the new `spacing` feature of the `Layout` struct to allocate
      columns spacing in the `Table` widget.
      This changes the behavior of the table column layout in the following
      ways:
      
      1. Selection width is always allocated.
      - if a user does not want a selection width ever they should use
      `HighlightSpacing::Never`
      2. Column spacing is prioritized over other constraints
      - if a user does not want column spacing, they should use
      `Table::new(...).column_spacing(0)`
      
      ---------
      
    • f299463 (uncategorized) Add one eighth wide and tall border sets ✨ (#831)

      This PR adds the
      [`McGugan`](https://www.willmcgugan.com/blog/tech/post/ceo-just-wants-to-draw-boxes/)
      border set, which allows for tighter borders.
      
      For example, with the `flex` example you can get this effect (top is
      mcgugan wide, bottom is mcgugan tall):
      
      <img width="759" alt="image"
      src="https://github.com/ratatui/ratatui/assets/1813121/756bb50e-f8c3-4eec-abe8-ce358058a526">
      
      <img width="759" alt="image"
      src="https://github.com/ratatui/ratatui/assets/1813121/583485ef-9eb2-4b45-ab88-90bd7cb14c54">
      
      As of this PR, `MCGUGAN_WIDE` has to be styled manually, like so:
      
      ```rust
                  let main_color = color_for_constraint(*constraint);
                  let cell = buf.get_mut(block.x, block.y + 1);
                  cell.set_style(Style::reset().fg(main_color).reversed());
                  let cell = buf.get_mut(block.x, block.y + 2);
                  cell.set_style(Style::reset().fg(main_color).reversed());
                  let cell = buf.get_mut(block.x + block.width.saturating_sub(1), block.y + 1);
                  cell.set_style(Style::reset().fg(main_color).reversed());
                  let cell = buf.get_mut(block.x + block.width.saturating_sub(1), block.y + 2);
                  cell.set_style(Style::reset().fg(main_color).reversed());
      
      ```
      
      `MCGUGAN_TALL` has to be styled manually, like so:
      
      ```rust
                  let main_color = color_for_constraint(*constraint);
                  for x in block.x + 1..(block.x + block.width).saturating_sub(1) {
                      let cell = buf.get_mut(x, block.y);
                      cell.set_style(Style::reset().fg(main_color).reversed());
                      let cell = buf.get_mut(x, block.y + block.height - 1);
                      cell.set_style(Style::reset().fg(main_color).reversed());
                  }
      
      ```
      
    • ae6a2b0 (uncategorized) Add spacing feature to flex example ✨ (#830)

      This adds the `spacing` using `+` and `-` to the flex example
      
    • cddf4b2 (uncategorized) Implement Display for Text, Line, Span (#826)

      Issue:https://github.com/ratatui/ratatui/issues/816

    This PR adds:

    std::fmt::Display for Text, Line, and Span structs.

    Display implementation displays actual content while ignoring style.

    • 5131c81 (uncategorized) Add layout spacing ✨ (#821)

      This adds a `spacing` feature for layouts.
      
      Spacing can be added between items of a layout.
      
    • de97a1f (uncategorized) Add flex to layout ✨

      This PR adds a new way to space elements in a `Layout`.
      
      Loosely based on
      [flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/), this
      PR adds a `Flex` enum with the following variants:
      
      - Start
      - Center
      - End
      - SpaceAround
      - SpaceBetween
      
      <img width="380" alt="image" src="https://github.com/ratatui/ratatui/assets/1813121/b744518c-eae7-4e35-bbc4-fe3c95193cde">
      
      It also adds two more variants, to make this backward compatible and to
      make it replace `SegmentSize`:
      
      - StretchLast (default in the `Flex` enum, also behavior matches old
        default `SegmentSize::LastTakesRemainder`)
      - Stretch (behavior matches `SegmentSize::EvenDistribution`)
      
      The `Start` variant from above matches `SegmentSize::None`.
      
      This allows `Flex` to be a complete replacement for `SegmentSize`, hence
      this PR also deprecates the `segment_size` constructor on `Layout`.
      `SegmentSize` is still used in `Table` but under the hood `segment_size`
      maps to `Flex` with all tests passing unchanged.
      
      I also put together a simple example for `Flex` layouts so that I could
      test it visually, shared below:
      

      https://github.com/ratatui/ratatui/assets/1813121/c8716c59-493f-4631-add5-feecf4bd4e06

    • 9a3815b (uncategorized) Add Constraint::Fixed and Constraint::Proportional ✨ (#783)

    • 425a651 (uncategorized) Add comprehensive tests for Length interacting with other constraints ✨ (#802)

    • c50ff08 (uncategorized) Add frame count ✨ (#766)

    • 8f56fab (uncategorized) Accept Color and Modifier for all Styles (#720) [breaking]

      * feat: accept Color and Modifier for all Styles
      
      All style related methods now accept `S: Into<Style>` instead of
      `Style`.
      `Color` and `Modifier` implement `Into<Style>` so this is allows for
      more ergonomic usage. E.g.:
      
      ```rust
      Line::styled("hello", Style::new().red());
      Line::styled("world", Style::new().bold());
      
      // can now be simplified to
      

      Line::styled("hello", Color::Red);

      Line::styled("world", Modifier::BOLD);

    
    Fixes https://github.com/ratatui/ratatui/issues/694
    
      BREAKING CHANGE:All style related methods now accept `S: Into<Style>`
    instead of `Style`. This means that if you are already passing an
    ambiguous type that implements `Into<Style>` you will need to remove
    the `.into()` call.
    
    `Block` style methods can no longer be called from a const context as
    trait functions cannot (yet) be const.
    
    * feat: add tuple conversions to Style
    
    Adds conversions for various Color and Modifier combinations
    
    * chore: add unit tests
    
    ### Bug Fixes
    
    - [ee54493](https://github.com/ratatui/ratatui/commit/ee544931633ada25d84daa95e4e3a0b17801cb8b)
      *(buffer)* Don't panic in set_style ([#714](https://github.com/ratatui/ratatui/issues/714))
    
      ````text
      This fixes a panic in set_style when the area to be styled is
      outside the buffer's bounds.
    
    • c959bd2 (calendar) CalendarEventStore panic (#822)

      CalendarEventStore::today() panics if the system's UTC offset cannot be determined. In this circumstance, it's better to use now_utc instead.

    • 0614190 (cd) Fix grepping the last release (#762)

    • a67815e (chart) Exclude unnamed datasets from legend (#753)

      A dataset with no name won't display an empty line anymore in the legend.
      If no dataset have name, then no legend is ever displayed.
      
    • 3e7810a (example) Increase layout cache size (#815)

      This was causing very bad performances especially on scrolling.
      It's also a good usage demonstration.
      
    • 50b81c9 (examples/scrollbar) Title wasn't displayed because of background reset (#795)

    • b3a57f3 (list) Modify List and List example to support saving offsets. (#667)

      The current `List` example will unselect and reset the position of a
      list.
      
      This PR will save the last selected item, and updates `List` to honor
      its offset, preventing the list from resetting when the user
      `unselect()`s a `StatefulList`.
      
    • 6645d2e (table) Ensure that default and new() match (#751) [breaking]

      In https://github.com/ratatui/ratatui/pull/660 we introduced the
      segment_size field to the Table struct. However, we forgot to update
      the default() implementation to match the new() implementation. This
      meant that the default() implementation picked up SegmentSize::default()
      instead of SegmentSize::None.
      
      Additionally the introduction of Table::default() in an earlier PR,
      https://github.com/ratatui/ratatui/pull/339, was also missing the
      default for the column_spacing field (1).
      
      This commit fixes the default() implementation to match the new()
      implementation of these two fields by implementing the Default trait
      manually.
      

      BREAKING CHANGE:The default() implementation of Table now sets the column_spacing field to 1 and the segment_size field to

      SegmentSize::None. This will affect the rendering of a small amount of apps.

    • b0ed658 (table) Render missing widths as equal (#710)

      Previously, if `.widths` was not called before rendering a `Table`, no
      content would render in the area of the table. This commit changes that
      behaviour to default to equal widths for each column.
      

      Fixes #510.

    • f71bf18 (uncategorized) Bug with flex stretch with spacing and proportional constraints (#829)

      This PR fixes a bug with layouts when using spacing on proportional
      constraints.
      
    • cc6737b (uncategorized) Make SpaceBetween with one element Stretch 🐛 (#813)

      When there's just one element, `SpaceBetween` should do the same thing
      as `Stretch`.
      
    • 7a8af8d (uncategorized) Update templates links (#808)

    • f2eab71 (uncategorized) Broken tests in table.rs (#784)

      * fix: broken tests in table.rs
      
      * fix: Use default instead of raw
      
    • 8dd177a (uncategorized) Fix PR write permission to upload unsigned commit comment (#770)

    Refactor

    • cf86123 (scrollbar) Rewrite scrollbar implementation (#847)

      Implementation was simplified and calculates the size of the thumb a
      bit more proportionally to the content that is visible.
      
    • fd4703c (block) Move padding and title into separate files (#837)

    • bc274e2 (block) Remove deprecated title_on_bottom (#757) [breaking]

      Block::title_on_bottom was deprecated in v0.22. Use Block::title and Title::position instead.

    • a62632a (buffer) Split buffer module into files (#721)

    • e0aa6c5 (chart) Replace deprecated apply (#812)

      Fixes #793

    • 7f42ec9 (colors_rgb) Impl widget on mutable refs (#865)

      This commit refactors the colors_rgb example to implement the Widget
      trait on mutable references to the app and its sub-widgets. This allows
      the app to update its state while it is being rendered.
      
      Additionally the main and run functions are refactored to be similar to
      the other recent examples. This uses a pattern where the App struct has
      a `run` method that takes a terminal as an argument, and the main
      function is in control of initializing and restoring the terminal and
      installing the error hooks.
      
    • 813f707 (example) Improve constraints and flex examples (#817)

      This PR is a follow up to
      https://github.com/ratatui/ratatui/pull/811.
      
      It improves the UI of the layouts by
      
      - thoughtful accessible color that represent priority in constraints
      resolving
      - using QUADRANT_OUTSIDE symbol set for block rendering
      - adding a scrollbar
      - panic handling
      - refactoring for readability
      
      to name a few. Here are some example gifs of the outcome:
      
      
      ![constraints](https://github.com/ratatui/ratatui/assets/381361/8eed34cf-e959-472f-961b-d439bfe3324e)
      
      
      ![flex](https://github.com/ratatui/ratatui/assets/381361/3195a56c-9cb6-4525-bc1c-b969c0d6a812)
      
      ---------
      
    • bb5444f (example) Add scroll to flex example (#811)

      This commit adds `scroll` to the flex example. It also adds more examples to showcase how constraints interact. It improves the UI to make it easier to understand and short terminal friendly.
      
      <img width="380" alt="image" src="https://github.com/ratatui/ratatui/assets/1813121/30541efc-ecbe-4e28-b4ef-4d5f1dc63fec"/>
      
      ---------
      
    • 6d15b25 (layout) Move the remaining types (#743)

      - alignment -> layout/alignment.rs
      - corner -> layout/corner.rs
      - direction -> layout/direction.rs
      - size -> layout/size.rs
      
    • 659460e (layout) Move SegmentSize to layout/segment_size.rs (#742)

    • ba036cd (layout) Move Layout to layout/layout.rs (#741)

    • 8724aeb (layout) Move Margin to margin.rs (#740)

    • 9574198 (line) Reorder methods for natural reading order (#713)

    • 6364533 (table) Split table into multiple files (#718)

      At close to 2000 lines of code, the table widget was getting a bit
      unwieldy. This commit splits it into multiple files, one for each
      struct, and one for the table itself.
      
      Also refactors the table rendering code to be easier to maintain.
      
    • 5aba988 (terminal) Extract types to files (#760)

      Fields on Frame that were private are now pub(crate).
      
    • 4d262d2 (widget) Move borders to widgets/borders.rs (#832)

    • 5254795 (uncategorized) Make layout tests a bit easier to understand (#890)

    • bd6b91c (uncategorized) Make patch_style & reset_style chainable (#754) [breaking]

      Previously, `patch_style` and `reset_style` in `Text`, `Line` and `Span`
       were using a mutable reference to `Self`. To be more consistent with
       the rest of `ratatui`, which is using fluent setters, these now take
       ownership of `Self` and return it.
      
    • da6c299 (uncategorized) Extract layout::Constraint to file (#739)

    Documentation

    • 6ecaeed (text) Add overview of the relevant methods (#857)

      Add an overview of the relevant methods under `Constructor Methods`, `Setter Methods`, and `Other Methods` subtitles.
      
    • 50374b2 (backend) Fix broken book link (#733)

    • e1cc849 (breaking) Fix typo (#702)

    • 49df5d4 (example) Fix markdown syntax for note (#730)

    • 4b8e54e (examples) Refactor Tabs example (#861)

      - Used a few new techniques from the 0.26 features (ref widgets, text rendering,
        dividers / padding etc.)
      - Updated the app to a simpler application approach
      - Use color_eyre
      - Make it look pretty (colors, new proportional borders)
      
      ![Made with VHS](https://vhs.charm.sh/vhs-4WW21XTtepDhUSq4ZShO56.gif)
      
      ---------
      Fixes https://github.com/ratatui/ratatui/issues/819
      Co-authored-by: Josh McKinney <[email protected]>
      
    • 5b7ad2a (examples) Update gauge example (#863)

      - colored gauges
      - removed box borders
      - show the difference between ratio / percentage and unicode / no unicode better
      - better application approach (consistent with newer examples)
      - various changes for 0.26 features
      - impl `Widget` for `&App`
      - use color_eyre
      
      for gauge.tape
      
      - change to get better output from the new code
      
      ---------
      Fixes: https://github.com/ratatui/ratatui/issues/846
      Co-authored-by: Josh McKinney <[email protected]>
      
    • f383625 (examples) Add note about example versions to all examples (#871)

    • 847bacf (examples) Refactor demo2 (#836)

      Simplified a bunch of the logic in the demo2 example
      - Moved destroy mode to its own file.
      - Moved error handling to its own file.
      - Removed AppContext
      - Implemented Widget for &App. The app state is small enough that it
        doesn't matter here and we could just copy or clone the app state on
        every frame, but for larger apps this can be a significant performance
        improvement.
      - Made the tabs stateful
      - Made the term module just a collection of functions rather than a
        struct.
      - Changed to use color_eyre for error handling.
      - Changed keyboard shortcuts and rearranged the bottom bar.
      - Use strum for the tabs enum.
      
    • 804c841 (examples) Update list example and list.tape (#864)

      This PR adds:
      
      - subjectively better-looking list example
      - change list example to a todo list example
      - status of a TODO can be changed, further info can be seen under the list.
      
    • eb1484b (examples) Update tabs example and tabs.tape (#855)

      This PR adds:
      
      for tabs.rs
      
      - general refactoring on code
      - subjectively better looking front
      - add tailwind colors
      
      for tabs.tape
      
      - change to get better output from the new code
      
      Here is the new output:
      
      ![tabs](https://github.com/ratatui/ratatui/assets/30180366/0a9371a5-e90d-42ba-aba5-70cbf66afd1f)
      
    • 330a899 (examples) Update table example and table.tape (#840)

      In table.rs
      - added scrollbar to the table
      - colors changed to use style::palette::tailwind
      - now colors can be changed with keys (l or →) for the next color, (h or
      ←) for the previous color
      - added a footer for key info
      
      For table.tape
      - typing speed changed to 0.75s from 0.5s
      - screen size changed to fit
      - pushed keys changed to show the current example better
      

      Fixes:https://github.com/ratatui/ratatui/issues/800

    • 41de884 (examples) Document incompatible examples better (#844)

      Examples often take advantage of unreleased API changes, which makes
      them not copy-paste friendly.
      
    • 3464894 (examples) Add warning about examples matching the main branch (#778)

    • fb93db0 (examples) Simplify docs using new layout methods (#731)

      Use the new `Layout::horizontal` and `vertical` constructors and
      `Rect::split_array` through all the examples.
      
    • d6b8513 (examples) Refactor chart example to showcase scatter (#703)

    • fe84141 (layout) Document the difference in the split methods (#750)

      * docs(layout): document the difference in the split methods
      
      * fix: doc suggestion
      
    • 48b0380 (scrollbar) Complete scrollbar documentation (#823)

    • e67d3c6 (table) Fix typo (#707)

    • 065b6b0 (terminal) Document buffer diffing better (#852)

    • 86168aa (uncategorized) Fix docstring for Max constraints (#898)

    • 11e4f6a (uncategorized) Adds better documentation for constraints and flex 📚 (#818)

    • 1746a61 (uncategorized) Update links to templates repository 📚 (#810)

      This PR updates links to the `templates` repository.
      
    • 43b2b57 (uncategorized) Fix typo in Table widget description (#797)

    • 2b4aa46 (uncategorized) GitHub admonition syntax for examples README.md (#791)

      * docs: GitHub admonition syntax for examples README.md
      
      * docs: Add link to stable release
      
    • 388aa46 (uncategorized) Update crate, lib and readme links (#771)

      Link to the contributing, changelog, and breaking changes docs at the
      top of the page instead of just in the main part of the doc. This
      makes it easier to find them.
      
    Open source →
  56. 0.26.0-alpha.3 27 Jan 2024 pre-release

    Nothing published for this version

  57. 0.26.0-alpha.2 20 Jan 2024 pre-release

    Nothing published for this version

  58. 0.26.0-alpha.1 13 Jan 2024 pre-release

    Nothing published for this version

  59. 0.26.0-alpha.0 07 Jan 2024 pre-release

    Nothing published for this version

  60. 0.25.0 18 Dec 2023
    Release notes

    We are thrilled to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 🐭

    In this version, we made improvements on widgets such as List, Table and Layout and changed some of the defaults for a better user experience. Also, we renewed our website and updated our documentation/tutorials to get started with ratatui: https://ratatui.rs 🚀

    Release highlights: https://ratatui.rs/highlights/v025/

    ⚠️ List of breaking changes can be found here.

    💖 We also enabled GitHub Sponsors for our organization, consider sponsoring us if you like ratatui: https://github.com/sponsors/ratatui

    Features

    • aef4956 (list) List::new now accepts IntoIterator<Item = Into<ListItem>> (#672) [breaking]

      This allows to build list like
      
      ```
      List::new(["Item 1", "Item 2"])
      ```
      
    • 8bfd666 (paragraph) Add line_count and line_width unstable helper methods

      This is an unstable feature that may be removed in the future
      
    • 1229b96 (rect) Add offset method (#533)

      The offset method creates a new Rect that is moved by the amount
      specified in the x and y direction. These values can be positive or
      negative. This is useful for manual layout tasks.
      
      ```rust
      let rect = area.offset(Offset { x: 10, y -10 });
      ```
      
    • edacaf7 (buffer) Deprecate Cell::symbol field (#624)

      The Cell::symbol field is now accessible via a getter method (`symbol()`). This will
      allow us to make future changes to the Cell internals such as replacing `String` with
      `compact_str`.
      
    • 6b2efd0 (layout) Accept IntoIterator for constraints (#663)

      Layout and Table now accept IntoIterator for constraints with an Item
      that is AsRef<Constraint>. This allows pretty much any collection of
      constraints to be passed to the layout functions including arrays,
      vectors, slices, and iterators (without having to call collect() on
      them).
      
    • 753e246 (layout) Allow configuring layout fill (#633)

      The layout split will generally fill the remaining area when `split()`
      is called. This change allows the caller to configure how any extra
      space is allocated to the `Rect`s. This is useful for cases where the
      caller wants to have a fixed size for one of the `Rect`s, and have the
      other `Rect`s fill the remaining space.
      
      For now, the method and enum are marked as unstable because the exact
      name is still being bikeshedded. To enable this functionality, add the
      `unstable-segment-size` feature flag in your `Cargo.toml`.
      
      To configure the layout to fill the remaining space evenly, use
      `Layout::segment_size(SegmentSize::EvenDistribution)`. The default
      behavior is `SegmentSize::LastTakesRemainder`, which gives the last
      segment the remaining space. `SegmentSize::None` will disable this
      behavior. See the docs for `Layout::segment_size()` and
      `layout::SegmentSize` for more information.
      
      Fixes https://github.com/ratatui/ratatui/issues/536
      
    • 1e2f0be (layout) Add parameters to Layout::new() (#557) [breaking]

      Adds a convenience function to create a layout with a direction and a
      list of constraints which are the most common parameters that would be
      generally configured using the builder pattern. The constraints can be
      passed in as any iterator of constraints.
      
      ```rust
      let layout = Layout::new(Direction::Horizontal, [
          Constraint::Percentage(50),
          Constraint::Percentage(50),
      ]);
      ```
      
    • c862aa5 (list) Support line alignment (#599)

      The `List` widget now respects the alignment of `Line`s and renders them as expected.
      
    • 4424637 (span) Add setters for content and style (#647)

    • ebf1f42 (style) Implement From trait for crossterm to Style related structs (#686)

    • e49385b (table) Add a Table::segment_size method (#660)

      It controls how to distribute extra space to an underconstrained table.
      The default, legacy behavior is to leave the extra space unused.  The
      new options are LastTakesRemainder which gets all space to the rightmost
      column that can used it, and EvenDistribution which divides it amongst
      all columns.
      
    • b8f71c0 (widgets/chart) Add option to set the position of legend (#378)

    • 5bf4f52 (uncategorized) Implement From trait for termion to Style related structs (#692)

      * feat(termion): implement from termion color
      
      * feat(termion): implement from termion style
      
      * feat(termion): implement from termion `Bg` and `Fg`
      
    • d19b266 (uncategorized) Add Constraint helpers (e.g. from_lengths) (#641)

      Adds helper methods that convert from iterators of u16 values to the
      specific Constraint type. This makes it easy to create constraints like:
      
      ```rust
      // a fixed layout
      let constraints = Constraint::from_lengths([10, 20, 10]);
      
      // a centered layout
      let constraints = Constraint::from_ratios([(1, 4), (1, 2), (1, 4)]);
      let constraints = Constraint::from_percentages([25, 50, 25]);
      
      // a centered layout with a minimum size
      let constraints = Constraint::from_mins([0, 100, 0]);
      
      // a sidebar / main layout with maximum sizes
      let constraints = Constraint::from_maxes([30, 200]);
      ```
      

    Bug Fixes

    • f69d57c (rect) Fix underflow in the Rect::intersection method (#678)

    • 56fc410 (block) Make inner aware of title positions (#657)

      Previously, when computing the inner rendering area of a block, all
      titles were assumed to be positioned at the top, which caused the
      height of the inner area to be miscalculated.
      
    • ec7b387 (doc) Do not access deprecated Cell::symbol field in doc example (#626)

    • 37c70db (table) Add widths parameter to new() (#664) [breaking]

      This prevents creating a table that doesn't actually render anything.
      
    • 1f88da7 (table) Fix new clippy lint which triggers on table widths tests (#630)

      * fix(table): new clippy lint in 1.74.0 triggers on table widths tests
      
    • 36d8c53 (table) Widths() now accepts AsRef<[Constraint]> (#628)

      This allows passing an array, slice or Vec of constraints, which is more
      ergonomic than requiring this to always be a slice.
      
      The following calls now all succeed:
      
      ```rust
      Table::new(rows).widths([Constraint::Length(5), Constraint::Length(5)]);
      Table::new(rows).widths(&[Constraint::Length(5), Constraint::Length(5)]);
      
      // widths could also be computed at runtime
      let widths = vec![Constraint::Length(5), Constraint::Length(5)];
      Table::new(rows).widths(widths.clone());
      Table::new(rows).widths(&widths);
      ```
      
    • 34d099c (tabs) Fixup tests broken by semantic merge conflict (#665)

      Two changes without any line overlap caused the tabs tests to break
      
    • e4579f0 (tabs) Set the default highlight_style (#635) [breaking]

      Previously the default highlight_style was set to `Style::default()`,
      which meant that the highlight style was the same as the normal style.
      This change sets the default highlight_style to reversed text.
      
    • 28ac55b (tabs) Tab widget now supports custom padding (#629)

      The Tab widget now contains padding_left and padding_right
      properties. Those values can be set with functions `padding_left()`,
      `padding_right()`, and `padding()` which all accept `Into<Line>`.
      
      Fixes issue https://github.com/ratatui/ratatui/issues/502
      
    • df0eb1f (terminal) Insert_before() now accepts lines > terminal height and doesn't add an extra blank line (#596)

      Fixes issue with inserting content with height>viewport_area.height and adds
      the ability to insert content of height>terminal_height
      
      - Adds TestBackend::append_lines() and TestBackend::clear_region() methods to
        support testing the changes
      
    • aaeba27 (uncategorized) Truncate table when overflow (#685)

      This prevents a panic when rendering an empty right aligned and rightmost table cell
      
    • ffa78aa (uncategorized) Add #[must_use] to Style-moving methods (#600)

    • a2f2bd5 (uncategorized) MSRV is now 1.70.0 (#593)

    Refactor

    • f767ea7 (list) start_corner is now direction (#673)

      The previous name `start_corner` did not communicate clearly the intent of the method.
      A new method `direction` and a new enum `ListDirection` were added.
      
      `start_corner` is now deprecated
      
    • b82451f (examples) Add vim binding (#688)

    • 0576a8a (layout) To natural reading order (#681)

      Structs and enums at the top of the file helps show the interaction
      between the types without having to find each type in between longer
      impl sections.
      
      Also moved the try_split function into the Layout impl as an associated
      function and inlined the `layout::split()` which just called try_split.
      This makes the code a bit more contained.
      
    • 4be18ab (readme) Reference awesome-ratatui instead of wiki (#689)

      * refactor(readme): link awesome-ratatui instead of wiki
      
      The apps wiki moved to awesome-ratatui
      
      * docs(readme): Update README.md
      
    • 7ef0afc (widgets) Remove unnecessary dynamic dispatch and heap allocation (#597)

    • b282a06 (uncategorized) Remove items deprecated since 0.10 (#691) [breaking]

      Remove `Axis::title_style` and `Buffer::set_background` which are deprecated since 0.10
      
    • 7ced7c0 (uncategorized) Define struct WrappedLine instead of anonymous tuple (#608)

      It makes the type easier to document, and more obvious for users
      

    Documentation

    • fe632d7 (sparkline) Add documentation (#648)

    • f4c8de0 (chart) Document chart module (#696)

    • 1b8b626 (examples) Add animation and FPS counter to colors_rgb (#583)

    • 2169a0d (examples) Add example of half block rendering (#687)

      This is a fun example of how to render big text using half blocks
      
    • 41c44a4 (frame) Add docs about resize events (#697)

    • 91c67eb (github) Update code owners (#666)

      onboard `@Valentin271` as maintainer
      
    • 458fa90 (lib) Tweak the crate documentation (#659)

    • 3ec4e24 (list) Add documentation to the List widget (#669)

      Adds documentation to the List widget and all its sub components like `ListState` and `ListItem`
      
    • 9f37100 (readme) Update README.md and fix the bug that demo2 cannot run (#595)

      Fixes https://github.com/ratatui/ratatui/issues/594
      
    • 2a87251 (security) Add security policy (#676)

      * docs: Create SECURITY.md
      
      * Update SECURITY.md
      
    • 987f7ee (website) Rename book to website (#661)

    • a15c3b2 (uncategorized) Remove deprecated table constructor from breaking changes (#698)

    • 113b4b7 (uncategorized) Rename template links to remove ratatui from name 📚 (#690)

    • 211160c (uncategorized) Remove simple-tui-rs (#651)

      This has not been recently and doesn't lead to good code
      

    Styling

    Miscellaneous Tasks

    • 910ad00 (rustfmt) Enable format_code_in_doc_comments (#695)

      This enables more consistently formatted code in doc comments,
      especially since ratatui heavily uses fluent setters.
      
      See https://rust-lang.github.io/rustfmt/?version=v1.6.0#format_code_in_doc_comments
      
    • d118565 (table) Cleanup docs and builder methods (#638)

      - Refactor the `table` module for better top to bottom readability by
      putting types first and arranging them in a logical order (Table, Row,
      Cell, other).
      
      - Adds new methods for:
        - `Table::rows`
        - `Row::cells`
        - `Cell::new`
        - `Cell::content`
        - `TableState::new`
        - `TableState::selected_mut`
      
      - Makes `HighlightSpacing::should_add` pub(crate) since it's an internal
        detail.
      
      - Adds tests for all the new methods and simple property tests for all
        the other setter methods.
      
    • dd22e72 (uncategorized) Correct "builder methods" in docs and add must_use on widgets setters (#655)

    • 18e19f6 (uncategorized) Fix breaking changes doc versions (#639)

      Moves the layout::new change to unreleasedd section and adds the table change
      
    • a58cce2 (uncategorized) Disable default benchmarking (#598)

      Disables the default benchmarking behaviour for the lib target to fix unrecognized
      criterion benchmark arguments.
      
      See https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options for details
      

    Continuous Integration

    • 59b9c32 (codecov) Adjust threshold and noise settings (#615)

      Fixes https://github.com/ratatui/ratatui/issues/612
      
    • 03401cd (uncategorized) Fix untrusted input in pr check workflow (#680)

    Contributors

    Thank you so much to everyone that contributed to this release!

    Here is the list of contributors who have contributed to ratatui for the first time!

    • @rikonaka
    • @danny-burrows
    • @SOF3
    • @jan-ferdinand
    • @rhaskia
    • @asomers
    • @progval
    • @TylerBloom
    • @YeungKC
    • @lyuha
    Open source →

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive