Summary#
A control is mounted into an element the platform creates. What size that element is used to be nobody's job: it was a plain block that grew with its content — right for a control that draws text, and wrong for one whose content is all positioned (a canvas, a map, a camera viewfinder), which has no height of its own to grow to. Such a control collapsed inside the app's box, and the only fix was for the control to reach out and style an element it does not own.
sizing says it once, in the declaration, and the platform does the rest:
control Map {
contractVersion "1.1"
participation headless
sizing fill
props { double lat; double lng; }
}The app then decides how big the map is by sizing the box around it — never the control.
Signature#
control <Name> {
sizing content // the default — the box grows with what the control draws
sizing fill // the box fills the space the app gave it
sizing aspect <W> / <H> // full width, height from the ratio — e.g. sizing aspect 16 / 9
}Description#
The three rules#
sizing | the control's box is… | for |
|---|---|---|
content (default) | a block that grows with what the control draws | a chart legend, a rich-text editor, a data grid |
fill | 100% of a sized parent; in a stack, it grows into the space left | a canvas, a map, a viewfinder, a diagram |
aspect W / H | the full width, with its height set by the ratio | a video frame, a chart that must keep its proportions |
fill also lets the box shrink inside a stack or grid track rather than forcing the track open, and in a stack
with no height of its own it keeps its content's height rather than collapsing to nothing.
A control that fills the box you give it#
control Diagram {
contractVersion "1.1"
participation headless
sizing fill
props { string title; }
}
[Route("/diagram")] [AllowAnonymous]
component DiagramPage() {
render {
// The PAGE decides how big the diagram is — the control fills whatever this box is.
Box(h: "480px", borderW: 1, rounded: "12px") {
Diagram(title: "Order flow");
}
}
}Why the control may not size itself#
The element a control is mounted into sits in the app's layout — its parent is the app's Box or Stack, and its
size is a layout decision. A control that sets that element's height is making a layout decision about a page it has
never seen, and the two can silently disagree: measured on the flow canvas, a control that forgot to fill its host was
360px tall inside a 520px box, and a gesture that pans near the pane's edge panned the whole graph away because the
pane "ended" 160px early.
So the rule is structural rather than a convention: the platform styles the host from the declaration before the control's code runs, and a control draws inside it. A control that needs a frame, a border or a background draws them on an element of its own that fills the host.
Diagnostics#
An unknown rule is refused with every legal form in the message:
control 'Map': unknown sizing 'stretch'. A control's host is sized by one of `sizing content` (the default — the host
sizes to what the control draws), `sizing fill` (it fills the box the app put it in: a canvas, a map, a viewfinder) or
`sizing aspect W / H` (full width at a fixed ratio, e.g. `sizing aspect 16 / 9`).Declaring sizing twice, or an aspect part that is not a positive number, is refused the same way.
See also#
- control — foreign UI controls (charts, grids, maps) — the
controlblock and everything else it declares - The flow kit — a node-and-edge canvas whose nodes are your own Osy# — a canvas that declares
sizing fill - The barcode kit — a QR and barcode scanner you opt into — a viewfinder that declares
sizing fill - layout primitives — how the app sizes the box around a control