Expand description
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 all of 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. A description that assumes per-side edges
is a CSS description wearing a neutral name. So this crate names the
intent — this region is a well — and each renderer chooses an expression
it can actually produce, including dropping half of one.
§Scope
Depth came first: the bevel and the surfaces it shapes. That much was
settled the hard way — the vocabulary here was read off audiofiles’
ui::theme and ui::widgets, which are the only implementation written
by a consumer with no CSS, then checked against both webview apps. All
three agreed once Balanced Breakfast’s fills were corrected.
0.2.0 adds the rest of the description, each member drawn the same way, from what the three apps already hand-write rather than from a taxonomy:
- Components.
Token(badge against chip),Notice(toast against banner),RowPart,Heading,Selector,Readiness, andTone, which is the one intent family they share. - Schemas.
Fieldfor forms andColumnfor lists and tables. - Structure.
Regionfor the parts of a screen,Arrangementfor how a screen is put together.
Validation is absent on purpose rather than pending: neither app has a shared story, and a schema describing fields but not constraints acquires a constraint layer per app, which is how the divergence this crate exists to end got started.
§Where the description stops
The bespoke widgets, a day-plan timeline and a kanban board and a calendar, are not describable here and will not become describable. A description expressive enough to produce a timeline is a widget library wearing a description’s name. Generate the boring 80% so the bespoke 20% gets the attention.
Region::Bespoke is how that limit is stated rather than hidden. The
description names the place and the app owns the contents, so a screen
containing a timeline is still a whole screen and still routable. Without
it, the four goingson screens that make the app worth using would need a
second, undescribed path beside the router, and two paths is how a
vocabulary starts drifting from its app again.
Structs§
Enums§
- Arrangement
- How a screen is laid out.
- Bevel
- Which way the light falls across a two-tone edge.
- Depth
- How a region sits relative to the surface behind it.
- Edge
- One side of a bevel, named by the intent it takes.
- Field
Kind - What kind of value a form field takes.
- Fill
- A surface intent a region is filled with.
- Heading
- How far down the heading tree a title sits.
- Notice
- Something the app is telling the user, unprompted.
- Priority
- What a column is worth when there is not room for all of them.
- Readiness
- Whether the content of a region has arrived.
- Region
- A named part of a screen.
- RowPart
- The parts of a list row.
- Selector
- A control that picks between things.
- Token
- A small labelled thing that sits inside something else.
- Tone
- What a region is saying, when it is saying something.
- Width
- How much room a column asks for.
Traits§
- Intent
- A colour intent this crate refers to but never resolves.