docs: document widgets module (#1932)

Adds a good overview of the use and implementation of widget traits.

Goals with the doc rewrite:
- document the rationale for the ratatui-widgets crate with info for app
builders and widget makers.
- Show how to use the widgets for rendering as well as implement the
traits- document the differences and reasons for each trait
- document the historical perspective (to make it easy to understand
older Ratatui apps as well as migrate to newer approaches
- give recommended approaches to implementing traits
- explain the differences between Consuming and Shared / Mutable
Reference implementations of Widget
- explain the differences between using StatefulWidget and Mutable
References
- Explain the use case for WidgetRef and StatefulWidgetRef
- Link out to third part widget lists

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

---------

Co-authored-by: hasezoey <hasezoey@gmail.com>
This commit is contained in:
Josh McKinney
2025-06-25 16:19:54 -07:00
committed by GitHub
parent d41b8d6334
commit 3de41a8249
6 changed files with 566 additions and 15 deletions

View File

@@ -4,6 +4,11 @@ use crate::layout::Rect;
/// A `StatefulWidget` is a widget that can take advantage of some local state to remember things
/// between two draw calls.
///
/// For a comprehensive guide to widgets, including trait explanations, implementation patterns,
/// and available widgets, see the [`widgets`] module documentation.
///
/// [`widgets`]: ../../ratatui/widgets/index.html
///
/// Most widgets can be drawn directly based on the input parameters. However, some features may
/// require some kind of associated state to be implemented.
///

View File

@@ -6,6 +6,11 @@ use crate::style::Style;
/// A `Widget` is a type that can be drawn on a [`Buffer`] in a given [`Rect`].
///
/// For a comprehensive guide to widgets, including trait explanations, implementation patterns,
/// and available widgets, see the [`widgets`] module documentation.
///
/// [`widgets`]: ../../ratatui/widgets/index.html
///
/// Prior to Ratatui 0.26.0, widgets generally were created for each frame as they were consumed
/// during rendering. This meant that they were not meant to be stored but used as *commands* to
/// draw common figures in the UI.

View File

@@ -24,8 +24,9 @@
//! # Ratatui
//!
//! [Ratatui][Ratatui Website] is a crate for cooking up terminal user interfaces in Rust. It is a
//! lightweight library that provides a set of widgets and utilities to build complex Rust TUIs.
//! Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its development.
//! lightweight library that provides a set of [widgets](`widgets`) and utilities to build complex
//! Rust TUIs. Ratatui was forked from the [tui-rs] crate in 2023 in order to continue its
//! development.
//!
//! ## Quickstart
//!
@@ -81,10 +82,10 @@
//! ## Introduction
//!
//! Ratatui is based on the principle of immediate rendering with intermediate buffers. This means
//! that for each frame, your app must render all widgets that are supposed to be part of the UI.
//! This is in contrast to the retained mode style of rendering where widgets are updated and then
//! automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui Website]
//! for more info.
//! that for each frame, your app must render all [`widgets`] that are supposed to be part of the
//! UI. This is in contrast to the retained mode style of rendering where widgets are updated and
//! then automatically redrawn on the next frame. See the [Rendering] section of the [Ratatui
//! Website] for more info.
//!
//! Ratatui uses [Crossterm] by default as it works on most platforms. See the [Installation]
//! section of the [Ratatui Website] for more details on how to use other backends ([Termion] /

View File

@@ -1,16 +1,513 @@
#![warn(missing_docs)]
//! `widgets` is a collection of types that implement [`Widget`] or [`StatefulWidget`] or both.
//! Widgets are the building blocks of user interfaces in Ratatui.
//!
//! The widgets provided with Ratatui are implemented in the [`ratatui_widgets`] crate, and are
//! re-exported here. The [`Widget`] and [`StatefulWidget`] traits are implemented in the
//! [`ratatui_core`] crate and are also re-exported in this module. This means that you can use
//! these types directly from the `ratatui` crate without having to import the `ratatui_widgets`
//! crate.
//! They are used to create and manage the layout and style of the terminal interface. Widgets can
//! be combined and nested to create complex UIs, and can be easily customized to suit the needs of
//! your application.
//!
//! Widgets are created for each frame as they are consumed after rendered. They are not meant to be
//! stored but used as *commands* to draw common figures in the UI.
//! Ratatui provides a wide variety of built-in widgets that can be used to quickly create UIs.
//! Additionally, [`String`], [`&str`], [`Span`], [`Line`], and [`Text`] can be used as widgets
//! (though often [`Paragraph`] is used instead of these directly as it allows wrapping and
//! surrounding the text with a block).
//!
//! # Crate Organization
//!
//! Starting with Ratatui 0.30.0, the project was split into multiple crates for better modularity:
//!
//! - **[`ratatui-core`]**: Contains the core widget traits ([`Widget`], [`StatefulWidget`]) and
//! text-related types ([`String`], [`&str`], [`Span`], [`Line`], [`Text`])
//! - **[`ratatui-widgets`]**: Contains all the built-in widget implementations ([`Block`],
//! [`Paragraph`], [`List`], etc.)
//! - **[`ratatui`](crate)**: The main crate that re-exports everything for convenience. The
//! unstable [`WidgetRef`] and [`StatefulWidgetRef`] traits are defined in the main `ratatui`
//! crate as they are experimental.
//!
//! This split serves different user needs:
//!
//! - **App Authors**: Most application developers should use the main [`ratatui`](crate) crate,
//! which provides everything needed to build terminal applications with widgets, backends, and
//! layout systems
//! - **Widget Library Authors**: When creating third-party widget libraries, consider depending
//! only on [`ratatui-core`] to avoid pulling in unnecessary built-in widgets and reduce
//! compilation time for your users
//! - **Minimalist Projects**: Use [`ratatui-core`] directly if you only need the fundamental traits
//! and text types without any built-in widgets
//!
//! The modular structure allows widget library authors to create lightweight dependencies while
//! still being compatible with the broader Ratatui ecosystem.
//!
//! [`ratatui-core`]: https://crates.io/crates/ratatui-core
//! [`ratatui-widgets`]: https://crates.io/crates/ratatui-widgets
//!
//! # Widget Traits
//!
//! In Ratatui, widgets are implemented as Rust traits, which allow for easy implementation and
//! extension. The main traits for widgets are:
//!
//! - [`Widget`]: Basic trait for stateless widgets that are consumed when rendered
//! - [`StatefulWidget`]: Trait for widgets that maintain state between renders
//! - [`WidgetRef`]: Trait for rendering widgets by reference (unstable)
//! - [`StatefulWidgetRef`]: Trait for rendering stateful widgets by reference (unstable)
//!
//! ## `Widget`
//!
//! The [`Widget`] trait is the most basic trait for widgets in Ratatui. It provides the basic
//! functionality for rendering a widget onto a buffer. Widgets implementing this trait are consumed
//! when rendered.
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect};
//! pub trait Widget {
//! fn render(self, area: Rect, buf: &mut Buffer);
//! }
//! ```
//!
//! Prior to Ratatui 0.26.0, widgets were generally created for each frame as they were consumed
//! during rendering. This meant that they were not meant to be stored but used as *commands* to
//! draw common figures in the UI. Starting with 0.26.0, implementing widgets on references became
//! the preferred pattern for reusability.
//!
//! ## `StatefulWidget`
//!
//! The [`StatefulWidget`] trait is similar to the [`Widget`] trait, but also includes state that
//! can be managed and updated during rendering. This is useful for widgets that need to remember
//! things between draw calls, such as scroll position or selection state.
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect};
//! pub trait StatefulWidget {
//! type State;
//! fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
//! }
//! ```
//!
//! For example, the built-in [`List`] widget can highlight the currently selected item. This
//! requires maintaining an offset to ensure the selected item is visible within the viewport.
//! Without state, the widget could only provide basic scrolling behavior, but with access to the
//! previous offset, it can implement natural scrolling where the offset is preserved until the
//! selected item moves out of view.
//!
//! ## `WidgetRef` and `StatefulWidgetRef`
//!
//! The [`WidgetRef`] and [`StatefulWidgetRef`] traits were introduced in Ratatui 0.26.0 to enable
//! rendering widgets by reference instead of consuming them. These traits address several important
//! use cases that the original `Widget` and `StatefulWidget` traits couldn't handle elegantly.
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect};
//! # #[cfg(feature = "unstable-widget-ref")]
//! pub trait WidgetRef {
//! fn render_ref(&self, area: Rect, buf: &mut Buffer);
//! }
//!
//! # #[cfg(feature = "unstable-widget-ref")]
//! pub trait StatefulWidgetRef {
//! type State;
//! fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
//! }
//! ```
//!
//! The reference-based traits solve several key problems:
//!
//! - **Reusability**: Widgets can be rendered multiple times without being consumed
//! - **Collections**: Store heterogeneous widgets in collections like `Vec<Box<dyn WidgetRef>>`
//! - **Borrowing**: Render widgets when you only have a reference, not ownership
//! - **Efficiency**: Avoid unnecessary cloning or reconstruction for repeated renders
//!
//! These traits are currently **experimental** and gated behind the `unstable-widget-ref` feature
//! flag. This means:
//!
//! - The API may change in future releases
//! - Method names, signatures, or behavior might be adjusted based on community feedback
//! - You must explicitly enable the feature flag to use them: `features = ["unstable-widget-ref"]`
//! - They are not covered by semantic versioning guarantees until stabilized
//!
//! The traits are being evaluated for potential breaking changes and improvements. See the
//! [tracking issue](https://github.com/ratatui/ratatui/issues/1287) for ongoing discussions and
//! design considerations.
//!
//! # Rendering Widgets
//!
//! Widgets are typically rendered using the [`Frame`] type, which provides methods for rendering
//! both consuming and reference-based widgets. These methods are usually called from the closure
//! passed to [`Terminal::draw`].
//!
//! ## Rendering Consuming Widgets
//!
//! Most widgets in Ratatui are rendered using `Frame::render_widget()`, which consumes the widget
//! when rendering. This is the standard approach for stateless widgets that don't need to persist
//! data between frames.
//!
//! ```rust
//! # use ratatui::{backend::TestBackend, Terminal};
//! # use ratatui::widgets::Paragraph;
//! # let backend = TestBackend::new(10, 3);
//! # let mut terminal = Terminal::new(backend).unwrap();
//! terminal.draw(|frame| {
//! let widget = Paragraph::new("Hello, world!");
//! frame.render_widget(widget, frame.area());
//! });
//! ```
//!
//! ## Rendering Widget References
//!
//! When you implement widgets on references (`Widget for &MyWidget`), you can render them directly
//! using the same `Frame::render_widget()` method. This approach enables widget reuse without
//! reconstruction and is the recommended pattern for new widgets.
//!
//! ```rust
//! # use ratatui::{backend::TestBackend, Terminal};
//! # use ratatui::widgets::{Block, Paragraph};
//! # let backend = TestBackend::new(10, 3);
//! # let mut terminal = Terminal::new(backend).unwrap();
//! // Create the widget outside the draw closure
//! let paragraph = Paragraph::new("Hello, world!").block(Block::bordered());
//!
//! terminal.draw(|frame| {
//! // Widget can be rendered by reference without being consumed
//! frame.render_widget(&paragraph, frame.area());
//! });
//!
//! // The widget can be used again in subsequent frames
//! terminal.draw(|frame| {
//! frame.render_widget(&paragraph, frame.area());
//! });
//! ```
//!
//! ## Rendering Stateful Widgets
//!
//! Widgets that need to maintain state between frames use `Frame::render_stateful_widget()`. This
//! method takes both the widget and a mutable reference to its state, allowing the widget to read
//! and modify state during rendering (such as updating scroll positions or handling selections).
//!
//! ```rust
//! # use ratatui::{backend::TestBackend, Terminal};
//! # use ratatui::widgets::{List, ListItem, ListState};
//! # let backend = TestBackend::new(10, 3);
//! # let mut terminal = Terminal::new(backend).unwrap();
//! let mut list_state = ListState::default();
//! terminal.draw(|frame| {
//! let items = vec![ListItem::new("Item 1"), ListItem::new("Item 2")];
//! let list = List::new(items);
//! frame.render_stateful_widget(list, frame.area(), &mut list_state);
//! });
//! ```
//!
//! ## Single Root Widget Pattern
//!
//! A common compositional pattern in Ratatui applications is to have a single root widget (often an
//! `App` struct) that represents your entire application state. This widget is passed to
//! `Frame::render_widget()`, and within its render method, it calls render on child widgets
//! directly. This pattern provides a clean separation between your application logic and rendering
//! code, and allows for easy composition of complex UIs from simpler components.
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect, widgets::Widget};
//! # use ratatui::widgets::{Block, Paragraph};
//! #[derive(Default)]
//! struct App {
//! should_quit: bool,
//! }
//!
//! impl Widget for &App {
//! fn render(self, area: Rect, buf: &mut Buffer) {
//! // Render header
//! let header = Paragraph::new("My App").block(Block::bordered());
//! header.render(Rect::new(area.x, area.y, area.width, 3), buf);
//!
//! // Render main content
//! let content = Paragraph::new("Main content area");
//! content.render(
//! Rect::new(area.x, area.y + 3, area.width, area.height - 3),
//! buf,
//! );
//! }
//! }
//! ```
//!
//! # Authoring Custom Widgets
//!
//! When implementing custom widgets in Ratatui, you'll make fundamental decisions about how your
//! widget manages state and how it's used by applications. Understanding these choices will help
//! you create widgets that fit well into your application's architecture. Widget implementation
//! involves several key architectural decisions that work together to determine how your widget
//! behaves - these decisions are independent but complementary, allowing you to mix and match
//! approaches based on your specific needs.
//!
//! **State Management**: The first choice is where state lives. Some widgets need to track
//! information between renders - things like scroll positions, selections, or counters. You can
//! either build this state into the widget itself (widget-owned state) or keep it separate and pass
//! it in during rendering (external state).
//!
//! **Ownership Model**: The second choice is how the widget is consumed. Widgets can either be
//! consumed when rendered (taking ownership) or work by reference (borrowing). Reference-based
//! widgets can be stored and reused across multiple frames, while consuming widgets are created
//! fresh each time.
//!
//! **`StatefulWidget` vs Mutable References**: When your widget needs state, you have two main
//! approaches. The [`StatefulWidget`] trait represents the established pattern - it separates the
//! widget from its state, allowing the application to own and manage the state independently. This
//! is what you'll see in most existing Ratatui code and built-in widgets like [`List`] and
//! [`Table`]. The mutable reference approach (`Widget for &mut MyWidget`) is newer and less common,
//! but useful when the state is intrinsic to the widget's identity. With mutable references, the
//! widget owns its state directly.
//!
//! The key question for state management is: "If I recreate this widget, should the state reset?"
//! If yes (like a counter that should start at zero), use mutable references with widget-owned
//! state. If no (like a list selection that should persist), use [`StatefulWidget`] with external
//! state that the application manages.
//!
//! **Evolution and Current Recommendations**: Ratatui's patterns have evolved significantly. Before
//! version 0.26.0, widgets were typically consuming (`Widget for MyWidget`) and created fresh each
//! frame. Starting with 0.26.0, reference-based widgets (`Widget for &MyWidget`) became possible,
//! allowing widgets to be stored and reused. You'll encounter both patterns in existing code, but
//! reference-based implementations are now recommended for new widgets because they enable
//! reusability and automatic [`WidgetRef`] support through blanket implementations.
//!
//! For new widgets, implement [`Widget`] or [`StatefulWidget`] on references to your widget types
//! (`&MyWidget` or `&mut MyWidget`). This provides reusability and automatic [`WidgetRef`] support.
//! You can optionally implement the consuming version for backward compatibility.
//!
//! ## Shared References (`&Widget`)
//!
//! The recommended pattern for most new widgets implements [`Widget`] on a shared reference,
//! allowing the widget to be rendered multiple times without being consumed. This approach is ideal
//! for immutable widgets that don't need to modify their internal state during rendering, and it's
//! the most common pattern you should use for new widgets.
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect, text::Line, widgets::Widget};
//! struct MyWidget {
//! content: String,
//! }
//!
//! impl Widget for &MyWidget {
//! fn render(self, area: Rect, buf: &mut Buffer) {
//! Line::raw(&self.content).render(area, buf);
//! }
//! }
//! ```
//!
//! This automatically provides [`WidgetRef`] support through blanket implementations and enables
//! widgets to be stored and reused across frames without reconstruction. For most use cases where
//! the widget doesn't need to change its internal state during rendering, this is the best choice.
//!
//! ## Mutable References (`&mut Widget`)
//!
//! For widgets that need to modify their internal state during rendering, implement [`Widget`] on a
//! mutable reference. This is a newer pattern that's less common but useful when the state is
//! intrinsic to the widget's identity and behavior. Use this pattern when the widget should own and
//! manage its state directly, rather than having external state passed in.
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect, text::Line, widgets::Widget};
//! struct CounterWidget {
//! count: u32, // This state belongs to the widget
//! label: String,
//! }
//!
//! impl Widget for &mut CounterWidget {
//! fn render(self, area: Rect, buf: &mut Buffer) {
//! self.count += 1; // State changes as part of rendering behavior
//! let text = format!("{label}: {count}", label = self.label, count = self.count);
//! Line::raw(text).render(area, buf);
//! }
//! }
//! ```
//!
//! This pattern works well when the widget owns its state and the state is part of the widget's
//! identity. It's ideal for counters, animations, cursors, progress indicators, or other
//! widget-specific behavior where the state should reset when you create a new widget instance.
//!
//! ## Consuming Widget Implementation
//!
//! The consuming widget pattern was the original approach in Ratatui and remains very common in
//! existing codebases. You'll encounter this pattern frequently when reading examples and community
//! code. Widgets implementing this pattern take ownership when rendered, which means they're
//! consumed on each use. While not the recommended approach for new widgets, it's still useful to
//! understand this pattern for compatibility and when working with existing code.
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect, style::Modifier, text::{Line, Span}, widgets::Widget};
//! struct GreetingWidget {
//! name: String,
//! }
//!
//! impl Widget for GreetingWidget {
//! fn render(self, area: Rect, buf: &mut Buffer) {
//! let hello = Span::raw("Hello, ");
//! let name = Span::styled(self.name, Modifier::BOLD);
//! let line = Line::from(vec![hello, name]);
//! line.render(area, buf);
//! }
//! }
//! ```
//!
//! This approach is simpler and works well for widgets created fresh each frame, but it means the
//! widget cannot be reused. Before reference-based widgets were introduced in version 0.26.0, this
//! was the standard pattern, and it's still valid for simple use cases or when following existing
//! code patterns.
//!
//! The easiest way to implement this pattern when you have a reference-based widget is to implement
//! the consuming version on the owned type, which can then call the reference-based implementation:
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect, widgets::Widget};
//! # struct GreetingWidget;
//! # impl Widget for &GreetingWidget {
//! # fn render(self, area: Rect, buf: &mut Buffer) {}
//! # }
//! impl Widget for GreetingWidget {
//! fn render(self, area: Rect, buf: &mut Buffer) {
//! // Call the reference-based implementation
//! (&self).render(area, buf);
//! }
//! }
//! ``````
//!
//! ## `StatefulWidget` Implementation
//!
//! When your widget needs to work with external state - data that exists independently of the
//! widget and should persist between widget instances - implement [`StatefulWidget`]. This is the
//! established pattern used by built-in widgets like [`List`] and [`Table`], where the widget
//! configuration is separate from application state like selections or scroll positions.
//!
//! Like [`Widget`], you can implement [`StatefulWidget`] on references to allow reuse, though it's
//! more common to see this trait implemented on owned types which are consumed during rendering.
//!
//! ```rust
//! # use ratatui_core::{buffer::Buffer, layout::Rect, text::Line, widgets::{StatefulWidget, Widget}};
//! struct ListView {
//! items: Vec<String>,
//! }
//!
//! #[derive(Default)]
//! struct ListState {
//! selected: Option<usize>, // This is application state
//! scroll_offset: usize,
//! }
//!
//! impl StatefulWidget for ListView {
//! type State = ListState;
//!
//! fn render(self, area: Rect, buf: &mut Buffer, state: &mut ListState) {
//! // Render based on external state, possibly modify for scrolling
//! let display_text = state
//! .selected
//! .and_then(|i| self.items.get(i))
//! .map_or("None selected", |s| s.as_str());
//! Line::raw(display_text).render(area, buf);
//! }
//! }
//! ```
//!
//! This pattern is ideal for selections, scroll positions, form data, or any state that should
//! persist between renders or be shared across your application. The state exists independently of
//! the widget, so recreating the widget doesn't reset the state.
//!
//! ### Automatic `WidgetRef` Support
//!
//! When you implement `Widget for &MyWidget`, you automatically get [`WidgetRef`] support without
//! any additional code. Ratatui provides blanket implementations that automatically implement these
//! traits for any type that implements [`Widget`] or [`StatefulWidget`] on a reference. This means
//! that implementing `Widget for &MyWidget` gives you both the standard widget functionality and
//! the unstable [`WidgetRef`] capabilities for free.
//!
//! ## Manual `WidgetRef` Implementation (Advanced)
//!
//! Manual implementation of [`WidgetRef`] or [`StatefulWidgetRef`] is only necessary when you need
//! to store widgets as trait objects (`Box<dyn WidgetRef>`) or when you want a different API than
//! the reference-based [`Widget`] implementation provides. In most cases, the automatic
//! implementation via blanket implementations is sufficient.
//!
//! These traits enable several benefits:
//! - Widgets can be stored and rendered multiple times without reconstruction
//! - Collections of widgets with different types can be stored using `Box<dyn WidgetRef>`
//! - Avoids the consumption model while maintaining backward compatibility
//!
//! Manual implementation is only needed when you want to use trait objects or need a different API
//! than the reference-based [`Widget`] implementation:
//!
//! ```rust
//! # #[cfg(feature = "unstable-widget-ref")] {
//! # use ratatui_core::{buffer::Buffer, layout::Rect, style::Modifier, text::{Line, Span}};
//! # use ratatui::widgets::{Widget, WidgetRef};
//! struct GreetingWidget {
//! name: String,
//! }
//!
//! // Manual WidgetRef implementation (usually not needed)
//! impl WidgetRef for GreetingWidget {
//! fn render_ref(&self, area: Rect, buf: &mut Buffer) {
//! let hello = Span::raw("Hello, ");
//! let name = Span::styled(&self.name, Modifier::BOLD);
//! let line = Line::from(vec![hello, name]);
//! line.render(area, buf);
//! }
//! }
//!
//! // For backward compatibility
//! impl Widget for GreetingWidget {
//! fn render(self, area: Rect, buf: &mut Buffer) {
//! self.render_ref(area, buf);
//! }
//! }
//! # }
//! ```
//!
//! This pattern allows the widget to be stored and rendered multiple times:
//!
//! ```rust
//! # #[cfg(feature = "unstable-widget-ref")] {
//! # use ratatui_core::{buffer::Buffer, layout::Rect};
//! # use ratatui::widgets::WidgetRef;
//! # struct GreetingWidget { name: String }
//! # impl WidgetRef for GreetingWidget {
//! # fn render_ref(&self, area: Rect, buf: &mut Buffer) {}
//! # }
//! struct App {
//! greeting: GreetingWidget,
//! }
//!
//! // The widget can be rendered multiple times without reconstruction
//! fn render_app(app: &App, area: Rect, buf: &mut Buffer) {
//! app.greeting.render_ref(area, buf);
//! }
//! # }
//! ```
//!
//! ### Using Trait Objects for Dynamic Collections
//!
//! The main benefit of manual [`WidgetRef`] implementation is the ability to create collections of
//! different widget types using trait objects. This is useful when you need to store widgets with
//! types that are not known at compile time:
//!
//! ```rust
//! # #[cfg(feature = "unstable-widget-ref")] {
//! # use ratatui_core::{buffer::Buffer, layout::Rect};
//! # use ratatui::widgets::WidgetRef;
//! # struct Greeting;
//! # struct Farewell;
//! # impl WidgetRef for Greeting { fn render_ref(&self, area: Rect, buf: &mut Buffer) {} }
//! # impl WidgetRef for Farewell { fn render_ref(&self, area: Rect, buf: &mut Buffer) {} }
//! # let area = Rect::new(0, 0, 10, 3);
//! # let mut buf = &mut Buffer::empty(area);
//! let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(Greeting), Box::new(Farewell)];
//!
//! for widget in &widgets {
//! widget.render_ref(area, buf);
//! }
//! # }
//! ```
//!
//! However, if you implement `Widget for &MyWidget`, you can achieve similar functionality by
//! storing references or using the automatic [`WidgetRef`] implementation without needing to
//! manually implement the trait.
//!
//! # Built-in Widgets
//!
//! Ratatui provides a comprehensive set of built-in widgets:
//!
//! The available widgets are:
//! - [`Block`]: a basic widget that draws a block with optional borders, titles and styles.
//! - [`BarChart`]: displays multiple datasets as bars with optional grouping.
//! - [`calendar::Monthly`]: displays a single month.
@@ -28,7 +525,40 @@
//! - [`RatatuiLogo`]: displays the Ratatui logo.
//! - [`RatatuiMascot`]: displays the Ratatui mascot.
//!
//! Additionally, primitive text types implement [`Widget`]:
//! - [`String`]: renders the owned string content
//! - [`&str`]: renders the string slice content
//! - [`Line`]: renders a single line of styled text spans
//! - [`Span`]: renders a styled text segment
//! - [`Text`]: renders multiple lines of styled text
//!
//! For more information on these widgets, you can view the widget showcase and examples.
//!
//! # Third-Party Widgets
//!
//! Beyond the built-in widgets, there's a rich ecosystem of third-party widgets available that
//! extend Ratatui's functionality. These community-contributed widgets provide specialized UI
//! components for various use cases.
//!
//! To discover third-party widgets:
//!
//! - **Search crates.io**: Look for crates with "tui" or "ratatui" in their names or descriptions
//! - **Awesome Ratatui**: Check the [Awesome Ratatui](https://github.com/ratatui-org/awesome-ratatui)
//! repository for a curated list of widgets, libraries, and applications
//! - **Widget Showcase**: Browse the [third-party widgets showcase](https://ratatui.rs/showcase/third-party-widgets/)
//! on the Ratatui website to see widgets in action
//!
//! These third-party widgets cover a wide range of functionality including specialized input
//! components, data visualization widgets, layout helpers, and domain-specific UI elements.
//!
//! [`Canvas`]: crate::widgets::canvas::Canvas
//! [`Frame`]: crate::Frame
//! [`Terminal::draw`]: crate::Terminal::draw
//! [`Line`]: crate::text::Line
//! [`Span`]: crate::text::Span
//! [`Text`]: crate::text::Text
//! [`String`]: alloc::string::String
//! [`&str`]: str
pub use ratatui_core::widgets::{StatefulWidget, Widget};
pub use ratatui_widgets::barchart::{Bar, BarChart, BarGroup};

View File

@@ -19,6 +19,11 @@ use crate::layout::Rect;
/// See the documentation for [`WidgetRef`] for more information on boxed widgets. See the
/// documentation for [`StatefulWidget`] for more information on stateful widgets.
///
/// For comprehensive information about widget implementation patterns, rendering, and usage,
/// see the [`widgets`] module documentation.
///
/// [`widgets`]: crate::widgets
///
/// # Examples
///
/// ```rust

View File

@@ -24,6 +24,11 @@ use crate::style::Style;
/// provided. This is a convenience approach to make it easier to attach child widgets to parent
/// widgets. It allows you to render an optional widget by reference.
///
/// For comprehensive information about widget implementation patterns, rendering, and usage,
/// see the [`widgets`] module documentation.
///
/// [`widgets`]: crate::widgets
///
/// # Examples
///
/// ```rust