Reference

The authoring surface

Lumen's markup is a fixed tag vocabulary; its CSS is a narrow subset that maps one-to-one onto the same attributes; its scripting is Rhai plus a fixed set of host builtins. These tables condense the reference — jump to tags, CSS, or Rhai.

Markup tags

Tag vocabulary

Unknown tags are a parse error. Every visible tag also accepts the shared layout and visual attributes below.

# structure & layout
TagWhat it isNotable attributes
<root>The single document root; vertical flex filling the window.skin, frameless, class
<column> / <row>Flex containers — stack children vertically / horizontally.gap, align, justify
<spacer>Empty grow box; pushes siblings apart. Defaults to grow="1".
<tile>Generic styled box leaf — a paint target for backgrounds, gradients, shadows.bg, radius, shadow
<div>Block leaf with no default decoration; a class-styled box.class
<scroll>Clipped scrolling container with layout isolation.scroll, sensitivity, inertia
<overlay>Floats out of flow; covers its positioned ancestor. Modals, dropdowns, tooltips.position, inset
<title-bar>Draggable region for frameless windows.drag
# content & controls
TagWhat it isNotable attributes
<label>Text leaf, fully shaped and BiDi-aware.text, font-size, wrap, max-lines, bind-text
<input> / <textarea>Editable text field — single-line / multiline.placeholder, bind-text, required, pattern
<button>Focusable tile with click dispatch. Inner text is the label.id, text, class
<toggle>Boolean two-state control.bind-checked, checked
<slider>Drag value across a range (default 0..1).min, max, value, bind-value
<image>Raster or SVG image; loaded once and cached.src, fit, opacity
<dropdown> + <option>Select widget: header button + options panel.bind-value, placeholder / value, label
<date-picker> / <time-picker>Validated text inputs with format hints.bind-value, placeholder
# reactivity, menus & composition
TagWhat it isNotable attributes
<for>Reactive iteration over a signal-backed array; {field} placeholders fill per item.each, key, virtualized, row-height
<if>Conditional subtree — mounts when a signal is truthy.signal, mode, eq
<dialog>Modal overlay with focus trap and Esc-to-close.open
<tabs> + <tab>Tabbed container; switching preserves each tab's descendant state.bind-value / name, label
<tooltip>Hover-delay popup wrapping exactly one child.text, delay
<menu> / <menubar> + <menuitem>Popup, context, and native OS menu bars.id / label, accel
<template> + <slot>Reusable markup body with default attributes and id namespacing.name, custom defaults
<script>Attaches Rhai — inline, or src="…rhai". Not a layout node.src
# shared attributes — work on every visible tag
FamilyAttributes
Layout boxwidth height min-* max-* aspect-ratio padding margin gap grow align justify position inset overflow
Visualsbg radius shadow opacity
Texttext text-color font-size text-align wrap max-lines
Interactionhover-bg press-bg focus-outline tab-index draggable drop
Bindingsbind-text bind-checked bind-value
Value grammar. Lengths: a bare number is pixels (24), or use 24px / 50%. Edges (padding, margin, inset) take 1, 2, or 4 numbers, CSS-shorthand style. Colors are #rrggbb or #rrggbbaa. A bg value may also be a linear-gradient, radial-gradient, or conic-gradient.
CSS subset

Style properties

Most properties share a name with their markup attribute. There is no specificity beyond source order, inline attributes always win, and a handful of properties are CSS-only.

