Skip to content

Commit

Permalink
docs(ribir): ✏️ update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
M-Adoo committed Dec 8, 2023
1 parent 152a2b4 commit 841d526
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 90 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@ jobs:
- name: build ribir
run: cargo build
- name: compile doc examples
run: find "./docs" -name "*.md" | xargs -I {} rustdoc -Z unstable-options --test --no-run {} -L target/debug/deps/ --edition 2018 --extern ribir=target/debug/libribir.rlib
run: |
{
echo ./README.md
find "./docs" -name "*.md"
} | xargs -I {} rustdoc -Z unstable-options --test --no-run {} -L target/debug/deps/ --edition 2018 --extern ribir=target/debug/libribir.rlib
37 changes: 12 additions & 25 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ There are 5 types of changes:
- `Changed` for changes in existing functionality.
- `Fixed` for any bug fixes.
- `Documented` for any changes to the documentation.
- `Breaking` for the detail of any backwards incompatible changes.
- `Breaking` for the detail of any backward incompatible changes.

And please only add new entries below the [Unreleased](#unreleased---releasedate) header with the following format:

Expand All @@ -33,39 +33,26 @@ We use it in our own projects and have a good experience, and we hope you can al
### Features

- **core**: control the process of the entire view: compose, build, update, layout and render.

- **declarative language**: not a new language, but a set of Rust macros that easily interact with Rust.

- **widgets compose system**: has four kinds of widgets to support you can implement your own widget in different ways:
: function widget, `Compose`, `Render` and `ComposeChild`. So that
- function widget and `Compose`, from other widgets composition.
- `Render`, implement your own layout or rendering logic
- `ComposeChild`, control the compose logic between parent and child widgets, and specify the template of child widgets.

- `Render`, implement your layout and paint anything you want.
- `ComposeChild`, control the compose logic between parent and child widgets and specify the template of child widgets.
- **non-intrusive state**: convert your data to a listenable state, and update the view according to the change of the state.

- **layout system**: learning and inspired by [Flutter] Sublinear layout, but not exactly the same.

- **event system**: a compose event system, support event bubbling and capture. Support compose to any widget, and exist only if you use it.

- **theme System**: support full and inherit/partial theme, so you can use it to override or dynamically switch the theme of the subtree. Include: palette, icons, animate transitions, the decoration widget of the widget, etc. In a very rough state and the API will be redesigned soon.

- **animations**: base on state but no side effect animation, it's almost stable in concept, but not many predefined animations yet.

- **painter**: convert view to 2d path.

- **gpu render**: gpu backend for **painter**, do path tessellation, so that easy to render the triangles in any gpu render engine. A `wgpu` implementation is provided as the default gpu render engine. Tessellation base on [lyon].

- **Text**: support basic text typography and ime input, in a usable but rough stage.

- **widgets**: widgets library provide 20+ basic widgets, but all in a rough stage, and the API not stable yet.

- **layout system**: learning and inspired by [Flutter] Sublinear layout, but not the same.
- **event system**: a composition event system, that supports event bubbling and capture. Allow to compose with any widget, and exists only if you use it.
- **theme System**: support full and inherit/partial theme, so you can use it to override or dynamically switch the theme of the subtree. Include palette, icons, animate transitions, the decoration widget of the widget, etc. In a very rough state and the API will be redesigned soon.
- **animations**: based on state but no side effect animation, it's almost stable in concept, but not many predefined animations yet.
- **painter**: convert the view to the 2D path.
- **GPU render**: GPU backend for the **painter**, do path tessellation, so that easy to render the triangles in any GPU render engine. A `wgpu` implementation is provided as the default GPU render engine. Tessellation base on [lyon].
- **text**: support basic text typography and IME input, in a usable but rough stage.
- **widgets**: the widgets library provides 20+ basic widgets, but all are in a rough stage, and the API is not stable yet.
- **examples**: counter, storybook, messages, todos, wordle_game, etc.

### Documented

- **introduction**: add `introduction.md` to introduce Ribir and why choose it.
- **get started**: add the `get_started` series of tutorials to help user get started with Ribir.
- **get started**: add the `get_started` series of tutorials to help users get started with Ribir.


[Flutter]: https://flutter.dev/
Expand Down
107 changes: 67 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,86 @@
<h1 align="center">
Ribir - Non-intrusive Declarative GUI Framework
</h1>
<p align="center"><a href="https://ribir.org" target="_blank" rel="noopener noreferrer">
<img src="website/static/img/logo.svg" alt="Ribir-logo" width = "128px">
</a></p>

<p align="center">
Use Rust to build multi-platform applications from a single codebase.
</p>
<div align="center">
<img src="website/static/img/logo-animation.gif" width="480px" />

<!-- # Ribir -->

Ribir is a framework for building modern native/wasm cross-platform user interface applications.

[![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)
[![License](https://img.shields.io/badge/license-MIT-informational)](https://github.com/RibirX/ribir/blob/master/LICENSE)
[![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)

[Documents] | [Examples]
[Website] | [Documents] | [Examples] | [Changelog]

<!--todo: a demos picture here-->
</div>

## What's Ribir?

## Principles

- **Non-injection and Non-invasive**: Ribir interacts with the APIs of your data structure, and does not require you to do any pre-design for the user interface. Developers can focus on designing the data struct, logic and APIs. Ribir will neither break your existing logic nor require injecting any of its own objects.

- **Declarative**: The user interface is the description of data, the description will automatically react to the data modification. Once you describe your data, the description will keep describing your data.

- **Purely composed**: Ribir creates UI via widgets. There is not a base-object, even if the built-in fields are provided in a composed way. For example, only if you use `margin` field, the `Margin` widget will be composed, if you do not use it, you don't pay any overhead for `Margin`. "Only pay for what you need" is an important guideline for Ribir.
Ribir is a Rust GUI framework to help you build beautiful, natively compiled, multi-platform applications from a single codebase.

It's trying a new way to build UI directly based on the API of your data, and every modification of data will drive the UI update point-to-point. In this way, you can focus on designing the data structure and API of your application and then describe the UI of your data without intrusive logic.

## At First Glance

A simple example of a counter:


<div style="display:inline-block;">
<div style="float:left;height:400px;overflow:scroll; ">
<table>
<tr>
<td style="padding:10px">
<div>

``` rust
use ribir::prelude::*;
fn main() {
app::run(widget! {
states { cnt: Stateful::new(0) }
Column {
h_align: HAlign::Center,
align_items: Align::Center,
FilledButton { on_tap: move |_| *cnt += 1, Label::new("Add") }
H1 { text: cnt.to_string() }
FilledButton { on_tap: move |_| *cnt += -1, Label::new("Sub") }
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);
}
```
</div>
<img src="website/static/img/counter_demo.gif" width="300" style="float:right;"/>
</div>
</td>
<td style="padding:10px">
<img src="website/static/img/counter_demo.gif" width="300"/>
</td>
</tr>
</table>



More [Examples]


## Key Features
## Features

- **Write once run anywhere**: Compile native code for desktop and mobile(not yet), and WASM for Web(not yet). Since Ribir has rather few platform dependencies, it's not hard to support more platforms by yourself.
- **Declarative language expanded from Rust syntax**: The declarative language is based on Rust, so interaction with Rust becomes natural and easy.
- **Easy custom widget**: Ribir supports the implementation of custom `Compose`, `Render` and `ComposeChild` widgets, you only need to implement the corresponding traits. Evenmore, you are able to specify the template of the children of `ComposeChild`, just by deriving the `Template` traits.
- **Powerful custom theme**: Specify the theme for the whole application or partial subtree. In the theme, you can configure the palette, icons, animate transitions, widget custom themes, the interactive behavior of widget and even compose more decoration widgets on it.
- **Rich available official widgets**: A `ribir_widgets` library exists,containing common desktop and mobile widgets.
- **No side effect animations**: Animation in Ribir is only a visual effect, that won't affect data. Animate support for any render widgets.
- **Alternative rendering backends**: The rendering backend is replaceable, you can implement your own rendering to output image, html, svg or any other stuff. Ribir provides developers with a gpu backend basing on [wgpu] and perhaps a soft(cpu) render in the future.
- **declarative language**: not a new language, but a set of Rust macros that easily interact with Rust.
- **widgets compose system**: has four kinds of widgets to support you can implement your widget in different ways:
- function widget and `Compose`, from other widgets composition.
- `Render`, implement your layout and paint anything you want.
- `ComposeChild`, control the compose logic between parent and child widgets and specify the template of child widgets.
- **non-intrusive state**: convert your data to a listenable state, and update the view according to the change of the state.
- **layout system**: learning and inspired by [Flutter] Sublinear layout, but not the same.
- **event system**: a composition event system, that supports event bubbling and capture. Allow to compose with any widget, and exists only if you use it.
- **theme System**: support full and inherit/partial theme, so you can use it to override or dynamically switch the theme of the subtree. Include palette, icons, animate transitions, the decoration widget of the widget, etc. In a very rough state and the API will be redesigned soon.
- **animations**: based on state but no side effect animation, it's almost stable in concept, but not many predefined animations yet.
- **painter**: convert the view to the 2D path.
- **GPU render**: GPU backend for the **painter**, do path tessellation, so that easy to render the triangles in any GPU render engine. A `wgpu` implementation is provided as the default GPU render engine. Tessellation base on [lyon].
- **text**: support basic text typography and IME input, in a usable but rough stage.
- **widgets**: the widgets library provides 20+ basic widgets, but all are in a rough stage, and the API is not stable yet.

## Support Platform

Expand All @@ -72,6 +93,13 @@ More [Examples]
|Android|🚧 Not yet|
|Web|🚧 Not yet|

## Love Ribir?

If you like Ribir, give our repo a [⭐ star ⬆️](https://github.com/RibirX/Ribir) and ['Watch' 👀](https://github.com/RibirX/Ribir/subscription) 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.
Expand Down Expand Up @@ -99,13 +127,12 @@ Please [report all bugs](https://github.com/RibirX/Ribir/issues/new/choose)! We

## Thanks

This project exists thanks to all the people who contribute:
This project exists thanks to all the people who contributed:

<a href="https://github.com/RibirX/Ribir/graphs/contributors">
<img src="https://contrib.rocks/image?repo=RibirX/Ribir" height="50px">
</a>

<br/>
<br/>

We also found inspiration from the following frameworks:
Expand All @@ -114,12 +141,12 @@ We also found inspiration from the following frameworks:
* [QML]

## License
Ribir is [MIT-licensed](./LICENSE)

Ribir is [MIT licensed](./LICENSE)

[Website]: https://ribir.org
[Changelog]: ./CHANGELOG.md
[Flutter]: https://flutter.dev/
[QML]: https://doc.qt.io/qt-6/qtqml-index.html
[Examples]: ./examples/
[Documents]: https://ribir.org/docs/introduction
[Wgpu]: https://github.com/gfx-rs/wgpu

16 changes: 8 additions & 8 deletions docs/en/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## What is Ribir?

Ribir is an open source Rust framework for building beautiful UI, natively compiled, multi-platform applications from a single codebase.
Ribir is an open-source Rust framework for building beautiful UI, natively compiled, multi-platform applications from a single codebase.

Ribir uses a non-intrusive declarative programming model that allows you to develop and design user interfaces as an independent module.

Expand All @@ -23,7 +23,7 @@ Ribir only interacts with the API of your data and does not require any pre-desi
- No additional states
- No additional notification mechanisms
- No inheritance of any base classes
- No any other pre-constraints.
- No other pre-constraints.

It doesn't break the logic and structure of your existing data or inject any additional objects. When developing the core part of an application, you can focus on designing the data, logic, and API of the application without thinking about the UI at all.

Expand All @@ -33,7 +33,7 @@ The UI directly operates data, and data modifications directly drive UI updates,

Ribir can be used to develop desktop, mobile, web and server-side rendering applications. It generates efficient binary code or WASM programs without relying on any runtime environment. It outputs a very simple, platform-independent drawing result, allowing you to choose to be rendered entirely by the GPU or CPU. You can even easily implement your own rendering backend to expand to uncovered platforms.

### Declarative syntax that is easy to interact with Rust
### The Declarative syntax that is easy to interact with Rust

Ribir provides a declarative syntax that is easy to interact with Rust. It is not a new language, but a set of Rust macros. Therefore, it can interact well with Rust, making your code both a clear view description and a powerful logical expression, without any environment and tool dependencies.

Expand Down Expand Up @@ -64,9 +64,9 @@ fn_widget!{
};
```

The above example shows the way of combining built-in widgets. Even if `Text` does not have a `margin` field, you can still use the `Margin::margin` and compose it with `Text` to form a new widget. `Margin` will only be created when a widget uses the `margin` field, otherwise there will be no overhead.
The above example shows the way of combining built-in widgets. Even if `Text` does not have a `margin` field, you can still use the `Margin::margin` and compose it with `Text` to form a new widget. `Margin` will only be created when a widget uses the `margin` field, otherwise, there will be no overhead.

**Digestion of composite widget**: When describing the view of the data, in addition to some basic widgets, most widgets are composed of other widgets. For example, a `Button`, it is composed of `Text`, `Icon` or `BoxDecoration`, etc. widgets, `Button` itself is not a view element, we call this type of widget a composite widget. Composite widgets will be digested during view construction. They are like a function and are called once during view construction to build the final view and create the corresponding update logic, and do not exist in the final view.
**Digestion of composite widgets**: When describing the view of the data, in addition to some basic widgets, most widgets are composed of other widgets. For example, a `Button` is composed of `Text`, `Icon` or `BoxDecoration`, etc. The `Button` itself is not a view element, we call this type of widget a composite widget. Composite widgets will be digested during view construction. They are like a function and are called once during view construction to build the final view and create the corresponding update logic, and do not exist in the final view.

**Only state with write sources are real state**: Unlike other declarative frameworks that add fields to widgets to control widget updates. Ribir is non-intrusive. Ribir treats the entire widget as a state to control updates.
At the same time, it provides the ability to split the state, so that the local view can directly depend on the modification of part of the data to update (introduced in detail in the subsequent tutorial). Another big difference is that stateful and stateless can be converted to each other. If a state has no write source, it will degenerate into stateless, because no one will update it. For example:
Expand All @@ -83,11 +83,11 @@ fn_widget!{
};
```

In the above example, we declared a `Text` and used the `pipe!` macro to directly associate the visibility of `Text` with `show_hi`. But this association will be eliminated when the view is constructed, because `show_hi` always remains unchanged - it has no write source. Therefore, Ribir constructs a simple static view.
In the above example, we declared a `Text` and used the `pipe!` macro to directly associate the visibility of `Text` with `show_hi`. But this association will be removed when the view is constructed because `show_hi` has no written source. Therefore, Ribir constructs a simple static view.

### Reliability

Unlike general GUI frameworks that use inheritance and do not have any type constraints except base class inheritance, Ribir builds views based on widget composition and relies on the types between parent and child widgets to constrain whether and how to compose them. You can standardize your own child types, so many errors can be reported at compile time instead of being checked at runtime.
Unlike general GUI frameworks that use inheritance and do not have any type constraints except base class inheritance, Ribir builds views based on widget composition and relies on the types between parent and child widgets to constrain whether and how to compose them. You can standardize your child types, so many errors can be reported at compile time instead of being checked at runtime.


## What is the current status of Ribir?
Expand All @@ -108,4 +108,4 @@ In all important designs of the entire framework, performance is an important fa

**Polestar Chat**:

**Sisyphus**: An editor for editing interactive documents, this is a long-term project, which is still in the early design and development stage, and it is the idea of this project that led to the birth of Ribir.
**Sisyphus**: An editor for editing interactive documents, this is a long-term project, that is still in the early design and development stage, and it is the idea of this project that led to the birth of Ribir.
8 changes: 3 additions & 5 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# Ribir Examples

All the examples in this folder use the macro `example_framework!` to startup, the examples will generate tests and benchmarks for the example to ensure every modification work for those examples.
All the examples in this folder use the macro `example_framework!` to generate tests, benchmarks and main function for the example.

Run examples:
To run the examples, you can use the following commands:

``` sh
cargo run -p storybook --features="wgpu"
cargo run -p storybook
```

Remember add `--features="wgpu"` to use `wgpu` painter-backend to render, we not enable it as default.
Loading

0 comments on commit 841d526

Please sign in to comment.