Skip to main content

max / quasi

Give a region's label to the thing that draws it A label is the name of the control that reveals a member: a tab's text, a disclosure's summary. Only a region that discloses or steps through its members draws one, and until now any region could carry one. Max ruled that a label nothing will draw should not be representable. It cannot be a check. A member is built before it is placed, so nothing about the member knows whether its label will be drawn, and the parent that decides may be in another declare! entirely. That is how MNW's /use-cases lost the titles of nine cards for weeks with a green suite. So Slot has no label. A selective region's body is its own arm carrying frames, each with the name of the control that reveals it, and body, showing and shown collapse into it. That retires the neighbouring trap in the same move: shown was meaningless under Showing::All and ignored there. Picks is the two selective variants only, so a selective body cannot say it shows everything. Slot::frame(label, node) is the only thing that takes a name, and it places the member in the same call. layout::Showing is untouched: it carries no data, so it stays the vocabulary's word and is derived. The declare! syntax is unchanged where it can be. `label` stays written inside the child, which is where it reads, and the macro hoists it onto the placement. A `framed <label> <emission>` modifier covers what a hoist cannot reach: a shape in another invocation answers a Slot, which now carries no label, so goingson's summary_body is placed by its parent as `framed "Time tracked" include summary_body(panel)`. Found and fixed while landing it: three test fixtures labelling screen-level slots, and MNW's shortcuts modal, whose label had never reached markup. A dialog does want an accessible name, so that one became `named`, which is the field that writes one. Span placement is a repair again rather than a re-placement, and the walk is a stack. Choosing every span afresh moved spans that were already right -- a loop nested inside a branch has a range reaching back past the branch that holds it -- which broke quasi-bench under the previous commit. Comparing neighbours is not enough either: the two spans in a straddle are often not adjacent once sorted, since a third can nest inside the first and sort between them, which is /fan-plus. Breaking, so every pin moves in the same pass: the family to 0.104, and quasi-declare to 0.1.13 for `framed`.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01P8ostB2UmZJGj5WjSHRSot
Author: Max Johnson <me@maxj.phd> · 2026-09-08 00:48 UTC
Signed with PGP, not checked
Commit: b5a21fe19e59df423ec786db3ae74979173585d6
Parent: 4ac0c0e
30 files changed, +803 insertions, -334 deletions
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-axum"
3 - version = "0.103.0"
3 + version = "0.104.0"
4 4 description = "The axum host adapter for quasi-router: an HTTP request in, a rendered description out"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -13,14 +13,14 @@
13 13 workspace = true
14 14
15 15 [dependencies]
16 - quasi-router = { path = "../quasi-router", version = "0.103" }
17 - quasi-http = { path = "../quasi-http", version = "0.103" }
16 + quasi-router = { path = "../quasi-router", version = "0.104" }
17 + quasi-http = { path = "../quasi-http", version = "0.104" }
18 18 axum = "0.8.8"
19 19 http = "1.3.1"
20 20 tokio = { version = "1.50.0", features = ["rt"] }
21 21
22 22 [dev-dependencies]
23 - quasi-webview = { path = "../quasi-webview", version = "0.103" }
23 + quasi-webview = { path = "../quasi-webview", version = "0.104" }
24 24 tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread"] }
25 25 tower = { version = "0.5.3", features = ["util"] }
26 26 http-body-util = "0.1.3"
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-basics"
3 - version = "0.103.0"
3 + version = "0.104.0"
4 4 description = "The first-party widget set: named assemblies of primitives, shared across our apps"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -13,7 +13,7 @@
13 13 workspace = true
14 14
15 15 [dependencies]
16 - quasi-router = { path = "../quasi-router", version = "0.103" }
16 + quasi-router = { path = "../quasi-router", version = "0.104" }
17 17 quasi-declare = { path = "../quasi-declare", version = "0.1" }
18 18 makeover-layout = "0.44"
19 19
@@ -21,5 +21,5 @@
21 21 # A widget's guarantees are claims about what a renderer draws, so they are
22 22 # tested against a real one rather than by walking the tree the assembly just
23 23 # built. The webview is the renderer that recognises names today.
24 - quasi-webview = { path = "../quasi-webview", version = "0.103" }
25 - quasi-http = { path = "../quasi-http", version = "0.103" }
24 + quasi-webview = { path = "../quasi-webview", version = "0.104" }
25 + quasi-http = { path = "../quasi-http", version = "0.104" }
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-bench"
3 - version = "0.103.0"
3 + version = "0.104.0"
4 4 description = "What a described screen costs to render, in time and in allocations"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -26,14 +26,14 @@
26 26 askama = ["dep:askama"]
27 27
28 28 [dependencies]
29 - quasi-router = { path = "../quasi-router", version = "0.103" }
30 - quasi-webview = { path = "../quasi-webview", version = "0.103" }
31 - quasi-tui = { path = "../quasi-tui", version = "0.103" }
32 - quasi-immediate = { path = "../quasi-immediate", version = "0.103" }
29 + quasi-router = { path = "../quasi-router", version = "0.104" }
30 + quasi-webview = { path = "../quasi-webview", version = "0.104" }
31 + quasi-tui = { path = "../quasi-tui", version = "0.104" }
32 + quasi-immediate = { path = "../quasi-immediate", version = "0.104" }
33 33 # `Serves` is the trait carrying `screen` and `fragment`, which is what the
34 34 # webview is measured through. Taken directly rather than through quasi-webview
35 35 # because a bench calling a trait method should name the trait it calls.
36 - quasi-http = { path = "../quasi-http", version = "0.103" }
36 + quasi-http = { path = "../quasi-http", version = "0.104" }
37 37 # The macro under measurement. The bench holds the declared copy of the same
38 38 # screen `staging.rs` writes by hand, so the staged column measures what the
39 39 # server actually serves rather than a shape written for a benchmark.
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-declare"
3 - version = "0.1.12"
3 + version = "0.1.13"
4 4 description = "The declare! form: a screen description compiled to Rust at build time."
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -31,4 +31,4 @@
31 31 trybuild = "1"
32 32 # The generated code names the vocabulary, so a case that is meant to COMPILE
33 33 # needs it. A proc-macro crate cannot depend on it outside dev.
34 - quasi-router = { path = "../quasi-router", version = "0.103" }
34 + quasi-router = { path = "../quasi-router", version = "0.104" }
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-http"
3 - version = "0.103.0"
3 + version = "0.104.0"
4 4 description = "The http-shaped seam quasi's webview host adapters share: decoding in, a rendered description out"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -13,6 +13,6 @@
13 13 workspace = true
14 14
15 15 [dependencies]
16 - quasi-router = { path = "../quasi-router", version = "0.103" }
16 + quasi-router = { path = "../quasi-router", version = "0.104" }
17 17 http = "1.3.1"
18 18 form_urlencoded = "1.2.2"
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-immediate"
3 - version = "0.103.0"
3 + version = "0.104.0"
4 4 edition = "2024"
5 5 description = "The immediate-mode renderer for quasi-router: a described screen in, an egui frame out. Immediate mode is the constraint that matters, not the library."
6 6 license = "MIT"
@@ -12,7 +12,7 @@
12 12 categories = ["gui"]
13 13
14 14 [dependencies]
15 - quasi-router = { path = "../quasi-router", version = "0.103" }
15 + quasi-router = { path = "../quasi-router", version = "0.104" }
16 16 # The node drawing, which is the makeover layer's and not this crate's. Every
17 17 # widget here that is not a container comes from it: a screen walk that painted
18 18 # its own meter would be the divergence the suite exists to end, one copy per