Introduction

Freya logo

Freya is native GUI library built on top of 🧬 Dioxus and powered by 🎨 Skia, for 🦀 Rust.

⚠️ It's currently work in progress and not usable for production, but you can already play with it!

You can join the Discord server if you have any question or issue.

You can also see the API Reference.


#![allow(unused)]
fn main() {
fn app(cx: Scope) -> Element {
    let mut count = use_state(cx, || 0);

    render!(
        container {
            height: "100%",
            width: "100%",
            background: "rgb(35, 35, 35)",
            color: "white",
            padding: "12.5",
            onclick: move |_| count += 1,
            label { "Click to increase -> {count}" }
        }
    )
}
}

Check out the examples in the Freya repository to learn more.

About

Freya is built on top of Dioxus, it provides a renderer powered by Skia, alongside a set of elements, components, hooks and testing utilities.

Why 🧬 Dioxus?

Dioxus is heavily influenced by React, resulting in a streamlined process for creating complex components without the need for excessive code.

This sets it apart from other Rust libraries, where equivalent components often require a significant amount of additional code.

Why 🎨 Skia?

Skia is a battle-tested and well maintained graphics library, and there are even some rusty bindings.

Environment Setup

Make sure you have Rust and your OS dependencies installed.

Windows

You will need C++ build tools which you can get through Visual Studio 2022, learn more here.

Linux

Debian-based (Ubuntu, PopOS, etc)

Install these packages:

sudo apt install build-essential libssl-dev pkg-config cmake libgtk-3-dev libclang-dev

Don't hesitate to contribute so other distros can be added here.

MacOS

No setup required. But feel free to add more if we miss something.

Hello, World!

Let's start by creating a hello world project.

Creating the project

mkdir freya-app
cd freya-app
cargo init

Cargo.toml

Make sure to add Freya and Dioxus as dependencies:

[package]
name = "freya-app"
version = "0.1.0"
edition = "2021"

[dependencies]
freya = { git="https://github.com/marc2332/freya" }
dioxus = { git="https://github.com/DioxusLabs/dioxus", rev="49c5a5043a16fc82210af146c345793dd448e519"}

src/main.rs

And paste this code in your main.rs file.

#![cfg_attr(
    all(not(debug_assertions), target_os = "windows"),
    windows_subsystem = "windows"
)]

use freya::prelude::*;

fn main() {
    launch(app);
}

fn app(cx: Scope) -> Element {
    let mut count = use_state(cx, || 0);

    render!(
        container {
            height: "100%",
            width: "100%",
            background: "rgb(35, 35, 35)",
            color: "white",
            padding: "12",
            onclick: move |_| count += 1,
            label { "Click to increase -> {count}" }
        }
    )
}

Running

Simply run with cargo:

cargo run

Hot reload

Freya supports Dioxus hot reload, this means you can update the layout and styling of your app on the fly, without having to compile any rust code.

Setup

Just before launching your app, you need to initialize the hot-reload context:

fn main() {

    dioxus_hot_reload::hot_reload_init!(Config::<FreyaCtx>::default());

    launch(app);
}

That's it!

Virtualizing

Virtualizing helps you render a lot of data efficiently. It will only mount the elements you see in the screen, no matter how big the data is.

Target usages

  • Text editor
  • Tables
  • Etc

Usage

Freya comes with a VirtualScrollView component which can help you archive the virtualization of some data.

The virtualization logic of VirtualScrollView is implemented at component-level, so, you could implement your own version if you wanted.

Here is an example:

fn main() {
    launch(app);
}

fn app(cx: Scope) -> Element {
    let values = use_state(cx, || vec!["Hello World"].repeat(400));

    render!(
        VirtualScrollView {
            width: "100%",
            height: "100%",
            show_scrollbar: true,
            direction: "vertical",
            length: values.get().len(),
            item_size: 25.0,
            builder_values: values.get(),
            builder: Box::new(move |(key, index, values)| {
                let values = values.unwrap();
                let value = values[index];
                rsx! {
                    label {
                        key: "{key}",
                        height: "25",
                        "{index} {value}"
                    }
                }
            })
        }
    )
}

alt text

Parameters

show_scrollbar

By default, it does not display a scrollbar. However, you can enable it by setting the show_scrollbar parameter to true.

direction

It supports both vertical and horizontal directions. If direction is set to vertical, the items will be displayed in a single column, with the scrollbar appearing on the right-hand side. If direction is set to horizontal, the items will be displayed in a single row, with the scrollbar appearing at the bottom.

length

How many elements can be rendered. Usually the lenth of your data.

item_size

Used to calculate how many elements can be fit in the viewport.

builder_values

Any data that you might need in the builder function

builder

This is a function that dinamically creates an element for the given index in the list. It receives 3 arguments, a key for the element, the index of the element and the builder_values.