rui 0.3.0

Experimental Declarative UI library
Documentation

rui

build status

Experimental Rust UI library, inspired by SwiftUI. Early days, but some stuff already works.

rui is immediate mode (there is no retained tree of views), GPU rendered, updates reacitvely (when your state changes), and has richer layout options than other immediate mode UIs.

discord server

Examples

obligatory Counter (cargo run --example counter):

use rui::*;

fn main() {
    rui(state(
        || 1,
        |count, cx| {
            vstack((
                cx[count].padding(Auto),
                button("increment", move |cx| {
                    cx[count] += 1;
                })
                .padding(Auto),
            ))
        },
    ));
}

some shapes (cargo run --example shapes):

use rui::*;

fn main() {
    rui(hstack((
        circle()
            .color(RED_HIGHLIGHT)
            .padding(Auto),
        rectangle()
            .corner_radius(5.0)
            .color(AZURE_HIGHLIGHT)
            .padding(Auto)
    )));
}

canvas for gpu drawing (cargo run --example canvas):

use rui::*;

fn main() {
    rui(canvas(|_, rect, vger| {
        vger.translate(rect.center() - LocalPoint::zero());

        let paint = vger.linear_gradient(
            [-100.0, -100.0],
            [100.0, 100.0],
            AZURE_HIGHLIGHT,
            RED_HIGHLIGHT,
            0.0,
        );

        let radius = 100.0;
        vger.fill_circle(LocalPoint::zero(), radius, paint);
    }));
}

slider with map (cargo run --example slider):

use rui::*;

#[derive(Default)]
struct MyState {
    value: f32,
}

fn main() {
    rui(state(MyState::default, |state, cx| {
        vstack((
            cx[state].value.font_size(10).padding(Auto),
            map(
                cx[state].value,
                move |v, cx| cx[state].value = v,
                |s, _| hslider(s).thumb_color(RED_HIGHLIGHT).padding(Auto),
            ),
        ))
    }));
}

widget gallery (cargo run --example gallery):

Goals

  • Encode UI in types to ensure stable identity.
  • Use immediate mode initially, then optimize to reduce redraw later.
  • Use vger-rs for rendering.
  • Minimal boilerplate.
  • Good looking.
  • No unsafe.
  • Accessible.

Optional Features

  • tao - (enabled by default) use tao for windowing.
  • winit - use winit for windowing.
  • Use default-features = false if you are embedding rui.

Why?

In the long term, I'd like to move Audulus over to Rust. After looking at other available UI options, it seemed best to implement something resembling the existing immediate mode UI system I already have working in Audulus, but better.

Status

  • ✅ basic shapes: circle, rounded rectangle
  • ✅ basic gestures: tap, drag
  • ✅ hstack/vstack
  • ✅ text
  • ✅ padding
  • ✅ offsets
  • ✅ state
  • ✅ zstack
  • ✅ canvas (GPU vector graphics with vger)
  • ✅ bindings
  • ✅ list
  • ✅ sliders
  • ✅ knobs
  • ✅ editable text (still a bit rough)
  • ✅ any_view (view type erasure)
  • ❌ layout feedback
  • ✅ animation

References

Towards principled reactive UI

Towards a unified theory of reactive UI

Flutter's Rendering Pipeline

Static Types in SwiftUI

How Layout Works in SwiftUI