#tui #declarative-ui #terminal-interface #cli #hook #output #element

iocraft

Create beautifully crafted CLI programs and text output with a declarative React-like Rust API

10 releases

0.3.2 Oct 4, 2024
0.3.1 Sep 30, 2024
0.2.3 Sep 27, 2024
0.1.2 Sep 24, 2024

#80 in GUI

Download history 745/week @ 2024-09-22 593/week @ 2024-09-29 46/week @ 2024-10-06

1,384 downloads per month

MIT/Apache

190KB
4.5K SLoC

iocraft

✨ A Rust crate for beautiful, artisanally crafted CLIs, TUIs, and text-based IO. ✨

GitHub Actions Workflow Status docs.rs crates.io Codecov

iocraft is a library for crafting beautiful text output and interfaces for the terminal or logs. It allows you to easily build complex layouts and interactive elements using a declarative API.

Features

  • Define your UI using a clean, highly readable syntax.
  • Organize your UI using flexbox layouts powered by taffy.
  • Output colored and styled UIs to the terminal or ASCII output anywhere else.
  • Create animated or interactive elements with event handling and hooks.
  • Build fullscreen terminal applications with ease.
  • Pass props and context by reference to avoid unnecessary cloning.
  • Broad support for both Unix and Windows terminals so your UIs look great everywhere.

Getting Started

If you're familiar with React, you'll feel right at home with iocraft. It uses all the same concepts, but is text-focused and made for Rust.

Here's your first iocraft program:

use iocraft::prelude::*;

fn main() {
    element! {
        Box(
            border_style: BorderStyle::Round,
            border_color: Color::Blue,
        ) {
            Text(content: "Hello, world!")
        }
    }
    .print();
}

Your UI is composed primarily via the element! macro, which allows you to declare your UI elements in a React/SwiftUI-like syntax.

iocraft provides a few built-in components, such as Box, Text, and TextInput, but you can also create your own using the #[component] macro.

For example, here's a custom component that uses a hook to display a counter which increments every 100ms:

use iocraft::prelude::*;
use std::time::Duration;

#[component]
fn Counter(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
    let mut count = hooks.use_state(|| 0);

    hooks.use_future(async move {
        loop {
            smol::Timer::after(Duration::from_millis(100)).await;
            count += 1;
        }
    });

    element! {
        Text(color: Color::Blue, content: format!("counter: {}", count))
    }
}

fn main() {
    smol::block_on(element!(Counter).render_loop()).unwrap();
}

More Examples

There are many examples on GitHub which demonstrate various concepts such as tables, progress bars, fullscreen apps, forms, and more!

Shoutouts

iocraft was inspired by Dioxus and Ink, which you should also check out, especially if you're building graphical interfaces or interested in using JavaScript/TypeScript.

You may also want to check out Ratatui, which serves a similar purpose with a less declarative API.

License

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.

Dependencies

~7–16MB
~220K SLoC