The rules
Every part of kiln follows these. If something does not, it is a bug (see
Problems). The original version is at the top of kiln/kiln.odin.
1. Containers are if blocks
Section titled “1. Containers are if blocks”if kiln.card("Profil") { if kiln.row() { ... }}All containers use the same parameter names:
| name | what | type |
|---|---|---|
gap | space between children | Space |
padding | space inside the border | Space |
fill | which axes grow | Fill |
align | cross axis alignment | Align |
width | fixed width in units | f32 |
2. Widgets are controlled
Section titled “2. Widgets are controlled”A value widget takes the current value and returns (new_value, changed). The view never writes
to the model, it turns changes into messages:
if v, ok := kiln.slider(m.volume, 0, 100); ok {append(out, Set_Volume{v})}if kiln.button("Speichern") {append(out, Save{})} // actions return boolif i, ok := kiln.menu("Aktionen", ITEMS[:]); ok { ... } // menus return (index, ok)- Selections are indices with
-1for “nothing”. - Choice widgets (
tabs,segmented,nav,select,chips) also take an enum-indexed array of labels and then return the enum. - Strings returned by widgets live until the end of the frame. Clone them in
update.
3. UI state lives in kiln, app state lives in the model
Section titled “3. UI state lives in kiln, app state lives in the model”Focus, cursor, scroll offsets, open popups, hover fades, table sorting, expanded tree nodes and collapsed sections are kept by kiln. You do not store them.
Dialogs and drawers are opened by name:
if kiln.button("Löschen", .Danger) {kiln.show("confirm")}if kiln.dialog("confirm", "Wirklich löschen?") { ... kiln.hide() ... }4. Item queries refer to the widget declared just before them
Section titled “4. Item queries refer to the widget declared just before them”kiln.button("Speichern")kiln.tooltip("Strg+S")
if kiln.list_item(selected) { ... }if kiln.clicked() { ... } // clicked, hovered, submittedif i, ok := kiln.context_menu(ITEMS[:]); ok { ... }clicked, hovered, submitted, tooltip and context_menu all work like this.
5. Identity is automatic
Section titled “5. Identity is automatic”Widgets are identified by their label (or kind) and how often it occurred before in the current scope, so equal labels never clash.
When a loop draws items of a list that can change, wrap each item in a scope, so its UI state (hover, open, focus) follows the item and not the position:
for item in m.items { if kiln.scope(item.id) { ... }}6. Values come from the theme
Section titled “6. Values come from the theme”Spacing, radii, sizes, fonts and colors are named steps (.SM, .Raised, .Muted, …). The
theme decides what they are. Numbers only appear as widths in units (scaled pixels).
See Theme.
7. Layouts adapt to the screen
Section titled “7. Layouts adapt to the screen”screen() classifies the window as .Compact (phones), .Medium (tablets, narrow windows) or
.Expanded. by_screen(a, b, c) picks a value per class. Containers also adapt to the space they
actually get. See Layout.