| Card |
Use a cardWidget to present one important update as a clean,
scannable card. Include a short subject, an optional subtitle for
context, a brief summary, and if helpful a status line or time
stamp, so the update feels informative without being
crowded. |
- Use it for: a single alert, update, or status
card
- Required:
subject
- Common fields:
summary, timestamp,
badgeText,
variant
- Actions:
link and optional
additionalLink, each with
text and action
- Variant values:
error, warning,
info, or omitted for neutral
Use commands such as ora.Invoke(...).
|
<oraInfoDisplay key="maintenance-card">
{
"patternId": "cardWidget",
"config": {
"subject": "Maintenance Complete",
"summary": "Scheduled database maintenance finished successfully.",
"timestamp": "1 hour ago",
"badgeText": "Info",
"variant": "info",
"link": {
"text": "View Details",
"action": "ora.Invoke(\"viewMaintenanceSummary\")"
}
}
}
</oraInfoDisplay>
|
| Multi Card |
Use a multiCardWidget to display multiple cards
in one widget. For example, for generic alerts or status
summaries. |
- Use it for: multiple peer cards in one widget when a
table or message list would be the wrong shape
- Required:
cards[]
- Optional top-level fields:
layoutMode
- layoutMode values:
default, collapsed,
single-col
- cards[] entries: each card uses the same fields as
cardWidget including
subject, summary,
optional subtitle, status,
statusPriority,
timestamp, badgeText,
link, additionalLink,
and variant
- Card color values: use the same
variant and
statusPriority values as
cardWidget, including
success and
neutral
Use layoutMode only if you need a compact
two-column layout (collapsed) or a
one-card-per-row layout (single-col). Use the
top-level widget title and text for shared context, and keep
card-specific details inside each cards[]
entry.
|
<oraInfoDisplay key="ops-status-cards">
{
"patternId": "multiCardWidget",
"config": {
"cards": [
{
"subject": "Database Cluster",
"subtitle": "Primary region",
"summary": "Replication lag returned to normal after failover testing.",
"status": "Healthy",
"statusPriority": "success",
"timestamp": "8 min ago",
"badgeText": "Info",
"link": {
"text": "View Details",
"action": "ora.Invoke(\"openDatabaseStatus\")"
}
},
{
"subject": "API Capacity",
"subtitle": "Public gateway",
"summary": "Traffic remains elevated and is close to the scaling threshold.",
"status": "Watching autoscale behavior",
"statusPriority": "warning",
"timestamp": "12 min ago",
"badgeText": "Warning",
"variant": "warning"
}
]
}
}
</oraInfoDisplay>
|
| Artifact Preview |
Use a artifactPreviewWidget when the artifact
content itself should be previewed inline and opened in the artifact
viewer. For generic alerts or status summaries, use
cardWidget or
multiCardWidget. |
- Use it for: reviewable text, rich text, structured
rich text, PDF, or URL artifacts that should open directly
in the artifact viewer
- Required:
items[]
- Each item requires:
artifactId, title,
mode, and content
- mode values:
preview, edit,
custom
- Optional item fields:
subtitle, actionText
- action: only for
custom items
- content shape: mirrors the artifact viewer /
editArtifact payload with
id, type, optional
title, value, optional
sections, url,
mediaType,
highlightText,
commitText, and optional
metadata
For preview and edit, don't use
an action property. The runtime opens the
artifact viewer directly from the item's
content payload. Only
custom items run an explicit command.
preview opens the viewer in read-only mode, and
edit opens the viewer in editable mode. On
save, the runtime returns the edited value using the normal
oraFormSubmit format and adds the item's
artifactId under
metadata.artifactId.
Some artifact types are not writable. For example, PDFs and URLs
are always treated as read-only, so mode:
"edit" behaves the same as mode:
"preview" for PDF and URL content.
For type: "url", provide url.
The preview card and artifact viewer show the URL in an iframe,
and no edited value is submitted back to the workflow.
For type: "structuredRichText", provide
sections instead of value.
Each section should include name,
locked, and text. Locked
sections remain visible in the editor but cannot be modified.
The runtime renders the sections into the rich text editor using
those locked boundaries.
|
<oraInfoDisplay key="artifact-previews">
{
"patternId": "artifactPreviewWidget",
"properties": {
"items": [
{
"artifactId": "customer-note-rich-text",
"title": "Customer Note",
"subtitle": "Standard rich text draft",
"mode": "edit",
"content": {
"id": "customer-note-1",
"type": "richText",
"title": "Customer Note",
"value": "<p><strong>Team,</strong></p><p>Please review the latest customer note before the renewal call.</p><ul><li>Pricing review is still open</li><li>Legal requested one contract edit</li><li>Customer wants final confirmation by Friday</li></ul>",
"commitText": "Save",
"metadata": {
"source": "customer-note"
}
}
},
{
"artifactId": "qbr-email-preview",
"title": "QBR Customer Email",
"subtitle": "Structured rich text draft",
"mode": "edit",
"content": {
"id": "qbr-follow-up",
"type": "structuredRichText",
"title": "QBR Follow-Up Email",
"sections": [
{
"name": "Greeting",
"locked": false,
"text": "<p><strong>Hi Jordan,</strong></p>"
},
{
"name": "Summary",
"locked": false,
"text": "<p>Thanks again for the time today...</p>"
},
{
"name": "Closing",
"locked": true,
"text": "<p>Best,<br/>Account Team</p>"
}
],
"commitText": "Save",
"metadata": {
"source": "qbr"
}
}
},
{
"artifactId": "renewal-brief-pdf",
"title": "Renewal Brief",
"subtitle": "Executive package",
"mode": "preview",
"content": {
"id": "renewal-brief",
"type": "pdf",
"title": "Renewal Brief",
"url": "/artifacts/renewal-brief.pdf",
"mediaType": "binary"
}
},
{
"artifactId": "order-dashboard-url",
"title": "Order Dashboard",
"subtitle": "Live dashboard",
"mode": "preview",
"content": {
"id": "order-dashboard",
"type": "url",
"title": "Order Dashboard",
"url": "https://example.com/orders/dashboard"
}
}
]
}
}
</oraInfoDisplay>
When a writable artifact is saved, the app sends the edited
result back to the workflow as an oraFormSubmit
block. The example below shows the exact payload shape the
workflow receives, including the edited value and the widget's
metadata.artifactId.
<oraFormSubmit id="qbr-follow-up">
{"newValue":"Updated text from the editor","metadata":{"source":"qbr","artifactId":"qbr-email-preview"}}
</oraFormSubmit>
For structuredRichText, the same submit envelope
is used, but newValue contains the updated
sections[] array instead of a string.
<oraFormSubmit id="qbr-follow-up">
{"newValue":[{"name":"Greeting","locked":false,"text":"<p><strong>Hi Jordan,</strong></p>"},{"name":"Summary","locked":false,"text":"<p>Updated summary from the editor.</p>"},{"name":"Closing","locked":true,"text":"<p>Best,<br/>Account Team</p>"}],"metadata":{"source":"qbr","artifactId":"qbr-email-preview"}}
</oraFormSubmit>
submitId: the artifact payload
content.id when present; otherwise
artifact
newValue: for
text and richText,
this is a string; for
structuredRichText, this is the
updated sections[] array with the
latest text for each section
metadata: the original metadata
payload, passed back unchanged except that the widget
adds artifactId under
metadata.artifactId
|
| Messages List |
Use a messageListWidget to show a short list of recent messages,
alerts, or notable events. Each item should have a clear title,
optional supporting context like a subtitle or summary, and a
time stamp when useful, so the list feels friendly, current, and
easy to scan.
|
- Use it for: alerts, activity feeds, and small
collections of highlight items
- Required:
items[] with at least
title per item
- Item fields:
subtitle, summary,
status, badgeText,
priority, timestamp,
image
- Interactivity: item
action and item
additionalAction with
text + command
Runtime behavior is considered. additionalAction
is only shown when the widget is in a focused panel. Also, the
runtime supports success as a priority in addition to alert,
warning, and medium.
|
<oraInfoDisplay key="system-alerts">
{
"patternId": "messageListWidget",
"config": {
"subtitle": "Real-time metrics",
"items": [
{
"title": "Memory Usage Spike Detected",
"subtitle": "82% confidence",
"summary": "Memory consumption increased by 40% in the last 5 minutes",
"status": "Investigating root cause",
"badgeText": "Medium",
"priority": "medium",
"timestamp": "3 min ago",
"action": "ora.Invoke(\"openMemoryIncident\", { \"metric\": \"memory\" })",
"additionalAction": {
"text": "View Metrics",
"command": "ora.Invoke(\"viewMetrics\", { \"metric\": \"memory\" })"
}
},
{
"title": "Network Latency Increase",
"summary": "Average response time increased from 120ms to 180ms.",
"status": "Under investigation",
"badgeText": "Warning",
"priority": "warning",
"timestamp": "16 min ago"
}
]
}
}
</oraInfoDisplay>
|
| Change List |
Use a changeListWidget to compare a few key metrics between a
previous value and a current value. Add a short subtitle to explain
what’s being measured, keep the rows easy to read, and only include
a message if there’s a meaningful insight or anomaly worth calling
out. |
- Use it for: current-versus-previous metric
comparisons
- Required:
displayType, items
- displayType:
percentage, raw, or
currency
- items[]:
title, currentValue,
previousValue
- Optional:
subtitle, messages
Values should stay numeric. Formatting comes from displayType,
not from embedding percent signs or currency symbols inside the
numbers.
|
<oraInfoDisplay key="campaign-change-list">
{
"patternId": "changeListWidget",
"config": {
"subtitle": "Campaign performance comparison",
"displayType": "percentage",
"items": [
{ "title": "Email Open Rate", "currentValue": 28.2, "previousValue": 24.5 },
{ "title": "Click-through Rate", "currentValue": 4.6, "previousValue": 3.8 },
{ "title": "Conversion Rate", "currentValue": 1.9, "previousValue": 2.1 }
],
"messages": [
"Conversion rate drop may indicate landing page issues"
]
}
}
</oraInfoDisplay>
|
| Chart |
Use a chartWidget to visualize a simple trend, comparison, or
proportion in a way that's easy to understand at a glance. Choose
the chart type that fits the story, use clear labels, and include
one or two short insights underneath to help explain what the chart
is showing. |
- Use it for: trends, comparisons, or proportions
- Required:
type, data
- type:
line, bar, or
pie
- data.labels[]: x-axis labels or categories
- data.datasets[]: each dataset needs
label and numeric
data[]
- Optional:
insights[]
|
<oraInfoDisplay key="sales-trend-chart">
{
"patternId": "chartWidget",
"config": {
"type": "line",
"data": {
"labels": ["January", "February", "March", "April", "May"],
"datasets": [
{
"label": "Sales Revenue",
"data": [10000, 25000, 15000, 40000, 30000]
}
]
},
"insights": [
"Revenue peaked in April",
"Steady growth trend overall"
]
}
}
</oraInfoDisplay>
|
| Record |
Use a recordWidget to show a structured record as a simple form
that can either be reviewed or edited. Include clearly labeled
fields, choose field types that match the data, and keep the layout
straightforward so it feels comfortable for someone filling in or
checking details. |
- Use it for: forms and read-only detail views
- Required:
id, fields[]
- Optional:
readOnly
- Field types:
text, textarea,
number, date,
select, system
- Field fields:
id, type,
value, plus label and
options when applicable
In editable mode, the runtime automatically submits the form
through an ora.Agent(<oraFormSubmit ...>)
command. You don't configure a separate submit command in the
widget itself.
|
<oraInfoDisplay key="employee-form">
{
"patternId": "recordWidget",
"config": {
"id": "employee_form",
"readOnly": false,
"fields": [
{
"id": "full_name",
"type": "text",
"label": "Full Name",
"value": "John Doe"
},
{
"id": "employee_id",
"type": "number",
"label": "Employee ID",
"value": 12345
},
{
"id": "department",
"type": "select",
"label": "Department",
"value": "engineering",
"options": [
{ "value": "engineering", "label": "Engineering" },
{ "value": "sales", "label": "Sales" }
]
},
{
"id": "session_context",
"type": "system",
"value": { "conversation_id": "abc123" }
}
]
}
}
</oraInfoDisplay>
|
| Multi Record |
Use a multiRecordWidget to present structured information in a
compact table with clear columns and rows. Keep the values short and
scannable, use badge-style cells for statuses when helpful, and only
add row actions if the experience should explicitly support taking
action from the table. |
- Use it for: tabular record lists
- Required:
cols[] and rows[]
- Column forms: plain string, or object with
label and optional
showOnExpand
- Row cells: plain string, or badge object with
type, text, and
priority
- Badge priority values:
alert, warning,
medium, success,
neutral
- Optional row actions:
action button and
drillDownAction on the first
column
- Optional:
subtitle for table context and
accessibility
- Optional multiselect fields:
id, selectMode,
multiSelectActionText,
multiSelectMetadata
The showOnExpand columns only appear when the
widget is focused. This is useful for secondary columns that
should stay hidden in compact mode.
Badge priorities follow the same meaning as message list
priorities: alert is red,
warning is orange, medium
is informational blue, success is green, and
neutral is gray.
To enable checkbox selection, set selectMode to
multiSelect. This renders a checkbox for
each row and a submit button below the table. The button label
defaults to Submit unless you provide
multiSelectActionText.
multiSelectMetadata is an optional JSON object
or value that's copied through unchanged into the submitted
oraFormSubmit payload under the top-level
metadata property. Use it to tell the
receiving workflow what the selection is for, such as an action
name, source context, routing hint, or any other extra data the
workflow needs when processing the selected rows.
|
<oraInfoDisplay key="pending-approvals-table">
{
"patternId": "multiRecordWidget",
"config": {
"subtitle": "Pending approvals",
"cols": ["Request ID", "Type", "Status"],
"rows": [
{
"cells": [
"REQ-101",
"Budget",
{ "type": "badge", "text": "PENDING", "priority": "warning" }
],
"action": {
"text": "Review",
"command": "ora.Invoke(\"reviewRequest\", { \"id\": \"REQ-101\" })"
},
"drillDownAction": "ora.Invoke(\"openRequest\", { \"id\": \"REQ-101\" })"
},
{
"cells": [
"REQ-102",
"Travel",
{ "type": "badge", "text": "PENDING", "priority": "warning" }
],
"action": {
"text": "Review",
"command": "ora.Invoke(\"reviewRequest\", { \"id\": \"REQ-102\" })"
}
}
]
}
}
</oraInfoDisplay>
Example for multiselect table with checkbox submit.
<oraInfoDisplay key="selected-orders">
{
"patternId": "multiRecordWidget",
"config": {
"id": "selected_orders",
"subtitle": "Orders awaiting batch approval",
"selectMode": "multiSelect",
"multiSelectActionText": "Approve Selected",
"multiSelectMetadata": {
"action": "approve_orders",
"source": "batch_review_queue",
"approvalLevel": "manager"
},
"cols": ["Order ID", "Customer", "Amount", "Status"],
"rows": [
{
"cells": [
"ORD-5001",
"Acme Corp",
"$12,500",
{ "type": "badge", "text": "PENDING", "priority": "warning" }
]
},
{
"cells": [
"ORD-5002",
"Global Inc",
"$8,750",
{ "type": "badge", "text": "PENDING", "priority": "warning" }
]
}
]
}
}
</oraInfoDisplay>
When the user submits selected rows in multiselect mode, the app
sends an oraFormSubmit block back to the
workflow using the widget's id.
In the example below, multiSelectMetadata is
copied directly into metadata, while the
checked table rows are returned under
value[0].value.
<oraFormSubmit id="selected_orders">
{ "value":[{"id":"selectedRows","value":
[
{"cells":["ORD-5001","Acme Corp","$12,500",
{"type":"badge","text":"PENDING","priority":"warning"}
]
},
{"cells":["ORD-5002","Global Inc","$8,750",
{"type":"badge","text":"PENDING","priority":"warning"
}]}]}],
"metadata":{"action":"approve_orders","source":"batch_review_queue","approvalLevel":"manager"}}
</oraFormSubmit>
|
| Sankey |
Use a sankeyWidget to show how volume or activity flows from one
stage to another across a process. Define clear node names, keep the
flow easy to follow from left to right, and use realistic values so
the visualization tells a simple story about where things are
going. |
- Use it for: flows between stages or states
- Required:
nodes[], edges[]
- nodes[]:
id, name
- edges[]:
source, target,
value
Node IDs are numeric and edges point to those IDs. Keep values
positive and keep the flow easy to follow.
|
<oraInfoDisplay key="support-flow-sankey">
{
"patternId": "sankeyWidget",
"config": {
"nodes": [
{ "id": 0, "name": "Web Visitor" },
{ "id": 1, "name": "Web Chat" },
{ "id": 2, "name": "AI Chat Bot" },
{ "id": 3, "name": "Resolved by Bot" },
{ "id": 4, "name": "Transfer to Human" },
{ "id": 5, "name": "Resolved by Human" }
],
"edges": [
{ "source": 0, "target": 1, "value": 1000 },
{ "source": 1, "target": 2, "value": 1000 },
{ "source": 2, "target": 3, "value": 700 },
{ "source": 2, "target": 4, "value": 300 },
{ "source": 4, "target": 5, "value": 300 }
]
}
}
</oraInfoDisplay>
|