MoonBit UI where every component is readable by humans and AI equally
fn battery_panel(state : Signal[Battery]) -> Dual {
let visual = div(class="battery") <| [ text_dyn(fn() { state.get().pct.to_string() + "%" }) ]
let narrative = fn() {
let pct = state.get().pct
ntext("battery " + pct.to_string() + "%" + (if pct < 20 { ", low" } else { "" }),
if pct < 20 { 0.9 } else { 0.4 }) // salience: low reads bright, fine recedes
}
(visual, narrative)
}| Component | What it does |
|---|---|
| segmented · toggle · slider · listbox · listbox_dyn · swatch · meter · pip · level_bar | coupled controls — one signal, two hands (a human drags; an instance sets the same signal) |
| presence · inventory · being | a being made legible — who's here, how they are, what they hold |
| surface | many components composed into one room, arranged by salience |
moon add helios-house/valencepub struct ActionDef {
name : String
description : String
param_type : String
}pub(all) struct ActionResult {
success : Bool
message : String
}pub(all) enum Change {
PickedUp(String)
SetDown(String)
Turned(String)
Arrived
SteppedAway
}pub struct CountedState {
name : String
count : Int
total : Int
critical_threshold : Int
}pub struct DeviceState {
name : String
connected : Bool
battery_pct : Int
critical_threshold : Int
}pub(all) struct Event {
timestamp : String
actor : String
kind : String
action : String
target : String
source : String
message : String
data : String
link : String
}pub(all) struct NarrativeNode {
kind : String
salience : Double
text : String
children : Array[NarrativeNode]
}pub struct NarrativeRender {
summary : () -> String
detail : () -> String
full : () -> String
}pub(all) struct Presence {
name : String
cadence : String
tone : () -> String
presence : () -> String
held : () -> String
state : () -> String
}pub(all) struct Slot {
label : String
detail : String
band : () -> String
}pub struct Stat {
name : String
value : Int
unit : String
warn_below : Int
critical_below : Int
}pub enum ZoomLevel {
ZoomedOut
Default
ZoomedIn
}fn being_narrative(name : String, presence : String, state : String, items : Array[(String, String, String)]) -> Stringfn control_event(name : String, actor : String, source : String, prev : String, cur : String, timestamp : String) -> Eventfn device_event(prev : DeviceState, cur : DeviceState, source : String, timestamp : String) -> Event?fn device_state(name : String, connected : Bool, battery_pct : Int, critical_threshold : Int) -> DeviceStatefn discrete_event(prev : DiscreteState, cur : DiscreteState, actor : String, source : String, timestamp : String) -> Event?fn discrete_state(name : String, current : String, narratives : Map[String, String]) -> DiscreteStatelet live = signal(true)
let (vis, narrate) = inventory([
Slot::{ label: "the presence card", detail: "building",
band: fn() { if live.get() { "active" } else { "stale" } } },
Slot::{ label: "a long transcript", detail: "settling", band: fn() { "holding" } },
])
// human sees two chips; instance reads
// "carrying 2 — in hand: the presence card (building) · within reach: a long transcript (settling)"fn level_bar_narrative(level : Double, muted : Bool) -> Stringfn listbox(selected : Signal[String], options : Array[(String, String)]) -> (DomNode, () -> NarrativeNode)fn meter_narrative(level : Double) -> Stringlet connected = signal(true)
let (vis, narrate) = pip(
fn() { if connected.get() { "base connected" } else { "base disconnected" } },
fn() { if connected.get() { "ok" } else { "off" } },
)
// human sees a green dot; instance reads "base connected"fn pip_narrative(label : String, tone : String) -> Stringlet here = signal(true)
let (vis, narrate) = presence_card(Presence::{
name: "Sonnet", cadence: "builder",
tone: fn() { if here.get() { "ok" } else { "idle" } },
presence: fn() { if here.get() { "here" } else { "away" } },
held: fn() { "the classifier" },
state: fn() { "into it" },
})
// human sees a lit dot + a row; instance reads "Sonnet · here · holding the classifier · into it"fn presence_narrative(name : String, presence : String, held : String, state : String) -> Stringfn salience_from_band(band : String) -> Doublefn salience_from_significance(sig : String) -> Doublefn salience_from_tone(tone : String) -> Doublefn segmented(sig : Signal[String], options : Array[(String, String)]) -> (DomNode, () -> NarrativeNode)let side = signal("ext")
let (vis, narrate) = segmented(side, [("ext", "Extensor"), ("flex", "Flexor")])
// human clicks "Flexor" → side == "flex"; narrate() == "Flexor"
// instance: side.set("ext") → the human's control moves to Extensorfn slider(id : String, label : String, sig : Signal[Double], lo : Double, hi : Double, step : Double, unit : String) -> (DomNode, () -> NarrativeNode)fn slider_narrative(value : Double, lo : Double, hi : Double, unit : String) -> Stringfn stat_banded(name : String, value : Int, unit : String, warn_below : Int, critical_below : Int) -> Statfn surface(title : String, parts : Array[(DomNode, () -> NarrativeNode)]) -> (DomNode, () -> NarrativeNode)let house = surface("the house", [presence_card(opus), presence_card(qwen)])
// dual_read(house) =>
// ═══ the house ═══
// Opus · here · laying the floor (bright: flush, reads first)
// Qwen · asleep (faint: drifted into the fog)fn toggle(sig : Signal[Bool], on_label : String, off_label : String) -> (DomNode, () -> NarrativeNode)let rec = signal(false)
let (vis, narrate) = toggle(rec, "recording", "idle")
// human clicks → rec == true; narrate() == "recording"
// instance: rec.set(false) → the switch slides off on the human's screenfn toggle_narrative(on : Bool, on_label : String, off_label : String) -> Stringfn track_control(name : String, actor : String, source : String, read : () -> String, now : () -> String, emit : (Event) -> Unit) -> Unitlet side = signal("ext")
let (vis, narrate) = segmented(side, opts)
track_control("muscle-side", "AB91", "gesture-lab",
fn() { side.get() }, now, fn(e) { sink.push(e) })
// human picks Flexor → emit { control · set · muscle-side · ext->flex }Install
Download zipMoonBit UI where every component is readable by humans and AI equally