17 unstable releases (3 breaking)

new 0.4.4 Jul 25, 2024
0.3.4 Jul 7, 2024
0.2.3 Mar 12, 2024
0.2.1 Dec 31, 2023

#593 in Command-line interface

Download history 89/week @ 2024-04-04 206/week @ 2024-04-11 98/week @ 2024-04-18 157/week @ 2024-04-25 137/week @ 2024-05-02 160/week @ 2024-05-09 629/week @ 2024-05-16 262/week @ 2024-05-23 116/week @ 2024-05-30 58/week @ 2024-06-06 55/week @ 2024-06-13 220/week @ 2024-06-20 92/week @ 2024-06-27 302/week @ 2024-07-04 295/week @ 2024-07-11 128/week @ 2024-07-18

859 downloads per month
Used in 4 crates

MIT/Apache

19KB
206 lines

tui-popup

Crates.io badge License badge Docs.rs badge Deps.rs badge Discord badge

A popup widget for Ratatui

The popup widget is a simple widget that renders a popup in the center of the screen.

Example

use ratatui::prelude::*;
use tui_popup::Popup;

fn render_popup(frame: &mut Frame) {
    let popup = Popup::new("tui-popup demo", "Press any key to exit")
       .style(Style::new().white().on_blue());
    frame.render_widget(&popup, frame.size());
}

demo

State

The widget supports storing the position of the popup in PopupState. This is experimental and the exact api for this will likely change.

use ratatui::prelude::*;
use tui_popup::Popup;

fn render_stateful_popup(frame: &mut Frame, popup_state: &mut PopupState) {
    let popup = Popup::new("tui-popup demo", "Press any key to exit")
       .style(Style::new().white().on_blue());
    frame.render_stateful_widget_ref(popup, frame.size(), popup_state);
}

fn move_up(popup_state: &mut PopupState) {
    popup_state.move_by(0, -1);
}

The popup can automatically handle being moved around by the mouse, by passing in the column and row of Mouse Up / Down / Drag events. The current implemntation of this checks whether the click is in the first row of the popup, otherwise ignores the event.

match event.read()? {
    Event::Mouse(event) => {
        match event.kind {
            event::MouseEventKind::Down(MouseButton::Left) => {
                popup_state.mouse_down(event.column, event.row)
            }
            event::MouseEventKind::Up(MouseButton::Left) => {
                popup_state.mouse_up(event.column, event.row);
            }
            event::MouseEventKind::Drag(MouseButton::Left) => {
                popup_state.mouse_drag(event.column, event.row);
            }
            _ => {}
        };
    }
    // -- snip --
}

state demo

The popup also supports rendering arbitrary widgets by implementing SizedWidgetRef (or wrapping them with the provided SizedWrapper). This makes it possible to support wrapping and scrolling in using a Paragraph widget, or scrolling any amount of widgets using tui-scrollview.

let lines: Text = (0..10).map(|i| Span::raw(format!("Line {}", i))).collect();
let paragraph = Paragraph::new(lines).scroll((scroll, 0));
let sized_paragraph = SizedWrapper {
    inner: paragraph,
    width: 21,
    height: 5,
};
let popup = Popup::new("scroll: ↑/↓ quit: Esc", sized_paragraph)
    .style(Style::new().white().on_blue());
frame.render_widget_ref(popup, area);

paragraph example

Features

  • automatically centers
  • automatically sizes to content
  • style popup
  • move the popup (using state)
  • handle mouse events for dragging
  • move to position
  • resize
  • set border set / style
  • add close button
  • add nicer styling of header etc.
  • configure text wrapping in body to conform to a specific size

License

Copyright (c) Josh McKinney

This project is licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

See CONTRIBUTING.md.

Dependencies

~6–12MB
~114K SLoC