Your first component
This walk-through builds a toggle button: a rounded rectangle that lights up when clicked, with a hover look and a label. Each step adds one idea of the format.
1. The size and a face
Every widget has a design size. Its layers are drawn in order, back to front:
{
"spec": "0.1",
"about": "A toggle button.",
"widget": {
"size": [96, 32],
"layers": [
{ "shape": "rect", "radius": 6, "effects": [{ "type": "fill", "color": "#2a2b31" }] }
]
}
}A layer without a frame covers the whole widget. effects paint the shape, as CSS backgrounds and borders do.
2. State, and a layer that depends on it
Add an initial state and a second layer drawn only while the toggle is on:
"state": { "on": false, "label": "Loop" },
"layers": [
{ "shape": "rect", "radius": 6, "effects": [{ "type": "fill", "color": "#2a2b31" }] },
{ "shape": "rect", "radius": 6, "effects": [{ "type": "fill", "color": "#4a78c0" }], "when": "s.on" }
]when is an ECMAScript expression. s is the state as this widget sees it.
3. Hover and press
ui describes the pointer. Add a light veil while hovered and a dark one while pressed:
{ "shape": "rect", "radius": 6, "effects": [{ "type": "fill", "color": "#ffffff" }], "opacity": 0.08, "when": "ui.hover && !ui.down" },
{ "shape": "rect", "radius": 6, "effects": [{ "type": "fill", "color": "#000000" }], "opacity": 0.18, "when": "ui.down" }4. A label
A text layer’s text is an expression too, here reading the state:
{ "text": "s.label", "frame": { "l": 8, "t": 0, "r": 8, "b": 0 }, "size": 13, "color": "#ececec", "align": "center" }The frame insets the text 8 units from the left and right edges, as CSS left and right would.
5. Behaviour
Finally, a behaviour maps a click to a new state. It is a JavaScript object of handlers, each returning the state to change:
"behaviour": "({ click(s) { return { on: !s.on } } })"That is the whole component. The same file runs in every Ooidget runtime; with an accessible role it is also a proper toggle to screen readers:
"role": "switch", "label": "s.label"