frui 0.0.1

A developer-friendly framework for building user interfaces in Rust
Documentation

Reading: "Fr" as in "fruit" and "ui" as in "you" and "I".

What is Frui?

Frui is a developer-friendly UI framework that makes building user interfaces easy and productive. It's based on Flutter architecture and is written in Rust!

Example

#![feature(min_specialization)]
#![feature(type_alias_impl_trait)]

use frui::prelude::*;

#[derive(ViewWidget)]
struct App;

impl ViewWidget for App {
    fn build<'w>(&'w self, _: BuildContext<'w, Self>) -> Self::Widget<'w> {
        Center::child(Text::new("Hello, World!"))
    }
}

fn main() {
    run_app(App);
}

Features

Frui, as of now, is a PoC, and has only implemented the most essential parts of the API. There is a lot of work that needs to be done, especially in terms of back-end considerations, optimizations, and widget implementations (widgets like buttons, gesture detectors, theming, flex wrappers, etc.).

  • ViewWidget (based on StatelessWidget and StatefulWidget)
  • InheritedWidget (based on InheritedWidget)
  • LocalKey (based on Key)
  • Scheduling state updates
  • Basic event detection (KeyboardEventDetector / mouse events through event method)
  • Basic layout widgets (Column, Row, Center)
  • Documentation and tutorials
  • Event passing, handling focus, Z-layers
  • Optimizations: widget-rebuild order based on depth, layout & painting
  • Library of widgets common to all visual langauges provided out of the box (Column, Row, GestureDetector, Scroll, etc.)
  • Separate widget library implementing one of the design languages (e.g. Material Design)

🦀 Counter - Example

Obligatory crab counter! From examples/crab_counter.rs.

#![feature(min_specialization)]
#![feature(type_alias_impl_trait)]

use frui::prelude::*;

mod misc;
use misc::Button;

#[derive(ViewWidget)]
struct CrabCounter;

impl WidgetState for CrabCounter {
    type State = isize;

    fn create_state(&self) -> Self::State { 0 }
}

impl ViewWidget for CrabCounter {
    fn build<'w>(&'w self, ctx: BuildContext<'w, Self>) -> Self::Widget<'w> {
        Column::builder()
            .space_between(60.0)
            .main_axis_size(MainAxisSize::Max)
            .cross_axis_size(CrossAxisSize::Max)
            .main_axis_alignment(MainAxisAlignment::Center)
            .cross_axis_alignment(CrossAxisAlignment::Center)
            .children((
                Text::new(format!("{} 🦀", *ctx.state()))
                    .size(100.0)
                    .weight(FontWeight::BOLD),
                Row::builder()
                    .space_between(10.0)
                    .children((
                        Button {
                            label: Text::new("+").size(30.),
                            on_click: || *ctx.state_mut() += 1,
                        },
                        Button {
                            label: Text::new("-").size(30.),
                            on_click: || *ctx.state_mut() -= 1,
                        },
                    )),
            ))
    }
}

fn main() {
    run_app(CrabCounter);
}

Crabs counter running on MacOS

Credits

Frui wouldn't exist without Flutter and its widget architecture, which inspired Frui's API.

Frui also wouldn't exist without prior work done on Druid - which powers most of the back-end. Many widgets share some of the implementation details with it as well.

Thank you!

License

All code in this repository is dual-licensed under either: