# 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.
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.