Skip to main content

max / makeover-layout

3.9 KB · 86 lines History Blame Raw
1 # makeover-layout
2
3 The renderer-agnostic half of the make-family design system.
4
5 `makeover` answers *what colour*, and varies by theme. `makeover-geometry`
6 answers *how much space*, and varies by density and surface. This crate answers
7 *what the thing is*, and varies by nothing.
8
9 ## The deferral rule
10
11 A description names intents and relationships, never values. Say `Fill::Raised`,
12 never `#D9DDF4`. Say `Gap::Peer`, never `6px`. What is left once colour and
13 spacing are deferred is composition: which edges are lit, what inverts on press,
14 what nests in what.
15
16 The constraint that shapes it: a renderer that can only paint rectangles has to
17 be able to express the result. egui has no `box-shadow: inset` and one stroke per
18 widget with no per-side control. A terminal has box-drawing characters and one
19 cell of resolution, and cannot draw a two-tone lit edge at all. So this crate
20 names the intent, and each renderer picks an expression it can produce, including
21 dropping half of one.
22
23 ## What is here
24
25 **Depth**: `Bevel`, `Edge`, `Fill`, `Depth`. Fill and bevel are named together,
26 because naming them apart is what let them disagree. Every consumer had at least
27 one region carrying a raised bevel over a recessed fill; audiofiles fixed it and
28 wrote the bug down, Balanced Breakfast still had twelve of them a year later.
29 `Depth` makes that unrepresentable.
30
31 **Components**: `Token` (a badge does not answer a click, a chip does), `Notice`
32 (a toast is transient, a banner is persistent), `RowPart`, `Heading`, `Selector`,
33 `Readiness`, and `Tone`, the one intent family they share.
34
35 **Schemas**: `Field` for forms, `Column` for lists and tables. A column carries a
36 drop priority, which is what replaces addressing columns by position. Both
37 webview apps hide narrow-screen columns with `nth-child`, so inserting a column
38 silently hides the wrong one.
39
40 **Structure**: `Region` for the parts of a screen, `Arrangement` for how a screen
41 is put together. Two arrangements, because the two apps have two. `Showing` says
42 how many of a region's children are visible at once, which is what lets a
43 renderer derive a tab strip or a prev/next row for itself instead of recognising
44 a widget by name.
45
46 The vocabulary was read off audiofiles, the only implementation written by a
47 consumer with no CSS, then checked against both webview apps.
48
49 ## What is not here, on purpose
50
51 Validation. `Field` describes fields, not constraints. Neither app has a shared
52 story, and a schema that describes one without the other acquires a constraint
53 layer per app, which is how the divergence this crate exists to end got started.
54
55 ## Where the description stops
56
57 The bespoke widgets: a day-plan timeline, a kanban board, a calendar. A
58 description expressive enough to produce those is not a description any more, it
59 is a widget library with one app on top. Generate the boring 80% so the bespoke
60 20% gets the attention.
61
62 `Region::Bespoke` states that limit instead of hiding it. The description names
63 the place, the app owns the contents, and a screen with a timeline in it is still
64 a whole screen. Without that member the description would cover only the boring
65 screens, and the interesting ones would need a second path beside the router.
66 One opaque member, and `Region::described()` is how a renderer tells it from the
67 rest.
68
69 ## Status
70
71 On crates.io at 0.2.0, published 2026-07-29. 0.1.0 went out the day before, and
72 the sequencing decision behind it was not to publish until a second renderer had
73 exercised the vocabulary; three had, and it cost the description exactly one
74 deletion (`Fill::fallback`, which turned out to be renderer policy).
75
76 0.2.0 went out on a different basis: no renderer has been through the components,
77 schemas or structure yet. So expect the first renderer to force a correction, and
78 expect that correction to be a 0.3.0 with a migration rather than an edit.
79
80 Design lives in the wiki note `makeover-layout`; the backlog is in GoingsOn under
81 the project of the same name.
82
83 ## Licence
84
85 MIT.
86