Documentation

Composing a screen from patterns

Build a small dashboard from layout, data and feedback patterns, with tabs that switch the body.

A screen in Orb is a tree of patterns. This tutorial builds a dashboard with stat tiles, an alert and a team tab, and shows how a trait switches between bodies.

1. Layout first

stack arranges children in a row or a column; simple-grid places them in equal columns:

lolo
1{ type: simple-grid, cols: 3, gap: md, children: [ 2 { type: stat-display, label: "Open orders", value: 18 }, 3 { type: stat-display, label: "Shipped today", value: 7 }, 4 { type: stat-display, label: "Late", value: 1 } 5] }

2. Feedback

alert shows a message with a tone (info, success, warning, error). Tones come from the theme, so the same program looks right in every theme.

lolo
1 { type: alert, variant: warning, message: "One order is past its delivery date." }

3. Tabs that send events

Tabs are buttons in disguise: each item names the event it sends. Each event has a transition, and each transition renders its own body. The activeTab prop marks the current one.

lolo
1 2 3 4 ▼{ type: tabs, activeTab: "overview", items: [ { id: "overview", label: "Overview", event: SHOW_OVERVIEW }, { id: "team", label: "Team", event: SHOW_TEAM } ] }

4. The finished dashboard

State machine

Dashboard

on Board · states: 2 · transitions: 3
emitsMOVED
INIT
SHOW_TEAM
SHOW_OVERVIEW
nowoverview
team
Running live
Open orders

18

Shipped today

7

Late

1

The same trait as a state machine: each box is a state, each arrow an event that moves it, and the icons on an arrow are the effects that event runs. Hover a symbol to see what it does. How to read AVL

std-orb-docex-dashboard.lolololo
1app std-orb-docex-dashboard "1.0.0" 2"std-orb-docex-dashboard — UI patterns: a render-ui tree of layout, display and action patterns, with tabs that switch what the main slot shows." 3orbital DashboardOrbital { 4 entity Board [runtime] { 5 id : string! 6 tab : "overview" | "team" = overview 7 } 8 9 trait Dashboard -> Board [interaction, instance] { 10 initial: overview 11 12 state overview { 13 INIT -> overview 14 (render-ui main { type: stack, direction: vertical, gap: md, children: [ 15 { type: tabs, items: [{ id: "overview", label: "Overview", event: SHOW_OVERVIEW }, { id: "team", label: "Team", event: SHOW_TEAM }], activeTab: "overview" }, 16 { type: simple-grid, cols: 3, gap: md, children: [ 17 { type: stat-display, label: "Open orders", value: 18 }, 18 { type: stat-display, label: "Shipped today", value: 7 }, 19 { type: stat-display, label: "Late", value: 1 } 20 ] }, 21 { type: alert, variant: warning, message: "One order is past its delivery date." } 22 ] }) 23 SHOW_TEAM -> team 24 (emit MOVED { event: "SHOW_TEAM" }) 25 (set @entity.tab team) 26 (render-ui main { type: stack, direction: vertical, gap: md, children: [ 27 { type: tabs, items: [{ id: "overview", label: "Overview", event: SHOW_OVERVIEW }, { id: "team", label: "Team", event: SHOW_TEAM }], activeTab: "team" }, 28 { type: stack, direction: horizontal, gap: md, align: center, children: [ 29 { type: avatar, name: "Huda", size: md }, 30 { type: typography, content: "Huda · warehouse lead", variant: body } 31 ] }, 32 { type: stack, direction: horizontal, gap: md, align: center, children: [ 33 { type: avatar, name: "Luka", size: md }, 34 { type: typography, content: "Luka · dispatch", variant: body } 35 ] } 36 ] }) 37 } 38 39 state team { 40 SHOW_OVERVIEW -> overview 41 (emit MOVED { event: "SHOW_OVERVIEW" }) 42 (set @entity.tab overview) 43 (render-ui main { type: stack, direction: vertical, gap: md, children: [ 44 { type: tabs, items: [{ id: "overview", label: "Overview", event: SHOW_OVERVIEW }, { id: "team", label: "Team", event: SHOW_TEAM }], activeTab: "overview" }, 45 { type: simple-grid, cols: 3, gap: md, children: [ 46 { type: stat-display, label: "Open orders", value: 18 }, 47 { type: stat-display, label: "Shipped today", value: 7 }, 48 { type: stat-display, label: "Late", value: 1 } 49 ] }, 50 { type: alert, variant: warning, message: "One order is past its delivery date." } 51 ] }) 52 } 53 54 emits { 55 MOVED -> external { 56 event : string! 57 } 58 @description "Each move names the event it took, so the diagram beside the demo can follow it." 59 } 60 } 61 62 page "/dashboard" -> Dashboard 63}

What happens when SHOW_TEAM fires:

overviewSHOW_TEAM
→
team
Effects (2)What runs, in order, when the transition fires.
(set @entity.tab "team")
@entity.tab"team"set

Orb

The language where the rule is the program.

© 2026 Almadar. Ljubljana, Slovenia.
Not reported here