Atoms, Molecules, and the uses System
Orb follows atomic design for behavior, not just UI. Standard behaviors are atoms — small state machines that own their topology. Your application composes them into molecules using uses imports and an override surface. The atom's states and transitions stay constant. You rebind the data, rename the events, and replace the effects.
Atoms Own Topology
A standard behavior like std-modal defines a complete state machine: closed → open → closed, with save and cancel paths. This topology is fixed. No molecule can add or remove states from it.
What molecules can override:
| Field | Effect |
|---|---|
linkedEntity | Rebinds the trait to your entity |
events | Renames events (OPEN → ADD_ITEM) |
on EVENT { ... } | Replaces the effects for each event |
emitsScope | Sets internal or external |
Composition in Practice
orbital InventoryOrbital {
uses Modal from "std/behaviors/std-modal"
uses Browse from "std/behaviors/std-browse"
entity Item [runtime] {
id : string
name : string
sku : string
}
trait ItemBrowse = Browse.traits.BrowseItemBrowse -> Item {
on INIT {
(ref Item)
(render-ui main { type: "stack", direction: "vertical", gap: "lg", children: [{ type: "typography", content: "Inventory", variant: "h2" }, { type: "divider" }, { type: "data-list", entity: "Item", fields: ["name", "sku"] }] })
}
}
trait ItemAdd = Modal.traits.ModalRecordModal -> Item {
events { OPEN: ADD_ITEM }
on ADD_ITEM {
(fetch Item)
(render-ui modal { type: "stack", direction: "vertical", gap: "md", children: [{ type: "typography", content: "New Item", variant: "h3" }, { type: "input", label: "Name" }, { type: "button", label: "Save", event: "SAVE", variant: "primary" }] })
}
on SAVE {
(render-ui modal null)
(render-ui main { type: "stack", direction: "vertical", gap: "lg", children: [{ type: "typography", content: "Inventory", variant: "h2" }, { type: "divider" }, { type: "data-list", entity: "Item", fields: ["name", "sku"] }] })
}
emitsScope internal
}
page "/inventory" -> ItemBrowse, ItemAdd
}
Modal owns the open/save/cancel state machine. ItemAdd rebinds the entity to Item, renames OPEN to ADD_ITEM, and overrides the effects for ADD_ITEM and SAVE. The modal's topology — its states and transitions — is untouched.
The Emit/Listen Contract
Cross-orbital communication uses emits and listens. A trait declares what events it emits. Another trait declares what it listens for. The compiler verifies every emitted event has at least one listener:
Error: ORB_X_ORPHAN_EMIT
Trait 'ItemAdd' emits 'ITEM_CREATED' but no trait
has a matching 'listens' declaration.
No fire-and-forget events. No messages published to a queue with no consumer. The wiring is verified at compile time.
Why Topology Stays Constant
If a molecule needs a transition the atom does not have, the atom is incomplete. Fix the atom, not the molecule. This constraint keeps composition predictable: you always know what states exist by reading the atom. The molecule only controls what happens within those states — not which states exist.
