tui-menu

Crates.iotui-menu
lib.rstui-menu
version
sourcesrc
created_at2022-11-29 00:47:56.013862
updated_at2024-12-09 23:10:05.224927
descriptionA menu widget for Ratatui
homepage
repositoryhttps://github.com/shuoli84/tui-menu
max_upload_size
id724930
Cargo.toml error:TOML parse error at line 17, column 1 | 17 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include`
size0
MobileCoin Eng (github:mobilecoinofficial:mobilecoin-eng)

documentation

README

tui-menu

A menu widget for Ratatui.

Demo

Features

  • Sub menu groups.
  • Intuitive movement.
  • Item's data is generic as long as it Cloneable.

Try

cargo run --example basic

Example

take a look at examples/basic.rs

Render

// menu should be draw at last, so it can stay on top of other content
let menu = Menu::new();
frame.render_stateful_widget(menu, chunks[0], &mut app.menu);

Create nested menu tree

Note: MenuItems can be created from any type that implements Clone. Using an enum is just one option which can work. You could use strings or your own state types.

#[derive(Debug, Clone)]
enum Action {
    FileNew,
    FileOpen,
    FileOpenRecent(String),
    FileSaveAs,
    Exit,
    EditCopy,
    EditCut,
    EditPaste,
    AboutAuthor,
    AboutHelp,
}

let menu = MenuState::new(vec![
    MenuItem::group(
        "File",
        vec![
            MenuItem::item("New", Action::FileNew),
            MenuItem::item("Open", Action::FileOpen),
            MenuItem::group(
                "Open recent",
                ["file_1.txt", "file_2.txt"]
                    .iter()
                    .map(|&f| MenuItem::item(f, Action::FileOpenRecent(f.into())))
                    .collect(),
            ),
            MenuItem::item("Save as", Action::FileSaveAs),
            MenuItem::item("Exit", Action::Exit),
        ],
    ),
    MenuItem::group(
        "Edit",
        vec![
            MenuItem::item("Copy", Action::EditCopy),
            MenuItem::item("Cut", Action::EditCut),
            MenuItem::item("Paste", Action::EditPaste),
        ],
    ),
    MenuItem::group(
        "About",
        vec![
            MenuItem::item("Author", Action::AboutAuthor),
            MenuItem::item("Help", Action::AboutHelp),
        ],
    ),
]),

Consume events

for e in menu.drain_events() {
    match e {
        MenuEvent::Selected(item) => match item {
            Action::Exit => {
                return Ok(());
            }
            Action::FileNew => {
                self.content.clear();
            }
            Action::FileOpenRecent(file) => {
                self.content = format!("content of {file}");
            }
            action => {
                self.content = format!("{action:?} not implemented");
            }
        },
    }
    // close the menu once the event has been handled.
    menu.reset();
}
Commit count: 32

cargo fmt