# property surface
PropertyGroupValue
width height min/max-*LayoutLength (24, 50%).
aspect-ratioLayoutNumber (w/h ratio).
padding margin insetLayoutEdges (1, 2, or 4 numbers).
gap growLayoutNumber.
alignLayoutstart · end · center · stretch.
justifyLayoutstart · end · center · between · around · evenly.
positionLayoutrelative · absolute.
overflow overflow-x/yLayoutvisible · hidden · scroll.
bgVisualsColor or gradient.
radiusVisualsNumber (px).
text-colorVisualsColor.
opacityVisuals0..1.
shadowVisualsSingle shadow: [inset] ox oy blur #color.
box-shadowVisuals · CSS-onlyComma-separated shadow stack.
font-sizeTextNumber (px).
wrapTextnone · word · glyph.
max-linesTextInteger ≥ 0 (ellipsis truncation).
text-alignTextstart · center · end.
hover-bg press-bgInteractionColor. Same as :hover / :active { bg: … }.
focus-outlineInteraction<width-px> <#color>.
fitImagefill · cover · contain · none · scale-down.
transitionAnimation · CSS-only<property> <duration> [easing], comma-separated.
tokens.css
:root {
  --bg: #0d0d14;
  --fg: #e6e6e6;
  --accent: #7aa2f7;
}
.theme-light {
  --bg: #f6f6f9;
  --fg: #0d0d14;
}
root { bg: var(--bg); text-color: var(--fg); }
motion.css
.card {
  opacity: 0.5;
  transition: opacity 200ms ease-out;
}
.card.visible { opacity: 1.0; }

/* a class flip tweens the value */
/* over the declared duration    */
Selectors & cascade. Tag, class, and compound selectors (tile.card.primary) are supported, along with descendant and child combinators, structural pseudos, and :hover / :focus / :active. A @media (prefers-color-scheme) query switches token blocks for dark and light mode. Rules resolve by source order with later declarations winning at equal weight. Transitions currently animate opacity; other property names parse but are dropped for now.
Rhai builtins

Script functions

Scripts get Rhai's standard library plus a fixed set of host builtins — the bridge to the running app. Lifecycle callbacks are functions you write that the runtime calls by convention.

# builtins you call
FunctionGroupEffect
signal(name, default)StateHandle to a scalar signal with .get() / .set(v) / .value.
signal_array(name)StateReactive array backing <for>.set .push .len .get(i).
derive(name, deps, fn)StateComputed signal; re-runs when any dep changes.
set_text(id, text)MutateReplace an element's text content.
set_class(id, classes)MutateReplace an element's classes; re-applies CSS.
set_root_class(classes)MutateSame, targeting <root> — drives theme switches.
set_src(id, path)MutateSwap an <image>'s asset at runtime.
on(event, id, fn)RoutingPer-id handler; skips the global dispatcher for that pair.
local_id(source, suffix)RoutingSibling id within the same template instance.
set_timeout(name, ms)TimersOne-shot; fires on_timer(name).
set_interval(name, ms) · cancel_timer(name)TimersRepeating timer and its cancel.
fetch(url, tag)HTTPOff-thread GET; result lands in on_fetch(tag, body).
parse_json(body)HTTPJSON string → Rhai map / array / scalar.
pick_file(tag) · pick_files · pick_folder · save_fileDialogsNative file dialogs; results arrive via callbacks.
notify(title, body)ShellOS notification (fire-and-forget).
register_hotkey(name, accel)ShellGlobal accelerator; fires on_hotkey(name).
tray_icon(id, path, tooltip)ShellSystem tray icon (macOS / Windows).
open_menu(id) · close_menu(id)ShellFlip a <menu> popup open / closed.
print(...)DebugCaptured into the lumenc diagnostic stream.
# lifecycle callbacks the runtime calls
CallbackWhen
on_start()Once, after the layout tree spawns. Register handlers and seed signals.
on_tick(dt)Every frame; dt is seconds since the last tick.
on_click(id) · on_double_click · on_long_pressGlobal pointer dispatch (per-id on(...) handlers take priority).
on_text_input(id, text)Text committed on an input or textarea.
on_toggle(id, checked) · on_slider(id, value)Control state changes.
on_file_dropped(id, path)File dropped on a drop="true" target.
on_fetch(tag, body) · on_fetch_error(tag, msg)Result of a fetch(...) call.
on_file_picked · on_files_picked · on_folder_pickedFile-dialog results (empty path = cancelled).
on_timer(name) · on_hotkey(name) · on_menu(id) · on_tray(id)Timer, hotkey, menu, and tray events.
See it in real apps → Back to the walkthrough