Skip to main content

max / makenotwork

Describe the library tab strip Shape 2, step 1 of five (`6b24f2df`), and the first described tab strip in the tree. `pages/library.html` loses 64 lines of hand-written tab markup and prints one value. `src/quasi/library_tabs.rs` is an Askama entry point rather than a mounted screen, the shape `widgets::carousel` already had: the library page is still an Askama document and this is one region inside it. Every tab is a `RegionKind::Bespoke`, a place and nothing else, because what lands in one is Askama's markup rather than the description's. That is Max's ruling on this shape -- describe the strip, leave the panels as routes -- and it is what lets all five panel routes stay untouched. The page still makes zero panel requests on load and one per press, which is the whole safety argument and so is the first thing asserted. The strip button carries its panel's address and the panels emit no load trigger (quasi 0.31, `dfbc88ce`), and the shown panel comes with the document, rendered by the handler from `LibraryPurchasesTabTemplate` exactly as the `{% include %}` did. Each unshown tab says what its answer replaces. Three of the five panels are plain Askama routes that name no region, and htmx would otherwise swap the answer into the button that was pressed -- the same failure `DELETE /api/users/me/ssh-keys` had. The two described panels are left to name their own region, so their regions stopped being `tab-content` and became their panel ids. Frame movement is `core/showing.ts`, lifted out of the carousel island, which was already this loop written for one caller; `showing.logic.ts` came out of `islands/` with it, since core reaching up into islands is the layering backwards. Arrow keys on a strip click the tab rather than revealing it, or the reader lands on a panel that was never fetched. Two things the markup said that the vocabulary cannot: the tablist's `aria-label` and the Feed tab's `title`. Dropped rather than smuggled back as text, and filed as quasi `aad33ecc`. One reader-visible change, and it is the ruling working: makeover renders a menu run as `flex-wrap: wrap`, so a narrow viewport wraps the strip instead of folding tabs behind a More button. The menu's construction was explicitly left undescribed. Said on the module so nobody reads the missing button as a bug. The integration suite caught the one thing that broke, which is what it is for: its `SCREENS` table transcribed the region names, so when the two library panels stopped sharing `tab-content` the table still said they did. It reads the constants now. Checked rather than assumed: nothing anywhere links to `#tab-purchases` or a sibling, so hash restore loses nothing by the described buttons carrying no ids, and hover preload still applies since they keep makeover's `tab` class. The dead-vocabulary seal drops 33 to 32 -- this is the first `.run-menu` the server emits, and the `.run` case build.rs documented as hypothetical stopped being one.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-19 02:18 UTC
Signed with PGP, not checked
Commit: 3d3442d66c87e6de60ad74e53e9b74f5aee7757b
Parent: 172a25f
15 files changed, +536 insertions, -152 deletions
M server/build.rs +6 -1
@@ -415,7 +415,12 @@
415 415 /// rather than fixed for the same reason.
416 416 ///
417 417 /// It tightens when the discover sidebar ports, not before.
418 - const DEAD_VOCABULARY_HIGH_WATER: usize = 33;
418 + ///
419 + /// 33 to 32 on 2026-08-18: the library tab strip is described (`6b24f2df`), and
420 + /// the run it declares its overflow on is the first `.run-menu` this server
421 + /// emits. The `.run` case documented above stopped being hypothetical, which is
422 + /// the ratchet working rather than an exception to it.
423 + const DEAD_VOCABULARY_HIGH_WATER: usize = 32;
419 424
420 425 /// Every file that can carry a class name.
421 426 ///
@@ -45,7 +45,7 @@
45 45 pub const LIBRARY_PATH: &str = "/library/tabs/communities";
46 46
47 47 /// The region the library's tab nav targets.
48 - const LIBRARY_REGION: &str = "tab-content";
48 + pub const LIBRARY_REGION: &str = "library-communities";
49 49
50 50 /// The settings section's switch. `QUASI_SCREENS=user_forums`.
51 51 pub const SETTINGS_SCREEN: &str = "user_forums";
@@ -273,9 +273,22 @@
273 273 // Two navs, two regions, and they are genuinely different: the library
274 274 // swaps its tab pane, the settings section swaps the settings body. If
275 275 // either disagrees the tab swaps into nothing, and no other test sees it.
276 - let library = include_str!("../../templates/pages/library.html");
277 - assert!(library.contains(&format!("hx-get=\"{LIBRARY_PATH}\"")));
278 - assert!(library.contains(&format!("hx-target=\"#{LIBRARY_REGION}\"")));
276 + // The library half reads the described strip rather than the page, which
277 + // stopped holding the nav when the strip was described (`6b24f2df`).
278 + let library = crate::quasi::library_tabs::html(
279 + &crate::config::QuasiScreens::default(),
280 + "",
281 + true,
282 + true,
283 + );
284 + assert!(
285 + library.contains(&format!("hx-get=\"{LIBRARY_PATH}\"")),
286 + "{library}"
287 + );
288 + assert!(
289 + library.contains(&format!("id=\"{LIBRARY_REGION}\"")),
290 + "{library}"
291 + );
279 292
280 293 let settings = include_str!("../../templates/partials/tabs/user_settings.html");
281 294 assert!(settings.contains(&format!("hx-get=\"{SETTINGS_PATH}\"")));
@@ -42,7 +42,7 @@
42 42 pub const PATH: &str = "/library/tabs/contacts";
43 43
44 44 /// The region the answer replaces: the pane the library's tab nav targets.
45 - const REGION: &str = "tab-content";
45 + pub const REGION: &str = "library-contacts";
46 46
47 47 /// The address a revoke calls, relative to this screen's own nest.
48 48 const REVOKE: &str = "/revoke/{seller_id}";
@@ -298,16 +298,27 @@
298 298 }
299 299
300 300 #[test]
301 - fn the_region_matches_what_the_library_nav_targets() {
301 + fn the_region_matches_the_panel_the_library_strip_gives_this_tab() {
302 302 // The router says what it changed, through HX-Retarget. If this and the
303 - // template's hx-target ever disagree the tab swaps into nothing, and
304 - // that failure is invisible to every other test.
305 - let nav = include_str!("../../templates/pages/library.html");
306 - assert!(
307 - nav.contains(&format!("hx-target=\"#{REGION}\"")),
308 - "the library nav targets #{REGION}"
303 + // strip's panel id ever disagree the tab swaps into nothing, and that
304 + // failure is invisible to every other test.
305 + //
306 + // Read off the strip rather than off `library.html`, which stopped
307 + // holding the nav when the strip was described (`6b24f2df`). Both halves
308 + // are Rust now, so the id is shared rather than transcribed -- and this
309 + // still earns its keep, because `library_tabs` names the panel and this
310 + // module names the region and nothing but this asserts they agree.
311 + let strip = crate::quasi::library_tabs::html(
312 + &crate::config::QuasiScreens::default(),
313 + "",
314 + true,
315 + true,
309 316 );
310 - assert!(nav.contains(&format!("hx-get=\"{PATH}\"")));
317 + assert!(
318 + strip.contains(&format!("id=\"{REGION}\"")),
319 + "the library strip has no panel called {REGION}:\n{strip}"
320 + );
321 + assert!(strip.contains(&format!("hx-get=\"{PATH}\"")), "{strip}");
311 322 }
312 323
313 324 #[test]
@@ -34,6 +34,7 @@
34 34 pub mod buyer_contacts;
35 35 pub mod forum_memberships;
36 36 pub mod library_contacts;
37 + pub mod library_tabs;
37 38 pub mod ssh_keys;
38 39 pub mod user_analytics;
39 40 pub mod widgets;
@@ -9,70 +9,8 @@
9 9 <div class="container">
10 10 <h1 class="page-title">Your Library</h1>
11 11
12 - <div class="tabs" role="tablist" aria-label="Library sections">
13 - <button class="tab chosen"
14 - role="tab"
15 - aria-selected="true"
16 - aria-controls="tab-content"
17 - id="tab-purchases"
18 - hx-get="/library/tabs/purchases"
19 - hx-target="#tab-content"
20 - hx-swap="innerHTML"
21 - hx-indicator="#tab-spinner"
22 - data-action="onSetActiveTab">Purchases</button>
23 - <button class="tab"
24 - role="tab"
25 - aria-selected="false"
26 - aria-controls="tab-content"
27 - id="tab-feed"
28 - title="Updates from creators you follow"
29 - hx-get="/library/tabs/feed"
30 - hx-target="#tab-content"
31 - hx-swap="innerHTML"
32 - hx-indicator="#tab-spinner"
33 - data-action="onSetActiveTab">Feed</button>
34 - <button class="tab"
35 - role="tab"
36 - aria-selected="false"
37 - aria-controls="tab-content"
38 - id="tab-collections"
39 - hx-get="/library/tabs/collections"
40 - hx-target="#tab-content"
41 - hx-swap="innerHTML"
42 - hx-indicator="#tab-spinner"
43 - data-action="onSetActiveTab">Collections</button>
44 - {% if has_mt_memberships %}
45 - <button class="tab"
46 - role="tab"
47 - aria-selected="false"
48 - aria-controls="tab-content"
49 - id="tab-communities"
50 - hx-get="/library/tabs/communities"
51 - hx-target="#tab-content"
52 - hx-swap="innerHTML"
53 - hx-indicator="#tab-spinner"
54 - data-action="onSetActiveTab">Communities</button>
55 - {% endif %}
56 - {% if let Some(user) = session_user %}{% if user.can_create_projects %}
57 - <button class="tab"
58 - role="tab"
59 - aria-selected="false"
60 - aria-controls="tab-content"
61 - id="tab-contacts"
62 - hx-get="/library/tabs/contacts"
63 - hx-target="#tab-content"
64 - hx-swap="innerHTML"
65 - hx-indicator="#tab-spinner"
66 - data-action="onSetActiveTab">Contacts</button>
67 - {% endif %}{% endif %}
68 - <span id="tab-spinner" class="htmx-indicator tab-spinner-indicator" aria-live="polite"> Loading...</span>
69 - </div>
12 + {{ tabs|safe }}
70 13
71 - <div id="tab-content" class="tab-content active"
72 - role="tabpanel"
73 - aria-labelledby="tab-purchases">
74 - {% include "partials/tabs/library_purchases.html" %}
75 - </div>
76 14 </div>
77 15 {% endblock %}
78 16