Skip to main content

max / quasi

Chrome carries the places the app has, and says what each panel is for `71aa29b4`, ruled (e) by Max 2026-08-22. One panel was enough while the only measured consumer was goingson's timer band. It stopped being enough the moment an app wanted a tab bar as well: goingson's shell is three tabs, a sub-nav under the chosen one, a sync indicator and the band, and `presenting` replaced rather than appended precisely because a renderer handed two anonymous panels would place them by declaration order. Two members rather than a longer list of one kind. `Chrome::nav` holds `Place`s: a key, a label, an address, and one level of places within. A tab bar is not content that happens to be always on screen, it is a set of addresses with names, and saying so is what lets a webview draw tabs, a terminal draw a tab line and an egui host draw a toolbar without any of them being told which. There is no `Role::Navigation` for the same reason. `Chrome::panels` is plural and each carries a `Role`. `Activity` is something the app is doing right now, on screen while it lasts; `Status` is a standing readout of its condition. goingson's two are one of each. The role says what a panel is for and still not where it goes, which is the line `46fc763c` and `4453bf82` drew. WHICH PLACE IS CURRENT IS THE SCREEN'S TO SAY, and this is the part the ruling did not settle. Chrome is built once and held beside the router, so a `current` flag on a Place would be frozen at build time and could never point at where the user is. `Screen::place` names the key instead and the renderer marks the Place that holds it, which is exactly the move `Row::current` makes one level down. The alternative was the renderer matching a place's address against the request path, which needs the path in `Serves::screen` and goes fuzzy the first time a screen carries its view on the address; goingson's Timer is `/timer?work=25&days=7` and its place is `/timer`. THE THREE RENDERERS, each answering placement its own way, which is the whole point of the description not answering it. quasi-webview emits a `nav` of links (middle-click, status bar, landmark: none of which a button gets) with `aria-current="page"` on the current place, and `data-role` beside the `chrome-panel` class rather than instead of it, so a stylesheet written when there was one panel still finds it. quasi-tui draws a tab line across the top, two rows when the current place holds others, reverse video for current, and stacks panels activity-above-status so the app's condition sits where a status line goes. quasi-immediate draws them in the same order down its column. A terminal's places are reachable: `reaches_chromed` walks the nav first because it is drawn first, and only the row actually on screen. A tab line the user can read and cannot use would be worse than none. An app declaring no nav and no panels gets what it always got, in all three. 0.53.0, breaking. Consumers forward-fixed in the same pass: goingson declares its band `Role::Activity`, and goingson, audiofiles and the MNW server all move their requirement. The MNW server is the one the `Chrome` grep missed and the pre-push gate caught.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-22 15:45 UTC
Signed with PGP, not checked
Commit: c3c21308fe69736c0ebf585dbb09c569385a0832
Parent: 42d9263
29 files changed, +902 insertions, -135 deletions
M Cargo.lock +15 -15
@@ -3414,11 +3414,11 @@
3414 3414
3415 3415 [[package]]
3416 3416 name = "quasi"
3417 - version = "0.52.0"
3417 + version = "0.53.0"
3418 3418
3419 3419 [[package]]
3420 3420 name = "quasi-axum"
3421 - version = "0.52.0"
3421 + version = "0.53.0"
3422 3422 dependencies = [
3423 3423 "axum",
3424 3424 "http",
@@ -3432,7 +3432,7 @@
3432 3432
3433 3433 [[package]]
3434 3434 name = "quasi-basics"
3435 - version = "0.52.0"
3435 + version = "0.53.0"
3436 3436 dependencies = [
3437 3437 "makeover-layout",
3438 3438 "quasi-http",
@@ -3442,7 +3442,7 @@
3442 3442
3443 3443 [[package]]
3444 3444 name = "quasi-bench"
3445 - version = "0.52.0"
3445 + version = "0.53.0"
3446 3446 dependencies = [
3447 3447 "dhat",
3448 3448 "makeover",
@@ -3457,7 +3457,7 @@
3457 3457
3458 3458 [[package]]
3459 3459 name = "quasi-http"
3460 - version = "0.52.0"
3460 + version = "0.53.0"
3461 3461 dependencies = [
3462 3462 "form_urlencoded",
3463 3463 "http",
@@ -3466,7 +3466,7 @@
3466 3466
3467 3467 [[package]]
3468 3468 name = "quasi-immediate"
3469 - version = "0.52.0"
3469 + version = "0.53.0"
3470 3470 dependencies = [
3471 3471 "docengine",
3472 3472 "egui",
@@ -3476,7 +3476,7 @@
3476 3476
3477 3477 [[package]]
3478 3478 name = "quasi-notifs"
3479 - version = "0.52.0"
3479 + version = "0.53.0"
3480 3480 dependencies = [
3481 3481 "quasi-router",
3482 3482 "synckit-config",
@@ -3484,7 +3484,7 @@
3484 3484
3485 3485 [[package]]
3486 3486 name = "quasi-router"
3487 - version = "0.52.0"
3487 + version = "0.53.0"
3488 3488 dependencies = [
3489 3489 "makeover-layout",
3490 3490 ]
@@ -3501,7 +3501,7 @@
3501 3501
3502 3502 [[package]]
3503 3503 name = "quasi-tauri"
3504 - version = "0.52.0"
3504 + version = "0.53.0"
3505 3505 dependencies = [
3506 3506 "http",
3507 3507 "quasi-http",
@@ -3514,7 +3514,7 @@
3514 3514
3515 3515 [[package]]
3516 3516 name = "quasi-tui"
3517 - version = "0.52.0"
3517 + version = "0.53.0"
3518 3518 dependencies = [
3519 3519 "docengine",
3520 3520 "makeover",
@@ -3526,7 +3526,7 @@
3526 3526
3527 3527 [[package]]
3528 3528 name = "quasi-webview"
3529 - version = "0.52.0"
3529 + version = "0.53.0"
3530 3530 dependencies = [
3531 3531 "docengine",
3532 3532 "makeover-layout",
@@ -6201,10 +6201,6 @@
6201 6201 name = "quasi-type"
6202 6202 version = "0.1.0"
6203 6203
6204 - [[patch.unused]]
6205 - name = "synckit-client"
6206 - version = "0.8.1"
6207 -
6208 6204 [[patch.unused]]
6209 6205 name = "kberg"
6210 6206 version = "0.1.0"
@@ -6220,3 +6216,7 @@
6220 6216 [[patch.unused]]
6221 6217 name = "tagtree"
6222 6218 version = "0.4.1"
6219 +
6220 + [[patch.unused]]
6221 + name = "synckit-client"
6222 + version = "0.8.1"
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-axum"
3 - version = "0.52.0"
3 + version = "0.53.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.52.0" }
17 - quasi-http = { path = "../quasi-http", version = "0.52.0" }
16 + quasi-router = { path = "../quasi-router", version = "0.53.0" }
17 + quasi-http = { path = "../quasi-http", version = "0.53.0" }
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.52.0" }
23 + quasi-webview = { path = "../quasi-webview", version = "0.53.0" }
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.52.0"
3 + version = "0.53.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,12 +13,12 @@
13 13 workspace = true
14 14
15 15 [dependencies]
16 - quasi-router = { path = "../quasi-router", version = "0.52.0" }
16 + quasi-router = { path = "../quasi-router", version = "0.53.0" }
17 17 makeover-layout = "0.35.0"
18 18
19 19 [dev-dependencies]
20 20 # A widget's guarantees are claims about what a renderer draws, so they are
21 21 # tested against a real one rather than by walking the tree the assembly just
22 22 # built. The webview is the renderer that recognises names today.
23 - quasi-webview = { path = "../quasi-webview", version = "0.52.0" }
24 - quasi-http = { path = "../quasi-http", version = "0.52.0" }
23 + quasi-webview = { path = "../quasi-webview", version = "0.53.0" }
24 + quasi-http = { path = "../quasi-http", version = "0.53.0" }
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-bench"
3 - version = "0.52.0"
3 + version = "0.53.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
@@ -22,13 +22,13 @@
22 22 count = ["dep:dhat"]
23 23
24 24 [dependencies]
25 - quasi-router = { path = "../quasi-router", version = "0.52.0" }
26 - quasi-webview = { path = "../quasi-webview", version = "0.52.0" }
27 - quasi-tui = { path = "../quasi-tui", version = "0.52.0" }
25 + quasi-router = { path = "../quasi-router", version = "0.53.0" }
26 + quasi-webview = { path = "../quasi-webview", version = "0.53.0" }
27 + quasi-tui = { path = "../quasi-tui", version = "0.53.0" }
28 28 # `Serves` is the trait carrying `screen` and `fragment`, which is what the
29 29 # webview is measured through. Taken directly rather than through quasi-webview
30 30 # because a bench calling a trait method should name the trait it calls.
31 - quasi-http = { path = "../quasi-http", version = "0.52.0" }
31 + quasi-http = { path = "../quasi-http", version = "0.53.0" }
32 32 makeover-layout = "0.35.0"
33 33 makeover-tui = { version = "0.33.0", features = ["theme"] }
34 34 # Only to load a bundled theme file. `makeover_tui::Theme` is `#[non_exhaustive]`,
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-http"
3 - version = "0.52.0"
3 + version = "0.53.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.52.0" }
16 + quasi-router = { path = "../quasi-router", version = "0.53.0" }
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.52.0"
3 + version = "0.53.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.52.0" }
15 + quasi-router = { path = "../quasi-router", version = "0.53.0" }
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
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-notifs"
3 - version = "0.52.0"
3 + version = "0.53.0"
4 4 description = "Declared notification kinds and the registry that holds them: what a notification says and what it is for, apart from how it reaches a person"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -24,5 +24,5 @@
24 24 describe = ["dep:quasi-router"]
25 25
26 26 [dependencies]
27 - quasi-router = { path = "../quasi-router", version = "0.52.0", optional = true }
27 + quasi-router = { path = "../quasi-router", version = "0.53.0", optional = true }
28 28 synckit-config = { git = "https://makenot.work/git/max/synckit.git", version = "0.2", optional = true }