tui-popup 0.7.1

A simple popup for ratatui
Documentation

tui-popup

A popup widget for Ratatui

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

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

Example

use ratatui::style::{Style, Stylize};
use ratatui::Frame;
use tui_popup::Popup;

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

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 crossterm::event::{KeyCode, KeyEvent};
use ratatui::style::{Style, Stylize};
use ratatui::Frame;
use tui_popup::{Popup, PopupState};

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

fn handle_key(event: KeyEvent, state: &mut PopupState) {
    match event.code {
        KeyCode::Up => state.move_up(1),
        KeyCode::Down => state.move_down(1),
        KeyCode::Left => state.move_left(1),
        KeyCode::Right => state.move_right(1),
        _ => {}
    }
}

The popup can automatically handle being moved around by the mouse, by passing in the column and row of mouse up, down, or drag events.

use crossterm::event::{Event, MouseButton, MouseEventKind};
use tui_popup::PopupState;

fn handle_mouse(event: Event, popup_state: &mut PopupState) {
    if let Event::Mouse(event) = event {
        match event.kind {
            MouseEventKind::Down(MouseButton::Left) => {
                popup_state.mouse_down(event.column, event.row)
            }
            MouseEventKind::Up(MouseButton::Left) => {
                popup_state.mouse_up(event.column, event.row);
            }
            MouseEventKind::Drag(MouseButton::Left) => {
                popup_state.mouse_drag(event.column, event.row);
            }
            _ => {}
        }
    }
}

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

use ratatui::prelude::*;
use ratatui::text::{Span, Text};
use ratatui::widgets::Paragraph;
use tui_popup::{KnownSizeWrapper, Popup};

fn render_scrollable_popup(frame: &mut Frame, scroll: u16) {
    let lines: Text = (0..10).map(|i| Span::raw(format!("Line {}", i))).collect();
    let paragraph = Paragraph::new(lines).scroll((scroll, 0));
    let sized_paragraph = KnownSizeWrapper {
        inner: paragraph,
        width: 21,
        height: 5,
    };
    let popup = Popup::new(sized_paragraph)
        .title("scroll: ↑/↓ quit: Esc")
        .style(Style::new().white().on_blue());
    frame.render_widget(popup, frame.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.