ratatui/widgets.rs
1#![warn(missing_docs)]
2//! Widgets are the building blocks of user interfaces in Ratatui.
3//!
4//! They are used to create and manage the layout and style of the terminal interface. Widgets can
5//! be combined and nested to create complex UIs, and can be easily customized to suit the needs of
6//! your application.
7//!
8//! Ratatui provides a wide variety of built-in widgets that can be used to quickly create UIs.
9//! Additionally, [`String`], [`&str`], [`Span`], [`Line`], and [`Text`] can be used as widgets
10//! (though often [`Paragraph`] is used instead of these directly as it allows wrapping and
11//! surrounding the text with a block).
12//!
13//! # Crate Organization
14//!
15//! Starting with Ratatui 0.30.0, the project was split into multiple crates for better modularity:
16//!
17//! - **[`ratatui-core`]**: Contains the core widget traits ([`Widget`], [`StatefulWidget`]) and
18//! text-related types ([`String`], [`&str`], [`Span`], [`Line`], [`Text`])
19//! - **[`ratatui-widgets`]**: Contains all the built-in widget implementations ([`Block`],
20//! [`Paragraph`], [`List`], etc.)
21//! - **[`ratatui`](crate)**: The main crate that re-exports everything for convenience. The
22//! unstable [`WidgetRef`] and [`StatefulWidgetRef`] traits are defined in the main `ratatui`
23//! crate as they are experimental.
24//!
25//! This split serves different user needs:
26//!
27//! - **App Authors**: Most application developers should use the main [`ratatui`](crate) crate,
28//! which provides everything needed to build terminal applications with widgets, backends, and
29//! layout systems
30//! - **Widget Library Authors**: When creating third-party widget libraries, consider depending
31//! only on [`ratatui-core`] to avoid pulling in unnecessary built-in widgets and reduce
32//! compilation time for your users
33//! - **Minimalist Projects**: Use [`ratatui-core`] directly if you only need the fundamental traits
34//! and text types without any built-in widgets
35//!
36//! The modular structure allows widget library authors to create lightweight dependencies while
37//! still being compatible with the broader Ratatui ecosystem.
38//!
39//! [`ratatui-core`]: https://crates.io/crates/ratatui-core
40//! [`ratatui-widgets`]: https://crates.io/crates/ratatui-widgets
41//!
42//! # Built-in Widgets
43//!
44//! Ratatui provides a comprehensive set of built-in widgets:
45//!
46//! - [`Block`]: a basic widget that draws a block with optional borders, titles and styles.
47//! - [`BarChart`]: displays multiple datasets as bars with optional grouping.
48//! - [`calendar::Monthly`]: displays a single month.
49//! - [`Canvas`]: draws arbitrary shapes using drawing characters.
50//! - [`Chart`]: displays multiple datasets as a lines or scatter graph.
51//! - [`Clear`]: clears the area it occupies. Useful to render over previously drawn widgets.
52//! - [`Gauge`]: displays progress percentage using block characters.
53//! - [`LineGauge`]: display progress as a line.
54//! - [`List`]: displays a list of items and allows selection.
55//! - [`Paragraph`]: displays a paragraph of optionally styled and wrapped text.
56//! - [`Scrollbar`]: displays a scrollbar.
57//! - [`Sparkline`]: display a single data set as a sparkline.
58//! - [`Table`]: displays multiple rows and columns in a grid and allows selection.
59//! - [`Tabs`]: displays a tab bar and allows selection.
60//! - [`RatatuiLogo`]: displays the Ratatui logo.
61//! - [`RatatuiMascot`]: displays the Ratatui mascot.
62//!
63//! Additionally, primitive text types implement [`Widget`]:
64//! - [`String`]: renders the owned string content
65//! - [`&str`]: renders the string slice content
66//! - [`Line`]: renders a single line of styled text spans
67//! - [`Span`]: renders a styled text segment
68//! - [`Text`]: renders multiple lines of styled text
69//!
70//! For more information on these widgets, you can view the widget showcase and examples.
71//!
72//! # Third-Party Widgets
73//!
74//! Beyond the built-in widgets, there's a rich ecosystem of third-party widgets available that
75//! extend Ratatui's functionality. These community-contributed widgets provide specialized UI
76//! components for various use cases.
77//!
78//! To discover third-party widgets:
79//!
80//! - **Search crates.io**: Look for crates with "tui" or "ratatui" in their names or descriptions
81//! - **Awesome Ratatui**: Check the [Awesome Ratatui](https://github.com/ratatui-org/awesome-ratatui)
82//! repository for a curated list of widgets, libraries, and applications
83//! - **Widget Showcase**: Browse the [third-party widgets showcase](https://ratatui.rs/showcase/third-party-widgets/)
84//! on the Ratatui website to see widgets in action
85//!
86//! These third-party widgets cover a wide range of functionality including specialized input
87//! components, data visualization widgets, layout helpers, and domain-specific UI elements.
88//!
89//! [`Canvas`]: crate::widgets::canvas::Canvas
90//! [`Frame`]: crate::Frame
91//! [`Terminal::draw`]: crate::Terminal::draw
92//! [`Line`]: crate::text::Line
93//! [`Span`]: crate::text::Span
94//! [`Text`]: crate::text::Text
95//! [`String`]: alloc::string::String
96//! [`&str`]: str
97//!
98//! # Widget Traits
99//!
100//! In Ratatui, widgets are implemented as Rust traits, which allow for easy implementation and
101//! extension. The main traits for widgets are:
102//!
103//! - [`Widget`]: Basic trait for stateless widgets that are consumed when rendered
104//! - [`StatefulWidget`]: Trait for widgets that maintain state between renders
105//! - [`WidgetRef`]: Trait for rendering widgets by reference (unstable)
106//! - [`StatefulWidgetRef`]: Trait for rendering stateful widgets by reference (unstable)
107//!
108//! ## `Widget`
109//!
110//! The [`Widget`] trait is the most basic trait for widgets in Ratatui. It provides the basic
111//! functionality for rendering a widget onto a buffer. Widgets implementing this trait are consumed
112//! when rendered.
113//!
114//! ```rust
115//! # use ratatui_core::{buffer::Buffer, layout::Rect};
116//! pub trait Widget {
117//! fn render(self, area: Rect, buf: &mut Buffer);
118//! }
119//! ```
120//!
121//! Prior to Ratatui 0.26.0, widgets were generally created for each frame as they were consumed
122//! during rendering. This meant that they were not meant to be stored but used as *commands* to
123//! draw common figures in the UI. Starting with 0.26.0, implementing widgets on references became
124//! the preferred pattern for reusability.
125//!
126//! ## `StatefulWidget`
127//!
128//! The [`StatefulWidget`] trait is similar to the [`Widget`] trait, but also includes state that
129//! can be managed and updated during rendering. This is useful for widgets that need to remember
130//! things between draw calls, such as scroll position or selection state.
131//!
132//! ```rust
133//! # use ratatui_core::{buffer::Buffer, layout::Rect};
134//! pub trait StatefulWidget {
135//! type State;
136//! fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
137//! }
138//! ```
139//!
140//! For example, the built-in [`List`] widget can highlight the currently selected item. This
141//! requires maintaining an offset to ensure the selected item is visible within the viewport.
142//! Without state, the widget could only provide basic scrolling behavior, but with access to the
143//! previous offset, it can implement natural scrolling where the offset is preserved until the
144//! selected item moves out of view.
145//!
146//! ## `WidgetRef` and `StatefulWidgetRef`
147//!
148//! The [`WidgetRef`] and [`StatefulWidgetRef`] traits were introduced in Ratatui 0.26.0 to enable
149//! rendering widgets by reference instead of consuming them. These traits address several important
150//! use cases that the original `Widget` and `StatefulWidget` traits couldn't handle elegantly.
151//!
152//! ```rust
153//! # use ratatui_core::{buffer::Buffer, layout::Rect};
154//! # #[cfg(feature = "unstable-widget-ref")]
155//! pub trait WidgetRef {
156//! fn render_ref(&self, area: Rect, buf: &mut Buffer);
157//! }
158//!
159//! # #[cfg(feature = "unstable-widget-ref")]
160//! pub trait StatefulWidgetRef {
161//! type State;
162//! fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
163//! }
164//! ```
165//!
166//! The reference-based traits solve several key problems:
167//!
168//! - **Reusability**: Widgets can be rendered multiple times without being consumed
169//! - **Collections**: Store heterogeneous widgets in collections like `Vec<Box<dyn WidgetRef>>`
170//! - **Borrowing**: Render widgets when you only have a reference, not ownership
171//! - **Efficiency**: Avoid unnecessary cloning or reconstruction for repeated renders
172//!
173//! These traits are currently **experimental** and gated behind the `unstable-widget-ref` feature
174//! flag. This means:
175//!
176//! - The API may change in future releases
177//! - Method names, signatures, or behavior might be adjusted based on community feedback
178//! - You must explicitly enable the feature flag to use them: `features = ["unstable-widget-ref"]`
179//! - They are not covered by semantic versioning guarantees until stabilized
180//!
181//! The traits are being evaluated for potential breaking changes and improvements. See the
182//! [tracking issue](https://github.com/ratatui/ratatui/issues/1287) for ongoing discussions and
183//! design considerations.
184//!
185//! # Rendering Widgets
186//!
187//! Widgets are typically rendered using the [`Frame`] type, which provides methods for rendering
188//! both consuming and reference-based widgets. These methods are usually called from the closure
189//! passed to [`Terminal::draw`].
190//!
191//! ## Rendering Consuming Widgets
192//!
193//! Most widgets in Ratatui are rendered using `Frame::render_widget()`, which consumes the widget
194//! when rendering. This is the standard approach for stateless widgets that don't need to persist
195//! data between frames.
196//!
197//! ```rust
198//! # use ratatui::{backend::TestBackend, Terminal};
199//! # use ratatui::widgets::Paragraph;
200//! # let backend = TestBackend::new(10, 3);
201//! # let mut terminal = Terminal::new(backend).unwrap();
202//! terminal.draw(|frame| {
203//! let widget = Paragraph::new("Hello, world!");
204//! frame.render_widget(widget, frame.area());
205//! });
206//! ```
207//!
208//! ## Rendering Widget References
209//!
210//! When you implement widgets on references (`Widget for &MyWidget`), you can render them directly
211//! using the same `Frame::render_widget()` method. This approach enables widget reuse without
212//! reconstruction and is the recommended pattern for new widgets.
213//!
214//! ```rust
215//! # use ratatui::{backend::TestBackend, Terminal};
216//! # use ratatui::widgets::{Block, Paragraph};
217//! # let backend = TestBackend::new(10, 3);
218//! # let mut terminal = Terminal::new(backend).unwrap();
219//! // Create the widget outside the draw closure
220//! let paragraph = Paragraph::new("Hello, world!").block(Block::bordered());
221//!
222//! terminal.draw(|frame| {
223//! // Widget can be rendered by reference without being consumed
224//! frame.render_widget(¶graph, frame.area());
225//! });
226//!
227//! // The widget can be used again in subsequent frames
228//! terminal.draw(|frame| {
229//! frame.render_widget(¶graph, frame.area());
230//! });
231//! ```
232//!
233//! ## Rendering Stateful Widgets
234//!
235//! Widgets that need to maintain state between frames use `Frame::render_stateful_widget()`. This
236//! method takes both the widget and a mutable reference to its state, allowing the widget to read
237//! and modify state during rendering (such as updating scroll positions or handling selections).
238//!
239//! ```rust
240//! # use ratatui::{backend::TestBackend, Terminal};
241//! # use ratatui::widgets::{List, ListItem, ListState};
242//! # let backend = TestBackend::new(10, 3);
243//! # let mut terminal = Terminal::new(backend).unwrap();
244//! let mut list_state = ListState::default();
245//! terminal.draw(|frame| {
246//! let items = vec![ListItem::new("Item 1"), ListItem::new("Item 2")];
247//! let list = List::new(items);
248//! frame.render_stateful_widget(list, frame.area(), &mut list_state);
249//! });
250//! ```
251//!
252//! ## Single Root Widget Pattern
253//!
254//! A common compositional pattern in Ratatui applications is to have a single root widget (often an
255//! `App` struct) that represents your entire application state. This widget is passed to
256//! `Frame::render_widget()`, and within its render method, it calls render on child widgets
257//! directly. This pattern provides a clean separation between your application logic and rendering
258//! code, and allows for easy composition of complex UIs from simpler components.
259//!
260//! ```rust
261//! # use ratatui_core::{buffer::Buffer, layout::Rect, widgets::Widget};
262//! # use ratatui::widgets::{Block, Paragraph};
263//! #[derive(Default)]
264//! struct App {
265//! should_quit: bool,
266//! }
267//!
268//! impl Widget for &App {
269//! fn render(self, area: Rect, buf: &mut Buffer) {
270//! // Render header
271//! let header = Paragraph::new("My App").block(Block::bordered());
272//! header.render(Rect::new(area.x, area.y, area.width, 3), buf);
273//!
274//! // Render main content
275//! let content = Paragraph::new("Main content area");
276//! content.render(
277//! Rect::new(area.x, area.y + 3, area.width, area.height - 3),
278//! buf,
279//! );
280//! }
281//! }
282//! ```
283//!
284//! # Authoring Custom Widgets
285//!
286//! When implementing custom widgets in Ratatui, you'll make fundamental decisions about how your
287//! widget manages state and how it's used by applications. Understanding these choices will help
288//! you create widgets that fit well into your application's architecture. Widget implementation
289//! involves several key architectural decisions that work together to determine how your widget
290//! behaves - these decisions are independent but complementary, allowing you to mix and match
291//! approaches based on your specific needs.
292//!
293//! **State Management**: The first choice is where state lives. Some widgets need to track
294//! information between renders - things like scroll positions, selections, or counters. You can
295//! either build this state into the widget itself (widget-owned state) or keep it separate and pass
296//! it in during rendering (external state).
297//!
298//! **Ownership Model**: The second choice is how the widget is consumed. Widgets can either be
299//! consumed when rendered (taking ownership) or work by reference (borrowing). Reference-based
300//! widgets can be stored and reused across multiple frames, while consuming widgets are created
301//! fresh each time.
302//!
303//! **`StatefulWidget` vs Mutable References**: When your widget needs state, you have two main
304//! approaches. The [`StatefulWidget`] trait represents the established pattern - it separates the
305//! widget from its state, allowing the application to own and manage the state independently. This
306//! is what you'll see in most existing Ratatui code and built-in widgets like [`List`] and
307//! [`Table`]. The mutable reference approach (`Widget for &mut MyWidget`) is newer and less common,
308//! but useful when the state is intrinsic to the widget's identity. With mutable references, the
309//! widget owns its state directly.
310//!
311//! The key question for state management is: "If I recreate this widget, should the state reset?"
312//! If yes (like a counter that should start at zero), use mutable references with widget-owned
313//! state. If no (like a list selection that should persist), use [`StatefulWidget`] with external
314//! state that the application manages.
315//!
316//! **Evolution and Current Recommendations**: Ratatui's patterns have evolved significantly. Before
317//! version 0.26.0, widgets were typically consuming (`Widget for MyWidget`) and created fresh each
318//! frame. Starting with 0.26.0, reference-based widgets (`Widget for &MyWidget`) became possible,
319//! allowing widgets to be stored and reused. You'll encounter both patterns in existing code, but
320//! reference-based implementations are now recommended for new widgets because they enable
321//! reusability and automatic [`WidgetRef`] support through blanket implementations.
322//!
323//! For new widgets, implement [`Widget`] or [`StatefulWidget`] on references to your widget types
324//! (`&MyWidget` or `&mut MyWidget`). This provides reusability and automatic [`WidgetRef`] support.
325//! You can optionally implement the consuming version for backward compatibility.
326//!
327//! ## State Management Patterns
328//!
329//! For a comprehensive exploration of different approaches to handling both mutable and immutable
330//! state in widgets, see the [state examples] in the Ratatui repository. These examples demonstrate
331//! various patterns including:
332//!
333//! **Immutable State Patterns** (recommended for most use cases):
334//! - Function-based immutable state (`fn render(frame: &mut Frame, area: Rect, state: &State)`)
335//! - Shared reference widgets (`impl Widget for &MyWidget`)
336//! - Consuming widgets (`impl Widget for MyWidget`)
337//!
338//! **Mutable State Patterns** (for widgets that modify state during rendering):
339//! - Function-based mutable state (`fn render(frame: &mut Frame, area: Rect, state: &mut State)`)
340//! - Mutable widget references (`impl Widget for &mut MyWidget`)
341//! - `StatefulWidget` pattern (`impl StatefulWidget for MyWidget`)
342//! - Custom component traits (`trait MyComponent { fn render(&mut self, frame: &mut Frame, area:
343//! Rect) }`)
344//! - Interior mutability with `RefCell` (`struct MyWidget { state: Rc<RefCell<State>> }`)
345//! - Lifetime-based mutable references (`struct MyWidget<'a> { state: &'a mut State }`)
346//! - Nested widget hierarchies (compositions with owned or external state)
347//!
348//! Each pattern has different trade-offs in terms of complexity, performance, and architectural
349//! fit, making them suitable for different use cases and application designs. For most
350//! applications, start with immutable patterns as they are simpler to reason about and less prone
351//! to borrowing issues.
352//!
353//! [state examples]: https://github.com/ratatui/ratatui/tree/main/examples/concepts/state
354//!
355//! ## Shared References (`&Widget`)
356//!
357//! The recommended pattern for most new widgets implements [`Widget`] on a shared reference,
358//! allowing the widget to be rendered multiple times without being consumed. This approach is ideal
359//! for immutable widgets that don't need to modify their internal state during rendering, and it's
360//! the most common pattern you should use for new widgets.
361//!
362//! ```rust
363//! # use ratatui_core::{buffer::Buffer, layout::Rect, text::Line, widgets::Widget};
364//! struct MyWidget {
365//! content: String,
366//! }
367//!
368//! impl Widget for &MyWidget {
369//! fn render(self, area: Rect, buf: &mut Buffer) {
370//! Line::raw(&self.content).render(area, buf);
371//! }
372//! }
373//! ```
374//!
375//! This automatically provides [`WidgetRef`] support through blanket implementations and enables
376//! widgets to be stored and reused across frames without reconstruction. For most use cases where
377//! the widget doesn't need to change its internal state during rendering, this is the best choice.
378//!
379//! ## Mutable References (`&mut Widget`)
380//!
381//! For widgets that need to modify their internal state during rendering, implement [`Widget`] on a
382//! mutable reference. This is a newer pattern that's less common but useful when the state is
383//! intrinsic to the widget's identity and behavior. Use this pattern when the widget should own and
384//! manage its state directly, rather than having external state passed in.
385//!
386//! ```rust
387//! # use ratatui_core::{buffer::Buffer, layout::Rect, text::Line, widgets::Widget};
388//! struct CounterWidget {
389//! count: u32, // This state belongs to the widget
390//! label: String,
391//! }
392//!
393//! impl Widget for &mut CounterWidget {
394//! fn render(self, area: Rect, buf: &mut Buffer) {
395//! self.count += 1; // State changes as part of rendering behavior
396//! let text = format!("{label}: {count}", label = self.label, count = self.count);
397//! Line::raw(text).render(area, buf);
398//! }
399//! }
400//! ```
401//!
402//! This pattern works well when the widget owns its state and the state is part of the widget's
403//! identity. It's ideal for counters, animations, cursors, progress indicators, or other
404//! widget-specific behavior where the state should reset when you create a new widget instance.
405//!
406//! ## Consuming Widget Implementation
407//!
408//! The consuming widget pattern was the original approach in Ratatui and remains very common in
409//! existing codebases. You'll encounter this pattern frequently when reading examples and community
410//! code. Widgets implementing this pattern take ownership when rendered, which means they're
411//! consumed on each use. While not the recommended approach for new widgets, it's still useful to
412//! understand this pattern for compatibility and when working with existing code.
413//!
414//! ```rust
415//! # use ratatui_core::{buffer::Buffer, layout::Rect, style::Modifier, text::{Line, Span}, widgets::Widget};
416//! struct GreetingWidget {
417//! name: String,
418//! }
419//!
420//! impl Widget for GreetingWidget {
421//! fn render(self, area: Rect, buf: &mut Buffer) {
422//! let hello = Span::raw("Hello, ");
423//! let name = Span::styled(self.name, Modifier::BOLD);
424//! let line = Line::from(vec![hello, name]);
425//! line.render(area, buf);
426//! }
427//! }
428//! ```
429//!
430//! This approach is simpler and works well for widgets created fresh each frame, but it means the
431//! widget cannot be reused. Before reference-based widgets were introduced in version 0.26.0, this
432//! was the standard pattern, and it's still valid for simple use cases or when following existing
433//! code patterns.
434//!
435//! The easiest way to implement this pattern when you have a reference-based widget is to implement
436//! the consuming version on the owned type, which can then call the reference-based implementation:
437//!
438//! ```rust
439//! # use ratatui_core::{buffer::Buffer, layout::Rect, widgets::Widget};
440//! # struct GreetingWidget;
441//! # impl Widget for &GreetingWidget {
442//! # fn render(self, area: Rect, buf: &mut Buffer) {}
443//! # }
444//! impl Widget for GreetingWidget {
445//! fn render(self, area: Rect, buf: &mut Buffer) {
446//! // Call the reference-based implementation
447//! (&self).render(area, buf);
448//! }
449//! }
450//! ``````
451//!
452//! ## `StatefulWidget` Implementation
453//!
454//! When your widget needs to work with external state - data that exists independently of the
455//! widget and should persist between widget instances - implement [`StatefulWidget`]. This is the
456//! established pattern used by built-in widgets like [`List`] and [`Table`], where the widget
457//! configuration is separate from application state like selections or scroll positions.
458//!
459//! Like [`Widget`], you can implement [`StatefulWidget`] on references to allow reuse, though it's
460//! more common to see this trait implemented on owned types which are consumed during rendering.
461//!
462//! ```rust
463//! # use ratatui_core::{buffer::Buffer, layout::Rect, text::Line, widgets::{StatefulWidget, Widget}};
464//! struct ListView {
465//! items: Vec<String>,
466//! }
467//!
468//! #[derive(Default)]
469//! struct ListState {
470//! selected: Option<usize>, // This is application state
471//! scroll_offset: usize,
472//! }
473//!
474//! impl StatefulWidget for ListView {
475//! type State = ListState;
476//!
477//! fn render(self, area: Rect, buf: &mut Buffer, state: &mut ListState) {
478//! // Render based on external state, possibly modify for scrolling
479//! let display_text = state
480//! .selected
481//! .and_then(|i| self.items.get(i))
482//! .map_or("None selected", |s| s.as_str());
483//! Line::raw(display_text).render(area, buf);
484//! }
485//! }
486//! ```
487//!
488//! This pattern is ideal for selections, scroll positions, form data, or any state that should
489//! persist between renders or be shared across your application. The state exists independently of
490//! the widget, so recreating the widget doesn't reset the state.
491//!
492//! ### Automatic `WidgetRef` Support
493//!
494//! When you implement `Widget for &MyWidget`, you automatically get [`WidgetRef`] support without
495//! any additional code. Ratatui provides blanket implementations that automatically implement these
496//! traits for any type that implements [`Widget`] or [`StatefulWidget`] on a reference. This means
497//! that implementing `Widget for &MyWidget` gives you both the standard widget functionality and
498//! the unstable [`WidgetRef`] capabilities for free.
499//!
500//! ## Manual `WidgetRef` Implementation (Advanced)
501//!
502//! Manual implementation of [`WidgetRef`] or [`StatefulWidgetRef`] is only necessary when you need
503//! to store widgets as trait objects (`Box<dyn WidgetRef>`) or when you want a different API than
504//! the reference-based [`Widget`] implementation provides. In most cases, the automatic
505//! implementation via blanket implementations is sufficient.
506//!
507//! These traits enable several benefits:
508//! - Widgets can be stored and rendered multiple times without reconstruction
509//! - Collections of widgets with different types can be stored using `Box<dyn WidgetRef>`
510//! - Avoids the consumption model while maintaining backward compatibility
511//!
512//! Manual implementation is only needed when you want to use trait objects or need a different API
513//! than the reference-based [`Widget`] implementation:
514//!
515//! ```rust
516//! # #[cfg(feature = "unstable-widget-ref")] {
517//! # use ratatui_core::{buffer::Buffer, layout::Rect, style::Modifier, text::{Line, Span}};
518//! # use ratatui::widgets::{Widget, WidgetRef};
519//! struct GreetingWidget {
520//! name: String,
521//! }
522//!
523//! // Manual WidgetRef implementation (usually not needed)
524//! impl WidgetRef for GreetingWidget {
525//! fn render_ref(&self, area: Rect, buf: &mut Buffer) {
526//! let hello = Span::raw("Hello, ");
527//! let name = Span::styled(&self.name, Modifier::BOLD);
528//! let line = Line::from(vec![hello, name]);
529//! line.render(area, buf);
530//! }
531//! }
532//!
533//! // For backward compatibility
534//! impl Widget for GreetingWidget {
535//! fn render(self, area: Rect, buf: &mut Buffer) {
536//! self.render_ref(area, buf);
537//! }
538//! }
539//! # }
540//! ```
541//!
542//! This pattern allows the widget to be stored and rendered multiple times:
543//!
544//! ```rust
545//! # #[cfg(feature = "unstable-widget-ref")] {
546//! # use ratatui_core::{buffer::Buffer, layout::Rect};
547//! # use ratatui::widgets::WidgetRef;
548//! # struct GreetingWidget { name: String }
549//! # impl WidgetRef for GreetingWidget {
550//! # fn render_ref(&self, area: Rect, buf: &mut Buffer) {}
551//! # }
552//! struct App {
553//! greeting: GreetingWidget,
554//! }
555//!
556//! // The widget can be rendered multiple times without reconstruction
557//! fn render_app(app: &App, area: Rect, buf: &mut Buffer) {
558//! app.greeting.render_ref(area, buf);
559//! }
560//! # }
561//! ```
562//!
563//! ### Using Trait Objects for Dynamic Collections
564//!
565//! The main benefit of manual [`WidgetRef`] implementation is the ability to create collections of
566//! different widget types using trait objects. This is useful when you need to store widgets with
567//! types that are not known at compile time:
568//!
569//! ```rust
570//! # #[cfg(feature = "unstable-widget-ref")] {
571//! # use ratatui_core::{buffer::Buffer, layout::Rect};
572//! # use ratatui::widgets::WidgetRef;
573//! # struct Greeting;
574//! # struct Farewell;
575//! # impl WidgetRef for Greeting { fn render_ref(&self, area: Rect, buf: &mut Buffer) {} }
576//! # impl WidgetRef for Farewell { fn render_ref(&self, area: Rect, buf: &mut Buffer) {} }
577//! # let area = Rect::new(0, 0, 10, 3);
578//! # let mut buf = &mut Buffer::empty(area);
579//! let widgets: Vec<Box<dyn WidgetRef>> = vec![Box::new(Greeting), Box::new(Farewell)];
580//!
581//! for widget in &widgets {
582//! widget.render_ref(area, buf);
583//! }
584//! # }
585//! ```
586//!
587//! However, if you implement `Widget for &MyWidget`, you can achieve similar functionality by
588//! storing references or using the automatic [`WidgetRef`] implementation without needing to
589//! manually implement the trait.
590//!
591//! ## Authoring Custom Widget Libraries
592//!
593//! When creating a library of custom widgets for distribution, there are specific considerations
594//! that will make your library more compatible and accessible to a wider range of users. Following
595//! these guidelines will help ensure your widget library works well in various environments and
596//! can be easily integrated into different types of applications.
597//!
598//! ### Depend on `ratatui_core`
599//!
600//! For widget libraries, depend on [`ratatui-core`] instead of the full `ratatui` crate. This
601//! provides all the essential types and traits needed for widget development while avoiding
602//! unnecessary dependencies on backends and other components that widget libraries don't need.
603//!
604//! This approach offers several key advantages for both library authors and users:
605//!
606//! - **Lighter dependencies**: Users don't pull in backend code they don't need, keeping their
607//! dependency tree smaller and more focused
608//! - **Better compile times**: Fewer dependencies mean faster builds for both development and
609//! end-user projects
610//! - **Future-proofing**: Your library remains compatible as Ratatui evolves its architecture,
611//! since core widget functionality is stable across versions
612//!
613//! ### Make Your Crate `no_std` Compatible
614//!
615//! For maximum compatibility, especially in embedded environments, consider making your widget
616//! library `no_std` compatible. This is often easier than you might expect and broadens the range
617//! of projects that can use your widgets.
618//!
619//! For more detail on advantages of this, maintenance tips and feature flags, see the
620//! [no-std concept guide].
621//!
622//! To implement `no_std` compatibility, add the `#![no_std]` attribute at the top of your `lib.rs`.
623//! When working in a `no_std` environment, you'll need to make a few adjustments:
624//!
625//! - Use `core::` instead of `std::` for basic functionality
626//! - Add `extern crate alloc;` to access allocation types
627//! - Use `alloc::` for heap-allocated types like `String`, `Vec`, and `Box`
628//!
629//! Here's a complete example of a `no_std` compatible widget:
630//!
631//! ```ignore
632//! #![no_std]
633//!
634//! extern crate alloc;
635//!
636//! use alloc::string::String;
637//!
638//! use ratatui_core::buffer::Buffer;
639//! use ratatui_core::layout::Rect;
640//! use ratatui_core::text::Line;
641//! use ratatui_core::widgets::Widget;
642//!
643//! struct MyWidget {
644//! content: String,
645//! }
646//!
647//! impl Widget for &MyWidget {
648//! fn render(self, area: Rect, buf: &mut Buffer) {
649//! Line::raw(&self.content).render(area, buf);
650//! }
651//! }
652//! ```
653//!
654//! The benefits of `no_std` compatibility include:
655//!
656//! - **Broader compatibility**: Your widgets work seamlessly in embedded environments and other
657//! `no_std` contexts where standard library functionality isn't available
658//! - **Easy to adopt**: Even if you haven't worked with `no_std` development before, the changes
659//! are typically minimal for widget libraries. Most widget logic involves basic data manipulation
660//! and rendering operations that work well within `no_std` constraints, making this compatibility
661//! straightforward to implement
662//!
663//! [`ratatui-core`]: https://crates.io/crates/ratatui-core
664//! [no-std concept guide]: https://ratatui.rs/concepts/no-std/
665
666pub use ratatui_core::widgets::{StatefulWidget, Widget};
667pub use ratatui_widgets::barchart::{Bar, BarChart, BarGroup};
668pub use ratatui_widgets::block::{Block, BlockExt, Padding, TitlePosition};
669pub use ratatui_widgets::borders::{BorderType, Borders};
670#[cfg(feature = "widget-calendar")]
671pub use ratatui_widgets::calendar;
672pub use ratatui_widgets::canvas;
673pub use ratatui_widgets::chart::{Axis, Chart, Dataset, GraphType, LegendPosition};
674pub use ratatui_widgets::clear::Clear;
675pub use ratatui_widgets::gauge::{Gauge, LineGauge};
676pub use ratatui_widgets::list::{List, ListDirection, ListItem, ListState};
677pub use ratatui_widgets::logo::{RatatuiLogo, Size as RatatuiLogoSize};
678pub use ratatui_widgets::mascot::{MascotEyeColor, RatatuiMascot};
679pub use ratatui_widgets::paragraph::{Paragraph, Wrap};
680pub use ratatui_widgets::scrollbar::{
681 ScrollDirection, Scrollbar, ScrollbarOrientation, ScrollbarState,
682};
683pub use ratatui_widgets::sparkline::{RenderDirection, Sparkline, SparklineBar};
684pub use ratatui_widgets::table::{Cell, HighlightSpacing, Row, Table, TableState};
685pub use ratatui_widgets::tabs::Tabs;
686#[instability::unstable(feature = "widget-ref")]
687pub use {stateful_widget_ref::StatefulWidgetRef, widget_ref::WidgetRef};
688
689mod stateful_widget_ref;
690mod widget_ref;
691
692use ratatui_core::layout::Rect;
693
694/// Extension trait for [`Frame`] that provides methods to render [`WidgetRef`] and
695/// [`StatefulWidgetRef`] to the current buffer.
696#[instability::unstable(feature = "widget-ref")]
697pub trait FrameExt {
698 /// Render a [`WidgetRef`] to the current buffer using [`WidgetRef::render_ref`].
699 ///
700 /// Usually the area argument is the size of the current frame or a sub-area of the current
701 /// frame (which can be obtained using [`Layout`] to split the total area).
702 ///
703 /// # Example
704 ///
705 /// ```rust
706 /// # #[cfg(feature = "unstable-widget-ref")] {
707 /// # use ratatui::{backend::TestBackend, Terminal};
708 /// # let backend = TestBackend::new(5, 5);
709 /// # let mut terminal = Terminal::new(backend).unwrap();
710 /// # let mut frame = terminal.get_frame();
711 /// use ratatui::layout::Rect;
712 /// use ratatui::widgets::{Block, FrameExt};
713 ///
714 /// let block = Block::new();
715 /// let area = Rect::new(0, 0, 5, 5);
716 /// frame.render_widget_ref(&block, area);
717 /// # }
718 /// ```
719 ///
720 /// [`Layout`]: crate::layout::Layout
721 fn render_widget_ref<W: WidgetRef>(&mut self, widget: W, area: Rect);
722
723 /// Render a [`StatefulWidgetRef`] to the current buffer using
724 /// [`StatefulWidgetRef::render_ref`].
725 ///
726 /// Usually the area argument is the size of the current frame or a sub-area of the current
727 /// frame (which can be obtained using [`Layout`] to split the total area).
728 ///
729 /// The last argument should be an instance of the [`StatefulWidgetRef::State`] associated to
730 /// the given [`StatefulWidgetRef`].
731 ///
732 /// # Example
733 ///
734 /// ```rust
735 /// # #[cfg(feature = "unstable-widget-ref")] {
736 /// # use ratatui::{backend::TestBackend, Terminal};
737 /// # let backend = TestBackend::new(5, 5);
738 /// # let mut terminal = Terminal::new(backend).unwrap();
739 /// # let mut frame = terminal.get_frame();
740 /// use ratatui::layout::Rect;
741 /// use ratatui::widgets::{FrameExt, List, ListItem, ListState};
742 ///
743 /// let mut state = ListState::default().with_selected(Some(1));
744 /// let list = List::new(vec![ListItem::new("Item 1"), ListItem::new("Item 2")]);
745 /// let area = Rect::new(0, 0, 5, 5);
746 /// frame.render_stateful_widget_ref(&list, area, &mut state);
747 /// # }
748 /// ```
749 /// [`Layout`]: crate::layout::Layout
750 fn render_stateful_widget_ref<W>(&mut self, widget: W, area: Rect, state: &mut W::State)
751 where
752 W: StatefulWidgetRef;
753}
754
755#[cfg(feature = "unstable-widget-ref")]
756impl FrameExt for ratatui_core::terminal::Frame<'_> {
757 fn render_widget_ref<W: WidgetRef>(&mut self, widget: W, area: Rect) {
758 widget.render_ref(area, self.buffer_mut());
759 }
760
761 fn render_stateful_widget_ref<W>(&mut self, widget: W, area: Rect, state: &mut W::State)
762 where
763 W: StatefulWidgetRef,
764 {
765 widget.render_ref(area, self.buffer_mut(), state);
766 }
767}