Patterns
Complete examples showing how Query, $variables, @builtins, and actions compose together.
Real dashboards combine multiple features. These patterns show complete, copy-paste-ready openui-lang snippets using the built-in openuiLibrary components (Stack, Card, Table, etc.). The openui-lang code works the same with any custom library, just swap the component names to match your own definitions.
Searchable, sortable table
A text input filters rows, a dropdown sorts them. Both are reactive.
$search = ""
$sortBy = "stars"
data = Query("get_repos", {}, {rows: []})
filtered = @Filter(data.rows, "name", "contains", $search)
sorted = @Sort(filtered, $sortBy, "desc")
searchBox = FormControl("Search", Input("search", "Filter repos...", "text", null, $search))
sortSelect = FormControl("Sort by", Select("sortBy", [SelectItem("stars", "Stars"), SelectItem("forks", "Forks"), SelectItem("updated", "Recent")], null, null, $sortBy))
controls = Stack([searchBox, sortSelect], "row", "m")
tbl = Table([Col("Name", sorted.name), Col("Stars", sorted.stars, "number"), Col("Forks", sorted.forks, "number")])
emptyState = @Count(filtered) > 0 ? tbl : TextContent("No results match your search.")
root = Stack([CardHeader("Repositories"), controls, emptyState])What's happening:
$searchbinds to the Input. User types,@Filterre-evaluates, table updates.$sortBybinds to the Select. User picks a field,@Sortre-evaluates.@Count(filtered) > 0shows an empty state when nothing matches.
CRUD with edit modal
Create tickets with a form, edit them in a modal, refresh the table after each action.
$title = ""
$priority = "medium"
$showEdit = false
$editId = ""
$editTitle = ""
$editPriority = "medium"
createResult = Mutation("create_ticket", {title: $title, priority: $priority})
updateResult = Mutation("update_ticket", {id: $editId, title: $editTitle, priority: $editPriority})
tickets = Query("list_tickets", {}, {rows: []})
createBtn = Button("Create", Action([@Run(createResult), @Run(tickets), @Reset($title, $priority)]))
createForm = Form("create", createBtn, [
FormControl("Title", Input("title", "Ticket title", "text", {required: true}, $title)),
FormControl("Priority", Select("priority", [SelectItem("low", "Low"), SelectItem("medium", "Medium"), SelectItem("high", "High")], null, null, $priority))
])
tbl = Table([
Col("Title", tickets.rows.title),
Col("Priority", @Each(tickets.rows, "t", Tag(t.priority, null, "sm", t.priority == "high" ? "danger" : "neutral"))),
Col("Edit", @Each(tickets.rows, "t", Button("Edit", Action([@Set($editId, t.id), @Set($editTitle, t.title), @Set($editPriority, t.priority), @Set($showEdit, true)]), "secondary", "normal", "small")))
])
saveBtn = Button("Save", Action([@Run(updateResult), @Run(tickets), @Set($showEdit, false)]), "primary")
cancelBtn = Button("Cancel", Action([@Set($showEdit, false)]), "secondary")
editForm = Form("edit", Buttons([saveBtn, cancelBtn]), [
FormControl("Title", Input("editTitle", "", "text", {required: true}, $editTitle)),
FormControl("Priority", Select("editPriority", [SelectItem("low", "Low"), SelectItem("medium", "Medium"), SelectItem("high", "High")], null, null, $editPriority))
])
editModal = Modal("Edit Ticket", $showEdit, [editForm])
root = Stack([CardHeader("Tickets"), createForm, tbl, editModal])What's happening:
- Create form uses
Mutation+@Run+@Resetto create and clear. - Edit button uses
@Setto populate modal fields and open it. - Save button runs the update mutation, refreshes the query, and closes the modal.
@Eachrenders per-row Tag colors and Edit buttons.
Dashboard with KPI cards
Aggregate query results into KPI cards using @Count, @Sum, and @Filter.
$days = "7"
data = Query("get_usage_metrics", {days: $days}, {totalEvents: 0, totalUsers: 0, data: []})
filter = FormControl("Date Range", Select("days", [SelectItem("7", "7 days"), SelectItem("14", "14 days"), SelectItem("30", "30 days")], null, null, $days))
kpiRow = Stack([
Card([TextContent("Events", "small"), TextContent("" + data.totalEvents, "large-heavy")]),
Card([TextContent("Users", "small"), TextContent("" + data.totalUsers, "large-heavy")]),
Card([TextContent("Avg/Day", "small"), TextContent("" + @Round(@Avg(data.data.events), 0), "large-heavy")])
], "row", "m", "stretch", "start", true)
chart = Card([CardHeader("Daily Trend"), LineChart(data.data.day, [Series("Events", data.data.events), Series("Users", data.data.users)])])
root = Stack([CardHeader("Analytics"), filter, kpiRow, chart])What's happening:
- One
$daysvariable drives the Query args. Changing the Select re-fetches everything. - KPIs use direct field access (
data.totalEvents) and computed values (@Round(@Avg(...))). - The chart uses array pluck (
data.data.day) to extract columns from the query result.
Auto-refresh monitoring
The 4th argument to Query sets a refresh interval in seconds.
health = Query("get_server_health", {}, {cpu: 0, memory: 0, latencyP95: 0, errorRate: 0, timeseries: []}, 30)
kpiRow = Stack([
Card([TextContent("CPU", "small"), TextContent("" + @Round(health.cpu, 1) + "%", "large-heavy")]),
Card([TextContent("Memory", "small"), TextContent("" + @Round(health.memory, 1) + "%", "large-heavy")]),
Card([TextContent("P95 Latency", "small"), TextContent("" + health.latencyP95 + "ms", "large-heavy")]),
Card([TextContent("Error Rate", "small"), TextContent("" + @Round(health.errorRate, 2) + "%", "large-heavy")])
], "row", "m", "stretch", "start", true)
chart = Card([CardHeader("24h Trend"), LineChart(health.timeseries.time, [Series("CPU", health.timeseries.cpu), Series("Memory", health.timeseries.memory)])])
refreshBtn = Button("Refresh Now", Action([@Run(health)]), "secondary")
root = Stack([CardHeader("Server Health"), refreshBtn, kpiRow, chart])What's happening:
Query(..., 30)re-fetches every 30 seconds automatically.@Run(health)on the button triggers an immediate manual refresh.- KPIs use
@Roundfor clean number formatting.
Shared filter across tabs
One $days variable works across all tab content because tabs share the same reactive scope.
$days = "7"
filter = FormControl("Date Range", Select("days", [SelectItem("7", "7 days"), SelectItem("14", "14 days"), SelectItem("30", "30 days")], null, null, $days))
usage = Query("get_usage_metrics", {days: $days}, {data: []})
endpoints = Query("get_top_endpoints", {days: $days}, {endpoints: []})
overviewTab = TabItem("overview", "Overview", [
LineChart(usage.data.day, [Series("Events", usage.data.events)])
])
endpointsTab = TabItem("endpoints", "Top Endpoints", [
Table([Col("Path", endpoints.endpoints.path), Col("Requests", endpoints.endpoints.requests, "number"), Col("Latency", endpoints.endpoints.avgLatency, "number")])
])
tabs = Tabs([overviewTab, endpointsTab])
root = Stack([CardHeader("Dashboard"), filter, tabs])What's happening:
- Both
usageandendpointsqueries reference$daysin their args. - Changing the filter re-fetches both queries, updating both tabs.
- Each tab renders different data but shares the same reactive variable.