Skip to main content

max / makeover-webview

Render the token strip, and pay off the lockstep prediction part_class carried a comment saying RowPart was the one closed enum left and that a new member would stop this compiling, calling that "the same lockstep break non_exhaustive was added elsewhere to end". makeover-layout 0.9.0 ended it, so the prediction is paid off rather than waited for. The fallback is what non_exhaustive costs: a member added upstream lands as a bare row-part class with no rule of its own, which is a thing rendering plainly rather than a build that stops. A test asserts the fallback exists, so nobody reads the match as closed and writes unreachable!() into it. row_rules stops iterating a derived list, since there is nothing to iterate off an open enum, and takes part_class rather than repeating the same match a second time. The token strip takes no colour of its own, for the reason actions do not: each token carries its own tone, and a rule on the strip would fight the things sitting in it. Carries the unreleased doc correction from 7833dd9, which said list was not implemented nine days after it landed.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-09 01:57 UTC
Signed with PGP, not checked
Commit: c3a9d2967e43292ae2b98acc91edc7c5fddf4388
Parent: 7833dd9
3 files changed, +49 insertions, -17 deletions
M Cargo.toml +2 -2
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "makeover-webview"
3 - version = "0.17.1"
3 + version = "0.18.0"
4 4 edition = "2024"
5 5 description = "The webview renderer for makeover-layout. Emits CSS, and is the one renderer that needs no palette: var() is the late binding, so resolution stays with the browser."
6 6 license = "MIT"
@@ -11,7 +11,7 @@
11 11 # in 0.8.2. Declared as "0.8" from 0.16.1, where the radio landed, so a consumer
12 12 # whose lock already held 0.8.0 got a resolve that satisfied the pin and failed
13 13 # to compile. makeover-build is where that surfaced, one release later.
14 - makeover-layout = "0.8.2"
14 + makeover-layout = "0.9.0"
15 15 # The capability axis. `makeover-touch` decides whether a hover rule should be
16 16 # gated at all; `makeover-geometry` spells the gate as a media condition. Both
17 17 # answers are owned elsewhere and neither is re-derived here.
M src/lib.rs +34 -10
@@ -196,6 +196,7 @@
196 196 pub mod form;
197 197 pub mod list;
198 198
199 + use crate::list::part_class;
199 200 use makeover_geometry::{Density, SizeClass};
200 201 // Re-exported rather than redefined. An app assembling its own stylesheet out
201 202 // of this crate's pieces needs the same layer name, and most such apps depend
@@ -649,7 +650,13 @@
649 650 css
650 651 }
651 652
652 - /// The four parts of a list row.
653 + /// The parts of a list row.
654 + ///
655 + /// The list is written out rather than derived because `RowPart` is
656 + /// `#[non_exhaustive]` as of makeover-layout 0.9.0, so there is nothing to
657 + /// iterate. A member added upstream emits no rule until it is named here, which
658 + /// is the trade `non_exhaustive` makes: a silent gap instead of a build break.
659 + /// [`part_class`] carries the same list and the same obligation.
653 660 fn row_rules(opts: &Emit) -> String {
654 661 let mut css = String::new();
655 662 let row = class("row", opts);
@@ -658,19 +665,16 @@
658 665 RowPart::Secondary,
659 666 RowPart::Meta,
660 667 RowPart::Actions,
668 + RowPart::Tokens,
661 669 ] {
662 - let name = match part {
663 - RowPart::Primary => "row-primary",
664 - RowPart::Secondary => "row-secondary",
665 - RowPart::Meta => "row-meta",
666 - RowPart::Actions => "row-actions",
667 - };
668 - let c = class(name, opts);
670 + let c = class(part_class(part), opts);
669 671
670 672 // Actions carry controls rather than text, and `RowPart::intent` says
671 673 // so by returning the same intent inheriting already gives. Pinning it
672 - // would be louder than saying nothing.
673 - if !matches!(part, RowPart::Actions) {
674 + // would be louder than saying nothing. Tokens answer alike, for their
675 + // own reason: each token carries its own tone, and a colour on the
676 + // strip would fight the things sitting in it.
677 + if !matches!(part, RowPart::Actions | RowPart::Tokens) {
674 678 let _ = writeln!(css, ".{c} {{\n color: var(--{});\n}}", part.intent());
675 679 }
676 680
@@ -1272,6 +1276,26 @@
1272 1276 assert!(!css.contains(".row-actions {\n color:"));
1273 1277 }
1274 1278
1279 + #[test]
1280 + fn the_token_strip_takes_no_colour_of_its_own() {
1281 + // makeover-layout 0.9.0. A token carries its own tone, so a colour on
1282 + // the strip would be a rule fighting the things sitting in it -- the
1283 + // same reasoning as actions, reached for a different reason.
1284 + let css = row_rules(&Emit::default());
1285 + assert!(!css.contains(".row-tokens {\n color:"));
1286 + }
1287 +
1288 + #[test]
1289 + fn an_unknown_row_part_renders_plainly_rather_than_failing_to_build() {
1290 + // What `#[non_exhaustive]` bought and what it cost. `part_class` can no
1291 + // longer be exhaustive, so a member added upstream lands as a bare
1292 + // class with no rule instead of stopping the build. Asserting the
1293 + // fallback exists is what keeps it from being written as `unreachable!`
1294 + // by someone who reads the match as closed.
1295 + assert_eq!(part_class(RowPart::Tokens), "row-tokens");
1296 + assert_eq!(part_class(RowPart::Meta), "row-meta");
1297 + }
1298 +
1275 1299 #[test]
1276 1300 fn the_progress_trough_is_a_well() {
1277 1301 let css = progress_rules(&Emit::default());
M src/list.rs +13 -5
@@ -188,16 +188,24 @@
188 188
189 189 /// The class for a row part.
190 190 ///
191 - /// Exhaustive, unlike the matches on [`Width`] and [`Priority`] above:
192 - /// `RowPart` is the one vocabulary in this module that is still a closed enum.
193 - /// If it ever gains a member this stops compiling, which is the same lockstep
194 - /// break `non_exhaustive` was added elsewhere to end.
195 - fn part_class(part: RowPart) -> &'static str {
191 + /// This comment used to say `RowPart` was the one closed enum left here, and
192 + /// that gaining a member would stop this compiling — "the same lockstep break
193 + /// `non_exhaustive` was added elsewhere to end". makeover-layout 0.9.0 ended
194 + /// it: the enum gained [`RowPart::Tokens`] and `#[non_exhaustive]` in the same
195 + /// release, so the prediction was paid off rather than waited for.
196 + ///
197 + /// The fallback is what that costs. A member added upstream lands here as a
198 + /// bare `row-part` with no rule of its own, which is a thing rendering plainly
199 + /// rather than a build that stops. Grep this function when adopting a new
200 + /// makeover-layout.
201 + pub(crate) fn part_class(part: RowPart) -> &'static str {
196 202 match part {
197 203 RowPart::Primary => "row-primary",
198 204 RowPart::Secondary => "row-secondary",
199 205 RowPart::Meta => "row-meta",
200 206 RowPart::Actions => "row-actions",
207 + RowPart::Tokens => "row-tokens",
208 + _ => "row-part",
201 209 }
202 210 }
203 211