Skip to main content

max / makeover-touch

Strip historical narrative from documentation Remove what a doc used to say, when it changed, the incidents that justified a rule, finished migration narration, and counts and versions that rot. State the rules in the present tense instead. Keep every instruction, prohibition and threshold, and keep the measurements that make a rule actionable. Public-facing docs keep their explanatory voice.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01MptwXZ8k65v19rFmdGAyki
Author: Max Johnson <me@maxj.phd> · 2026-08-31 01:51 UTC
Signed with PGP, not checked
Commit: 7a1d488b65e05fcbe2d082500012a7d132d71425
Parent: 0a01201
2 files changed, +27 insertions, -38 deletions
M README.md +9 -12
@@ -31,8 +31,7 @@
31 31 The bottom three are the roughly 43% no spacing scale can retire. `display:
32 32 none` on a keyboard hint says the affordance does not exist on touch. No amount
33 33 of gap retuning expresses that, and a scale that tried would be putting a
34 - product claim on a measurement axis, which is what the July 2026 Touch
35 - demolition was for.
34 + product claim on a measurement axis.
36 35
37 36 ## What is here
38 37
@@ -53,16 +52,16 @@
53 52
54 53 `column_cutoff(size)` closes the one seam neither neighbour could: layout defines
55 54 the priority ladder and `Column::kept_at`, geometry defines the boundaries, and
56 - nothing said which cutoff a compact window uses. Both webview apps answered it
57 - with `nth-child` on an ordinal, so inserting a column silently hid the wrong one.
55 + nothing else says which cutoff a compact window uses. Answering it with
56 + `nth-child` on an ordinal means inserting a column silently hides the wrong one.
58 57
59 58 ## The rules the tests hold
60 59
61 60 **Density gates only what the contact patch touches.** Hovering, and the
62 61 keyboard chrome documenting shortcuts a touch surface cannot send. Not how much
63 62 screen there is: a phone is small *and* touch, a tablet is big *and* touch.
64 - Putting a screen-budget claim on the input device is the specific failure that
65 - produced this crate.
63 + Putting a screen-budget claim on the input device is the
64 + failure this crate exists to prevent.
66 65
67 66 **Touch never gains an affordance pointer lacks.** Touch is derived from pointer
68 67 by subtracting what a fingertip cannot do, so it loses members and never gains
@@ -83,11 +82,10 @@
83 82 600 and 840. This crate adds no third axis, no fourth class and no breakpoint of
84 83 its own.
85 84
86 - **A navigation shell fork.** goingson currently carries two, concentrated in
85 + **A navigation shell fork.** goingson carries two, concentrated in
87 86 `.app-header`, `.tab`, `.tab-navigation`, `.pill-nav`, `.saved-views-sidebar`
88 87 and `.modal-container`. That is not one shell adapting, it is two shells, and
89 - choosing to build two is a product decision. goingson's own restructure is how
90 - it stops being true.
88 + choosing to build two is a product decision the app owns.
91 89
92 90 **Which class applies.** The app decides, from a measured width and from what it
93 91 already knows about the input. This crate takes both as arguments and never
@@ -99,9 +97,8 @@
99 97
100 98 ## Status
101 99
102 - Seeded at 0.1.0, unpublished, no renderer has been through it. The vocabulary is
103 - six members and the intent is to stop there: `makeover-layout`'s own warning is
104 - that guessing at eight is how a description becomes a framework.
100 + Unpublished. The vocabulary is six members and the intent is to stop there:
101 + guessing at an eighth is how a description becomes a framework.
105 102
106 103 Design lives in the wiki note `makeover-touch`; the backlog is in GoingsOn under
107 104 the project of the same name.
M src/lib.rs +18 -26
@@ -29,12 +29,10 @@
29 29 //! | **reposition** | **6%** | **20%** | **this crate** |
30 30 //! | **appearance** | **1%** | **17%** | **this crate** |
31 31 //!
32 - //! The bottom three are the roughly 43% that no spacing scale can retire, and
33 - //! trying is the mistake this whole family already made once. `display: none`
34 - //! on a keyboard hint says *the affordance does not exist on touch*. No amount
35 - //! of gap retuning expresses that, and a scale that tried would be smuggling a
36 - //! product claim onto a measurement axis — which is exactly what the 2026-07-29
37 - //! Touch demolition was for.
32 + //! The bottom three are the roughly 43% that no spacing scale can retire.
33 + //! `display: none` on a keyboard hint says *the affordance does not exist on
34 + //! touch*. No amount of gap retuning expresses that, and a scale that tried
35 + //! would be smuggling a product claim onto a measurement axis.
38 36 //!
39 37 //! Two of the eight members are not in that census at all, and the exception is
40 38 //! worth stating rather than leaving to be noticed. [`Affordance::Gesture`] and
@@ -68,26 +66,21 @@
68 66 //!
69 67 //! That separation is asserted, not merely intended, by
70 68 //! `density_gates_only_what_the_contact_patch_touches`. Putting a screen-budget
71 - //! claim on the input device is the specific failure that produced this crate,
72 - //! and re-introducing it should have to come to the test and say so.
69 + //! claim on the input device is the failure this crate exists to prevent, and
70 + //! re-introducing it has to come to the test and say so.
73 71 //!
74 - //! # Both densities gain something (0.3.0)
72 + //! # Both densities gain something
75 73 //!
76 - //! Until 0.3.0 this crate asserted that touch is pointer minus what a fingertip
77 - //! cannot do — availability only ever subtracted as you moved from
78 - //! [`Density::Pointer`] to [`Density::Touch`], and a test called
79 - //! `touch_never_gains_an_affordance_pointer_lacks` said so. That claim is
80 - //! withdrawn, deliberately, because it left a hole the crate could not name:
74 + //! Touch is not pointer minus what a fingertip cannot do.
81 75 //! [`Affordance::Hover`]'s own doc says a fingertip has no hover state *and that
82 - //! something else has to carry the same actions*, and nothing here was allowed
83 - //! to be that something. [`Affordance::Anchored`] and [`Affordance::Overflow`]
84 - //! compensate on the size axis; nothing compensated on the density axis.
76 + //! something else has to carry the same actions*, so something here has to be
77 + //! that something. [`Affordance::Anchored`] and [`Affordance::Overflow`]
78 + //! compensate on the size axis; [`Affordance::Gesture`] and
79 + //! [`Affordance::Haptic`] compensate on the density axis, and both are gained
80 + //! by touch rather than lost to it.
85 81 //!
86 - //! [`Affordance::Gesture`] and [`Affordance::Haptic`] are that compensation, and
87 - //! both are gained by touch rather than lost to it.
88 - //!
89 - //! The claim is replaced rather than dropped. [`Affordance::gained_by`] makes
90 - //! each member declare which density it belongs to, and
82 + //! [`Affordance::gained_by`] makes each member declare which density it belongs
83 + //! to, and
91 84 //! `a_density_member_is_available_on_exactly_the_density_it_declares` checks the
92 85 //! declaration against the rule. So a new member still cannot quietly invert:
93 86 //! it has to say which way it goes, in code, and the test is where a wrong
@@ -248,11 +241,10 @@
248 241 /// Which [`Density`] this affordance belongs to, or `None` when it reads the
249 242 /// screen budget instead.
250 243 ///
251 - /// The replacement for the withdrawn one-directional rule (see the crate
252 - /// doc). Until 0.3.0 the direction was a property of the whole crate and a
253 - /// test enforced it globally; now each member declares its own, and
244 + /// Each member declares its own direction, and
254 245 /// `a_density_member_is_available_on_exactly_the_density_it_declares` holds
255 - /// the declaration to the rule.
246 + /// the declaration to the rule. There is no crate-wide one-directional
247 + /// rule: see the crate doc.
256 248 ///
257 249 /// Exposed rather than kept private for the same reason [`Self::reads_density`]
258 250 /// is: it is the crate's claim about itself, and a renderer that has one