makeover-layout 0.52.3

The renderer-agnostic half of the make-family design system: what a thing IS, named as intents and relationships and never as values. Colour defers to makeover, spacing to makeover-geometry; what is left is composition, plus which affordances exist at a given input class and window size.
Documentation

makeover-layout

The renderer-agnostic half of the make-family design system.

makeover answers what colour, and varies by theme. makeover-geometry answers how much space, and varies by density and surface. This crate answers what the thing is, and varies by nothing.

The deferral rule

A description names intents and relationships, never values. Say Fill::Raised, never #D9DDF4. Say Gap::Peer, never 6px. What is left once colour and spacing are deferred is composition: which edges are lit, what inverts on press, what nests in what.

The constraint that shapes it: a renderer that can only paint rectangles has to be able to express the result. egui has no box-shadow: inset and one stroke per widget with no per-side control. A terminal has box-drawing characters and one cell of resolution, and cannot draw a two-tone lit edge at all. So this crate names the intent, and each renderer picks an expression it can produce, including dropping half of one.

What is here

Depth: Bevel, Edge, Fill, Depth, State. Fill and bevel are named together, because naming them apart lets them disagree: a region can carry a raised bevel over a recessed fill. Depth makes that unrepresentable.

Components: Token (a badge does not answer a click, a chip does), Notice (a toast is transient, a banner is persistent), Act, RowPart, Flow, Nesting, Heading, Selector, Facet, Fact, Readiness, and Tone, the one intent family they share.

Schemas: Field and Choice for forms, Column for lists and tables. A column carries a drop priority, which replaces addressing columns by position: addressing by nth-child means inserting a column silently hides the wrong one on a narrow screen. budget and cutoff_for are the one narrowing rule every native renderer applies, and Sizing holds a renderer's lengths per column.

Figures: Meter, Figure, Chart, Bar, and Track with its Span and Placement for anything laid on a time axis.

Structure: Region for the parts of a screen, Arrangement for how a screen is put together (list-detail, sidebar plus content, or a single region), Share for how much room the first region takes, and Measure for how wide content runs. Showing says how many of a region's children are visible at once, which lets a renderer derive a tab strip or a prev/next row itself rather than recognising a widget by name. Window and Paging carry where a reader is in a sequence.

Adaptation: Affordance says whether a hover state, a keyboard hint, a side panel, a swipe or a haptic exists at a given input class and window size class, read against makeover-geometry's Density and SizeClass. It names what appears and disappears, never how much space it takes. This was the makeover-touch crate, which is retired; take Affordance from here.

The vocabulary was read off audiofiles, the only implementation written by a consumer with no CSS, then checked against the webview apps.

What is not here, on purpose

Validation. Field describes fields, not constraints. A schema that describes fields without constraints acquires a constraint layer per app, which is the divergence this crate exists to end.

Where the description stops

The bespoke widgets: a day-plan timeline, a kanban board, a calendar. A description expressive enough to produce those is not a description any more, it is a widget library with one app on top. Generate the boring 80% so the bespoke 20% gets the attention.

Region::Handover and Region::Ceded state that limit instead of hiding it. The description names the place, the app owns the contents, and a screen with a timeline in it is still a whole screen. A handover is a place the app fills and a renderer must say so when it does not; a ceded region owes nothing. Region::described() is how a renderer tells either from the rest.

Status

On crates.io. Every public type is #[non_exhaustive] and built through constructors and setters, so adding a member is a minor release; removing or changing one is a major bump with a migration.

Design lives in the wiki note makeover-layout; the backlog is in GoingsOn under the project of the same name.

Licence

MIT.