Skip to content

Commit 0cf9384

Browse files
committed
small fixes for guide and add CSS chapter
1 parent ded34cd commit 0cf9384

File tree

11 files changed

+237
-6
lines changed

11 files changed

+237
-6
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use async_ui_web::{html::Div, NoChild};
2+
3+
// ANCHOR: no-shortcut
4+
async fn div_with_class() {
5+
let div = Div::new();
6+
div.class_list().add_1("my-container").expect("?!?!");
7+
div.render(NoChild).await;
8+
}
9+
// ANCHOR_END: no-shortcut
10+
11+
// ANCHOR: shortcut-imperative
12+
use async_ui_web::shortcut_traits::ShortcutClassList; // 👈 new import!
13+
async fn div_with_class_2() {
14+
let div = Div::new();
15+
16+
// 👇 `add_class` provided by the trait
17+
div.add_class("my-container");
18+
// 👇 `add_classes` for multiple classes
19+
div.add_classes(["my-class", "another-class"]);
20+
21+
div.render(NoChild).await;
22+
}
23+
// ANCHOR_END: shortcut-imperative
24+
// ANCHOR: shortcut-builder
25+
use async_ui_web::shortcut_traits::ShortcutClassListBuilder; // 👈 new import!
26+
async fn div_with_class_3() {
27+
Div::new()
28+
// 👇 add classes without putting `Div` in a variable
29+
.with_classes(["my-class", "another-class"])
30+
.render(NoChild)
31+
.await;
32+
}
33+
// ANCHOR_END: shortcut-builder
34+
// ANCHOR: embedded-css
35+
mod style {
36+
// 👇 Write our CSS here!
37+
async_ui_web::css!(
38+
"
39+
.my-class {
40+
border: 2px solid red;
41+
}
42+
/* Supports any selector */
43+
.flex.my-class:not(:hover) {
44+
background-color: green;
45+
}
46+
"
47+
);
48+
}
49+
async fn div_with_style() {
50+
Div::new()
51+
// 👇 the `style::my_class` constant is generated by the macro
52+
.with_class(style::my_class)
53+
.render(NoChild)
54+
.await;
55+
}
56+
// ANCHOR_END: embedded-css
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mod css;

