#ui-framework #ui #framework

frui

A developer-friendly framework for building user interfaces in Rust

1 unstable release

0.0.1 Sep 30, 2022

#160 in #ui-framework

MIT/Apache

175KB
3.5K SLoC

Frui

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

MIT Apache

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);
}

screenshot of application running above code

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:

Dependencies

~5–14MB
~178K SLoC