RibirX / Ribir

Non-intrusive GUI framework for Rust
https://ribir.org
MIT License
810 stars 17 forks source link
cross-platform declarative gui native non-intrusive reactive rust ui webassembly

Ribir - Non-intrusive GUI Framework for Rust

Ribir-logo

Use Rust to build multi-platform applications from a single codebase.

[![CI](https://github.com/RibirX/Ribir/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/RibirX/Ribir/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/RibirX/Ribir/branch/master/graph/badge.svg)](https://codecov.io/gh/RibirX/ribir) [![Crates.io](https://img.shields.io/crates/v/ribir)](https://crates.io/crates/ribir) [![Crates.io](https://img.shields.io/crates/d/ribir)](https://crates.io/crates/ribir) [![Discord](https://img.shields.io/discord/699900144002269226?label=discord)](https://discord.gg/7p3pSrUvmq) [![X (formerly Twitter) Follow](https://img.shields.io/twitter/follow/ribir_x )](https://twitter.com/intent/user?screen_name=ribir_x) [Website] | [Documents] | [中文文档] | [Web Demo]| [Examples] | [Changelog] | [Releases] | [Roadmap]

What's Ribir?

Ribir is a Rust GUI framework that helps you build beautiful and native multi-platform applications from a single codebase.

Experience a novel approach to UI development that's directly based on your data structure APIs. Any data mutation will trigger a precise UI update. Your focus should be on designing your data structure and its APIs. Then, you can describe your data's UI without intruding on its logic.

At First Glance

A simple example of a counter:

``` rust no_run use ribir::prelude::*; fn main() { let counter = fn_widget! { let cnt = Stateful::new(0); @Row { @FilledButton { on_tap: move |_| *$cnt.write() += 1, @{ Label::new("Inc") } } @H1 { text: pipe!($cnt.to_string()) } } }; App::run(counter); } ```

To use Ribir without DSL:

use ribir::prelude::*;

fn main() {
  let counter = |ctx: &mut BuildCtx| {
    let cnt = Stateful::new(0);

    let c_cnt = cnt.clone_writer();
    let inc_btn = FilledButton::declarer()
      .on_tap(move |_| *c_cnt.write() += 1)
      .finish(ctx)
      .with_child(Label::new("Inc"));

    let counter = H1::declarer()
      .text(pipe!($cnt.to_string()))
      .finish(ctx);

    Row::declarer()
      .finish(ctx)
      .with_child(inc_btn)
      .with_child(counter)
      .into_widget()
  };

  App::run(counter);
}

More Examples

Features

Architecture overview

Support Platform

Platform Support situation
Linux
Windows
macOS
iOS 🚧 Not yet
Android 🚧 Not yet
Web

Ribir is actively being developed and tested on desktop platforms, with both desktop and web platforms integrated into our CI/CD pipeline.

While the framework can compile and run on mobile platforms, we haven't fully tested or adapted the user interface for them yet. We plan to focus on mobile support once the core framework is stable and a production-ready widget library is released.

Love Ribir?

If you like Ribir, give our repo a ⭐ STAR ⬆️ and WATCH 👀 our repository to stay updated with the latest developments!

Every encouragement and feedback can support us to go further.

Contributing

We are grateful to the community for contributing bug fixes and improvements.

😎 New to Ribir?

Start learning about the framework by helping us improve our documentation. Feel free to open a new "Documentation" issue. We are also very welcome:

For more information please read:

🤔 Confused about something?

Feel free to go to Discussions and open a new "Q&A" to get help from contributors. Often questions lead to improvements to the ergonomics of the framework, better documentation, and even new features!

😱 Found a bug?

Please report all bugs! We are happy to help support developers fix the bugs they find if they are interested and have the time.

Thanks

This project exists thanks to all the people who contributed:


We also found inspiration from the following frameworks:

License

Ribir is MIT-licensed