examples/guide-project/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ async fn app() {
1010
mod building_ui;
1111
mod dynamicity;
1212
mod events;
13+
mod extras;

guide/src/SUMMARY.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- [Building the UI](./building-ui/README.md)
1212
- [Your First Component](./building-ui/1-first-component.md)
1313
- [Building Nested HTML](./building-ui/2-nested-html.md)
14-
- [All the HTML](./building-ui/3-html-components.md)
14+
- [All the HTML](./building-ui/3-all-the-html.md)
1515
- [Making Siblings](./building-ui/4-siblings.md)
1616
- [Components](./building-ui/5-components.md)
1717

@@ -22,6 +22,8 @@
2222

2323
- [Handling Events](./events/README.md)
2424
- [Reactivity and State Management](./reactive/README.md)
25-
25+
- [Extras](./extras/README.md)
26+
- [CSS Styling](./extras/css.md)
2627
# Framework Design & Internals
27-
- [Framework Design](./in-depth/framework-design.md)
28+
- [Framework Design](./in-depth/framework-design.md)
29+
- [Future Work: Other Backends](./in-depth/other-backends.md)

guide/src/building-ui/4-siblings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Making Siblings with Join
1+
# Making Siblings
22

33
We've so far seen how to render HTML elements and nest them.
44

guide/src/dynamicity/2-dynamic-slot.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# The DynamicSlot Component
22

3-
The last subchapter covered dynaimcally *updating* HTML elements.
3+
The previous subchapter covered dynamically *updating* HTML elements.
44
Now we'll be *adding* and *removing* elements.
55

66
The [`DynamicSlot` component](https://docs.rs/async_ui_web/latest/async_ui_web/components/struct.DynamicSlot.html)

guide/src/extras/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Extras
2+
3+
The content covered up to here should be sufficient to build any application,
4+
but there are a few more things that Async UI provides...

guide/src/extras/css.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# CSS Styling
2+
3+
## Class List Shortcuts
4+
You can already do basic styling by accessing your elements `style` property
5+
([MDN doc](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style),
6+
[web-sys doc](https://docs.rs/web-sys/latest/web_sys/struct.HtmlElement.html#method.style)).
7+
8+
You can also already do CSS styling by setting classnames
9+
for your elements with the `classList`
10+
([MDN doc](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList),
11+
[web-sys doc](https://docs.rs/web-sys/latest/web_sys/struct.Element.html#method.class_list))
12+
```rust
13+
{{ #include ../../../examples/guide-project/src/extras/css.rs:no-shortcut }}
14+
```
15+
16+
For extra convenience, Async UI provides a few traits to make styling code a bit
17+
less verbose.
18+
19+
### `ShortcutClassList`
20+
```rust
21+
{{ #include ../../../examples/guide-project/src/extras/css.rs:shortcut-imperative }}
22+
```
23+
There are a few more methods available.
24+
View the documentation [here](https://docs.rs/async_ui_web/latest/async_ui_web/shortcut_traits/trait.ShortcutClassList.html).
25+
### `ShortcutClassListBuilder`
26+
```rust
27+
{{ #include ../../../examples/guide-project/src/extras/css.rs:shortcut-builder }}
28+
```
29+
View the documentation [here](https://docs.rs/async_ui_web/latest/async_ui_web/shortcut_traits/trait.ShortcutClassListBuilder.html).
30+
31+
## Linking CSS
32+
33+
You can already add your CSS content by either
34+
* linking it in your `index.html` (with a `<link />` tag), or
35+
* constructing a `<style>` element with Async UI.
36+
37+
Async UI provide an extra mechanism that let you write your CSS in Rust file.
38+
```rust
39+
{{ #include ../../../examples/guide-project/src/extras/css.rs:embedded-css }}
40+
```
41+
With this method, you don't have to worry about linking the CSS -
42+
it is done automatically by the macro.
43+
44+
The macro will add random **postfix** to your CSS class names so that
45+
you don't have to worry about name collision.
46+
47+
The macro expose those postfixed class names as Rust `&str` constants you can use.
Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,96 @@
1-
# Framework Design
1+
# Framework Design
2+
3+
## Design
4+
5+
### Basics
6+
* UI as side effect: Rust [Future](https://doc.rust-lang.org/nightly/core/future/trait.Future.html)
7+
objects can render things.
8+
* These Futures are long-running. Their UI elements stay on the screen
9+
until they are dropped.
10+
11+
### DOM
12+
* HTML structure is built by joining and nesting Futures.
13+
* The "base" Future is [ContainerNodeFuture](https://docs.rs/async_ui_web_core/latest/async_ui_web_core/struct.ContainerNodeFuture.html).
14+
It puts a single HTML node on the screen.
15+
It use the described context to insert its node on first poll,
16+
and remove the node when dropped.
17+
* The code for joining is based on [futures-concurrency](https://docs.rs/futures-concurrency/),
18+
but rewritten to significantly improve performance and reduce allocations.
19+
* We use an implicit rendering context, provided as a scoped thread-local set
20+
for each Future `poll`. The context provides the information needed for
21+
[`insertBefore`](https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore)
22+
* The HTML element that the polled Future should insert its own element to.
23+
This is the "parent element".
24+
* An ordered map containing all the children of the parent element,
25+
each keyed by a lexicographical "path" from the parent element.
26+
```rust
27+
Div::new().render( // this Div is the parent element for A-F
28+
join((
29+
A, // path = [0]
30+
join((
31+
C, // path = [1, 0]
32+
D, // path = [1, 1]
33+
join((
34+
E, // path = [1, 2, 0]
35+
F, // path = [1, 2, 1]
36+
))
37+
)),
38+
B, // path = [2]
39+
Div::new().render( // this Div is the parent of G and H
40+
join((
41+
G, // path = [0]
42+
H, // path = [1]
43+
))
44+
),
45+
))
46+
)
47+
```
48+
```html
49+
<div>
50+
A
51+
C
52+
D
53+
E
54+
F
55+
B
56+
<div>
57+
G
58+
H
59+
</div>
60+
</div>
61+
```
62+
* The "path" is stored as a `SmallVec<[u32; 4]>`.
63+
* No diffing virtual DOM. Dynamicity is special case
64+
([DynamicSlot](https://docs.rs/async_ui_web/latest/async_ui_web/components/struct.DynamicSlot.html)).
65+
* The event listener [EventFutureStream](https://docs.rs/async_ui_web/latest/async_ui_web/event_handling/struct.EventFutureStream.html)
66+
type add a callback to put the event object in a cell and wake its waker.
67+
On every poll it the check if there is an event in the cell.
68+
69+
### State
70+
* We don't provide reactivity or state management.
71+
* State can be put in Future objects.
72+
* Usually, this comes in the form of variables in async functions.
73+
74+
### Scheduling
75+
* The whole app is one big Future.
76+
* A "main" async executor is provided ([async-executor](https://docs.rs/async-executor/)).
77+
It drives the app Future and can also be used to spawn things.
78+
* The main executor is driven by a hand-rolled "root" executor.
79+
* The root executor `setTimeout` itself to execute when woken.
80+
81+
## Comparisons
82+
* The UI-as-side-effect design of Async UI is quite unique, as far as I know.
83+
* Blocking UI (like [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert)
84+
or [`MessageBox`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox))
85+
technically present UI as side-effect too, but they're not very flexible
86+
since they block the entire application.
87+
* Async UI has long-living async functions and store component state as
88+
variables in functions. This approach is similar to [Crank.js](https://crank.js.org/).
89+
90+
## Motivations
91+
Async UI is motivated by the fact that async is an effect system, and in many cases,
92+
UI is too.
93+
94+
But that isn't the only possible motive for this framework design.
95+
[This blog post by *notgull*](https://notgull.github.io/async-gui/) describes
96+
the same idea of using async for UI, but from a less abstracted perspective.

0 commit comments

Comments
 (0)