minimal, obvious, graphical web application interface
master:
mogwai
is a view library for creating GUI applications.
It is written in Rust and runs in your browser and has enough functionality server-side
to do rendering. It is an alternative to React, Backbone, Ember, Elm, Purescript, etc.
The main concepts behind mogwai
are
sinks and streams instead of callbacks - view events like click, mouseover, etc are sent through streams instead of invoking a callback. Streams can be branched and may have their output messages mapped, filtered and folded.
views are dumb - a view is just a struct that mutates the UI tree after receiving a message from a stream. Views are constructed and nested using plain Rust functions or an RSX macro.
widget logic is a loop over event messages - widgets are asynchronous loops that receive events from the view and send updates to the view in response.
Here is an example of a button that counts the number of times it has been clicked:
```rust, norun use mogwaidom::prelude::*;
struct Button {
clicks: usize,
click: Output<()>,
text: Input
impl Button {
/// Convert into a ViewBuilder
fn builder(mut self) -> ViewBuilder {
rsx! (
button(on:click=self.click.sink().contramap(|: JsDomEvent| ())) {
// Using braces we can embed rust values in our UI tree.
// Here we're creating a text node that starts with the
// string "Clicked 0 times" which updates every time a
// message is received on the stream.
{("Clicked 0 times", self.text.stream().unwrap())}
}
).withtask(async move {
while let Some(()) = self.click.get().await {
self.clicks += 1;
self.text.set(if self.clicks == 1 {
"Clicked 1 time".tostring()
} else {
format!("Clicked {} times", self.clicks)
}).await.unwrap();
}
})
}
}
let btn = Button::default(); // Get a sink to manually send events. let mut clicksink = btn.click.sink(); // Build the view to render in the browser let view = Dom::tryfrom(btn.builder()).unwrap(); // Attach it to the browser's DOM tree view.run().unwrap();
// Spawn asyncronous updates wasmbindgenfutures::spawnlocal(async move { // Queue some messages for the view as if the button had been clicked: clicksink.send(()).await.unwrap(); click_sink.send(()).await.unwrap(); // view's html is now "" }); ```
If you're interested in learning more - please read the introduction and documentation.
mogwai
uses streams, sinks, a declarative view builder and async
logic to define components and how they change over time.
View mutation is explicit and happens as a result of views receiving messages, so there is no performance overhead from vdom diffing.
If you prefer a functional style of programming with lots of maps and folds -
or if you're looking to go vroom! then maybe mogwai
is right for you :)
Please do keep in mind that mogwai
is still in alpha and the API is actively
changing - PRs, issues and questions are welcomed. As of the 0.6
release we
expect that the API will be relatively backwards compatible.
mogwai
is a Rust first library. There is no requirement that you have npm
or
node
. Getting your project up and running without writing any javascript is easy
enough.
mogwai
is snappy! Here are some very handwavey and sketchy todomvc metrics:
First you'll need new(ish) version of the rust toolchain. For that you can visit https://rustup.rs/ and follow the installation instructions.
Then you'll need wasm-pack.
For starting a new mogwai project we'll use the wonderful cargo-generate
, which
can be installed using cargo install cargo-generate
.
Then run
shell
cargo generate --git https://github.com/schell/mogwai-template.git
and give the command line a project name. Then cd
into your sparkling new
project and
shell
wasm-pack build --target web
Then, if you don't already have it, cargo install basic-http-server
or use your
favorite alternative to serve your app:
shell
basic-http-server -a 127.0.0.1:8888
Happy hacking! :coffee: :coffee: :coffee:
:green_book: Cooking with Mogwai is a series of example solutions to various UI problems. It aims to be a good reference doc but not a step-by-step tutorial.
Hang out and talk about mogwai
in the support channel:
Examples can be found in the examples folder.
To build the examples use:
shell
wasm-pack build --target web examples/{the example}
Additional external examples include: - mogwai-realworld A "real world" app implementation (WIP) - the benchmark suite - your example here ;)
Please consider sponsoring the development of this library!