tui_popup/lib.rs
1//! A [Ratatui] widget to show a snappy popup overlay. Part of the [tui-widgets] suite by [Joshka].
2//!
3//! 
4//!
5//! The popup widget is a simple widget that renders a popup in the center of the screen.
6//!
7//! [![Crate badge]][Crate]
8//! [![Docs Badge]][Docs]
9//! [![Deps Badge]][Dependency Status]
10//! [![License Badge]][License]
11//! [![Coverage Badge]][Coverage]
12//! [![Discord Badge]][Ratatui Discord]
13//!
14//! [GitHub Repository] · [API Docs] · [Examples] · [Changelog] · [Contributing]
15//!
16//! # Installation
17//!
18//! ```shell
19//! cargo add tui-popup
20//! ```
21//!
22//! # Usage
23//!
24//! Build a `Popup` with content and render it over your frame.
25//!
26//! ```rust
27//! use ratatui::style::{Style, Stylize};
28//! use ratatui::Frame;
29//! use tui_popup::Popup;
30//!
31//! fn render_popup(frame: &mut Frame) {
32//! let popup = Popup::new("Press any key to exit")
33//! .title("tui-popup demo")
34//! .style(Style::new().white().on_blue());
35//! frame.render_widget(popup, frame.area());
36//! }
37//! ```
38//!
39//! # State
40//!
41//! The widget supports storing the position of the popup in `PopupState`. This is experimental and
42//! the exact API for this will likely change.
43//!
44//! ```rust
45//! # #[cfg(feature = "crossterm")]
46//! # {
47//! use crossterm::event::{KeyCode, KeyEvent};
48//! use ratatui::style::{Style, Stylize};
49//! use ratatui::Frame;
50//! use tui_popup::{Popup, PopupState};
51//!
52//! fn render_stateful_popup(frame: &mut Frame, popup_state: &mut PopupState) {
53//! let popup = Popup::new("Press any key to exit")
54//! .title("tui-popup demo")
55//! .style(Style::new().white().on_blue());
56//! frame.render_stateful_widget(popup, frame.area(), popup_state);
57//! }
58//!
59//! fn handle_key(event: KeyEvent, state: &mut PopupState) {
60//! match event.code {
61//! KeyCode::Up => state.move_up(1),
62//! KeyCode::Down => state.move_down(1),
63//! KeyCode::Left => state.move_left(1),
64//! KeyCode::Right => state.move_right(1),
65//! _ => {}
66//! }
67//! }
68//! # }
69//! ```
70//!
71//! The popup can automatically handle being moved around by the mouse, by passing in the column and
72//! row of mouse up, down, or drag events.
73//!
74//! ```rust
75//! # #[cfg(feature = "crossterm")]
76//! # {
77//! use crossterm::event::{Event, MouseButton, MouseEventKind};
78//! use tui_popup::PopupState;
79//!
80//! fn handle_mouse(event: Event, popup_state: &mut PopupState) {
81//! if let Event::Mouse(event) = event {
82//! match event.kind {
83//! MouseEventKind::Down(MouseButton::Left) => {
84//! popup_state.mouse_down(event.column, event.row)
85//! }
86//! MouseEventKind::Up(MouseButton::Left) => {
87//! popup_state.mouse_up(event.column, event.row);
88//! }
89//! MouseEventKind::Drag(MouseButton::Left) => {
90//! popup_state.mouse_drag(event.column, event.row);
91//! }
92//! _ => {}
93//! }
94//! }
95//! }
96//! # }
97//! ```
98//!
99//! The popup also supports rendering arbitrary widgets by implementing [`KnownSize`] (or wrapping
100//! them with [`KnownSizeWrapper`]). This makes it possible to support wrapping and scrolling in a
101//! `Paragraph` widget, or scrolling any amount of widgets using [tui-scrollview].
102//!
103//! ```rust
104//! use ratatui::prelude::*;
105//! use ratatui::text::{Span, Text};
106//! use ratatui::widgets::Paragraph;
107//! use tui_popup::{KnownSizeWrapper, Popup};
108//!
109//! fn render_scrollable_popup(frame: &mut Frame, scroll: u16) {
110//! let lines: Text = (0..10).map(|i| Span::raw(format!("Line {}", i))).collect();
111//! let paragraph = Paragraph::new(lines).scroll((scroll, 0));
112//! let sized_paragraph = KnownSizeWrapper {
113//! inner: paragraph,
114//! width: 21,
115//! height: 5,
116//! };
117//! let popup = Popup::new(sized_paragraph)
118//! .title("scroll: ↑/↓ quit: Esc")
119//! .style(Style::new().white().on_blue());
120//! frame.render_widget(popup, frame.area());
121//! }
122//! ```
123//!
124//! 
125//!
126//! # Features
127//!
128//! - [x] automatically centers
129//! - [x] automatically sizes to content
130//! - [x] style popup
131//! - [x] move the popup (using state)
132//! - [x] handle mouse events for dragging
133//! - [x] move to position
134//! - [ ] resize
135//! - [ ] set border set / style
136//! - [ ] add close button
137//! - [ ] add nicer styling of header etc.
138//! - [ ] configure text wrapping in body to conform to a specific size
139//!
140//! # More widgets
141//!
142//! For the full suite of widgets, see [tui-widgets].
143//!
144//!
145//! [Crate]: https://crates.io/crates/tui-popup
146//! [Docs]: https://docs.rs/tui-popup/
147//! [Dependency Status]: https://deps.rs/repo/github/joshka/tui-widgets
148//! [Coverage]: https://app.codecov.io/gh/joshka/tui-widgets
149//! [Ratatui Discord]: https://discord.gg/pMCEU9hNEj
150//! [Crate badge]: https://img.shields.io/crates/v/tui-popup?logo=rust&style=flat
151//! [Docs Badge]: https://img.shields.io/docsrs/tui-popup?logo=rust&style=flat
152//! [Deps Badge]: https://deps.rs/repo/github/joshka/tui-widgets/status.svg?style=flat
153//! [License Badge]: https://img.shields.io/crates/l/tui-popup?style=flat
154//! [License]: https://github.com/joshka/tui-widgets/blob/main/LICENSE-MIT
155//! [Coverage Badge]:
156//! https://img.shields.io/codecov/c/github/joshka/tui-widgets?logo=codecov&style=flat
157//! [Discord Badge]: https://img.shields.io/discord/1070692720437383208?logo=discord&style=flat
158//!
159//! [GitHub Repository]: https://github.com/joshka/tui-widgets
160//! [API Docs]: https://docs.rs/tui-popup/
161//! [Examples]: https://github.com/joshka/tui-widgets/tree/main/tui-popup/examples
162//! [Changelog]: https://github.com/joshka/tui-widgets/blob/main/tui-popup/CHANGELOG.md
163//! [Contributing]: https://github.com/joshka/tui-widgets/blob/main/CONTRIBUTING.md
164//! [KnownSize]: https://docs.rs/tui-popup/latest/tui_popup/trait.KnownSize.html
165//! [KnownSizeWrapper]: https://docs.rs/tui-popup/latest/tui_popup/struct.KnownSizeWrapper.html
166//! [tui-scrollview]: https://crates.io/crates/tui-scrollview
167//!
168//! [Joshka]: https://github.com/joshka
169//! [tui-widgets]: https://crates.io/crates/tui-widgets
170#![cfg_attr(docsrs, doc = "\n# Feature flags\n")]
171#![cfg_attr(docsrs, doc = document_features::document_features!())]
172
173mod known_size;
174mod known_size_wrapper;
175mod popup;
176mod popup_state;
177
178pub use crate::known_size::KnownSize;
179pub use crate::known_size_wrapper::KnownSizeWrapper;
180pub use crate::popup::Popup;
181pub use crate::popup_state::{DragState, PopupState};