8 releases

new 0.3.0 Apr 24, 2024
0.2.4 Apr 1, 2024
0.2.3 Mar 12, 2024
0.2.2 Jan 2, 2024
0.1.1 Dec 31, 2023

#584 in Command-line interface

Download history 1/week @ 2024-01-05 1/week @ 2024-02-23 1/week @ 2024-03-01 110/week @ 2024-03-08 17/week @ 2024-03-15 1/week @ 2024-03-22 148/week @ 2024-03-29 81/week @ 2024-04-05 206/week @ 2024-04-12 122/week @ 2024-04-19

557 downloads per month

MIT license

16KB
186 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

Dependencies

~6–12MB
~121K SLoC