PackageTrack
Sign in Get early access

ratatui-widgets

A collection of Ratatui widgets for building terminal user interfaces using Ratatui.

0.3.2 15M downloads/mo #2484 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

Some releases are documented

notes for 6 of 18 stable releases

Nothing withdrawn

no release was ever pulled

3 years old

26 releases · first in 2024

5 releases in the last 12 months

see the full history below

Release timeline

26 releases · Jan 2024 to Jun 2026
2025 2026
Release Pre-release

Releases

latest 26
  1. 0.3.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 →
  2. 0.3.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 →
  3. 0.3.0 26 Dec 2025
    Release notes

    Features

    • Add experimental test backend
    Open source →
  4. 0.3.0-beta.1 23 Dec 2025 pre-release
    Release notes

    Breaking Changes

    • Replace Item by a generic and flexible Text that can be used in both Paragraph and List widgets.
    • Remove unnecessary borrows on Style.
    Open source →
  5. 0.3.0-beta.0 31 Oct 2025 pre-release
    Release notes

    Features

    • Add a basic Crossterm backend

    Breaking Changes

    • Remove Group and introduce Layout in its place
      • Terminal is no longer required to compute a layout
      • Size has been renamed Constraint
    • Widgets are rendered on a Frame instead of a Terminal in order to avoid mixing draw and render calls
    • draw on Terminal expects a closure where the UI is built by rendering widgets on the given Frame
    • Update Widget trait
      • draw takes area by value
      • render takes a Frame instead of a Terminal
    • All widgets use the consumable builder pattern
    • SelectableList can have no selected item and the highlight symbol is hidden in this case
    • Remove markup language inside Paragraph. Paragraph now expects an iterator of Text items
    Open source →
  6. 0.3.0-alpha.5 30 Jun 2025 pre-release

    Nothing published for this version

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

    Nothing published for this version

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

    Nothing published for this version

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

    Nothing published for this version

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

    Nothing published for this version

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

    Nothing published for this version

  12. 0.2.2 19 Oct 2024
    Release notes

    Features

    • Terminal implements Debug

    Breaking Changes

    • Use FnOnce instead of FnMut in Group::render
    Open source →
  13. 0.2.1 19 Oct 2024
    Release notes

    Features

    • Add AlternateScreenBackend in termion backend
    • Add TermionBackend::with_stdout in order to let an user of the library provides its own termion struct
    • Add tests and documentation for Buffer::pos_of
    • Remove leading whitespaces when wrapping text

    Bug Fixes

    • Fix debug_assert in Buffer::pos_of
    • Pass the style of SelectableList to the underlying List
    • Fix missing character when wrapping text
    • Fix panic when specifying layout constraints
    Open source →
  14. 0.2.0 02 Oct 2024
    Release notes

    Features

    • Add MouseBackend in termion backend to handle scroll and mouse events
    • Add generic Item for items in a List
    • Drop log4rs as a dev-dependencies in favor of stderrlog

    Breaking Changes

    • Rename TermionBackend to RawBackend (to distinguish it from the MouseBackend)
    • Generic parameters for List to allow passing iterators as items
    • Generic parameters for Table to allow using iterators as rows and header
    • Generic parameters for Tabs
    • Rename border bitflags to Borders
    Open source →
  15. 0.1.11 02 Sep 2024

    Nothing published for this version

  16. 0.1.10 06 Aug 2024

    Nothing published for this version

  17. 0.1.9 22 Jul 2024

    Nothing published for this version

  18. 0.1.8 15 Jul 2024

    Nothing published for this version

  19. 0.1.7 02 Jul 2024

    Nothing published for this version

  20. 0.1.6 27 May 2024

    Nothing published for this version

  21. 0.1.5 24 Apr 2024

    Nothing published for this version

  22. 0.1.4 01 Apr 2024

    Nothing published for this version

  23. 0.1.3 01 Apr 2024

    Nothing published for this version

  24. 0.1.2 12 Mar 2024

    Nothing published for this version

  25. 0.1.1 03 Feb 2024

    Nothing published for this version

  26. 0.1.0 19 Jan 2024

    Nothing published for this version

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