Advanced Components
Conditional, Loop, Accordion, Section, Icon, Fragment, Slot, Custom
Advanced Components
Components for dynamic rendering and specialized use cases.
Conditional
Conditional rendering based on expressions.
{
"type": "Conditional",
"condition": "{{state.isLoggedIn}}",
"then": { "type": "Text", "content": "Welcome back!" },
"else": { "type": "Button", "label": "Sign In" }
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
condition | string | - | Expression to evaluate (required) |
then | object | - | Component when true (required) |
else | object | - | Component when false (optional) |
Condition Syntax
// Boolean state
"condition": "{{state.isActive}}"
// Comparison
"condition": "{{state.count}} > 0"
"condition": "{{state.status}} === 'completed'"
// Logical operators
"condition": "{{state.isAdmin}} && {{state.hasPermission}}"
"condition": "{{state.isEmpty}} || {{state.isLoading}}"
// Negation
"condition": "!{{state.hasError}}"
// Complex
"condition": "({{state.role}} === 'admin' || {{state.role}} === 'manager') && {{state.isVerified}}" Examples
Loading state:
{
"type": "Conditional",
"condition": "{{state.isLoading}}",
"then": { "type": "Skeleton", "variant": "rectangular", "height": "200px" },
"else": { "type": "Table", "dataSource": "state:items" }
} Empty state:
{
"type": "Conditional",
"condition": "{{state.items.length}} === 0",
"then": {
"type": "EmptyState",
"title": "No Items",
"description": "Create your first item",
"icon": "Inbox"
},
"else": { "type": "List", "dataSource": "state:items" }
} Role-based access:
{
"type": "Conditional",
"condition": "{{state.user.role}} === 'admin'",
"then": {
"type": "Button",
"label": "Admin Settings",
"events": {
"on_click": [{ "type": "navigate", "to": "/admin" }]
}
}
} Nested conditions:
{
"type": "Conditional",
"condition": "{{state.status}} === 'loading'",
"then": { "type": "Skeleton", "variant": "text" },
"else": {
"type": "Conditional",
"condition": "{{state.status}} === 'error'",
"then": {
"type": "Alert",
"variant": "destructive",
"message": "{{state.error}}"
},
"else": { "type": "Text", "content": "{{state.data}}" }
}
} Loop
Iterate over arrays to render repeated content.
{
"type": "Loop",
"dataSource": "state:items",
"template": {
"type": "Card",
"title": "{{$item.name}}",
"content": { "type": "Text", "content": "{{$item.description}}" }
}
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
dataSource | string | - | Data source path (required) |
template | object | - | Component template for each item (required) |
emptyTemplate | object | - | Component when data is empty |
Loop Variables
Inside template, you have access to:
| Variable | Description |
|---|---|
$item | Current item |
$index | Zero-based index |
$row | Alias for $item (table context) |
Examples
Basic list:
{
"type": "Loop",
"dataSource": "state:users",
"template": {
"type": "Flex",
"align": "center",
"gap": "1rem",
"className": "p-4 border-b",
"children": [
{
"type": "Avatar",
"src": "{{$item.avatar}}",
"fallback": "{{$item.initials}}"
},
{
"type": "Flex",
"direction": "column",
"children": [
{
"type": "Text",
"content": "{{$item.name}}",
"className": "font-medium"
},
{
"type": "Text",
"variant": "muted",
"content": "{{$item.email}}"
}
]
}
]
}
} Grid of cards:
{
"type": "Grid",
"columns": { "sm": 1, "md": 2, "lg": 3 },
"gap": "1rem",
"children": [
{
"type": "Loop",
"dataSource": "state:products",
"template": {
"type": "Card",
"className": "overflow-hidden",
"content": {
"type": "Container",
"children": [
{
"type": "Image",
"src": "{{$item.image}}",
"className": "w-full h-48 object-cover"
},
{
"type": "Container",
"className": "p-4",
"children": [
{ "type": "Heading", "level": 3, "text": "{{$item.name}}" },
{ "type": "Text", "content": "${{$item.price}}" }
]
}
]
}
}
}
]
} With index:
{
"type": "Loop",
"dataSource": "state:items",
"template": {
"type": "Flex",
"className": "p-4",
"children": [
{ "type": "Text", "content": "{{$index + 1}}. {{$item.name}}" }
]
}
} With empty state:
{
"type": "Loop",
"dataSource": "state:items",
"template": {
"type": "Card",
"title": "{{$item.name}}"
},
"emptyTemplate": {
"type": "EmptyState",
"title": "No items found",
"icon": "Inbox"
}
} Accordion
Collapsible content sections.
{
"type": "Accordion",
"items": [
{
"key": "section-1",
"title": "Section 1",
"content": { "type": "Text", "content": "Content for section 1" }
},
{
"key": "section-2",
"title": "Section 2",
"content": { "type": "Text", "content": "Content for section 2" }
}
]
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
items | array | [] | Accordion items (required) |
type_ | single | multiple | single | Selection mode |
defaultOpen | array | [] | Initially expanded keys |
collapsible | boolean | true | Allow collapse all |
className | string | - | CSS classes |
Item Definition
| Property | Type | Description |
|---|---|---|
key | string | Unique item identifier |
title | string | Item header text |
content | object | Item body component |
disabled | boolean | string | Disabled state |
Examples
FAQ section:
{
"type": "Accordion",
"type_": "single",
"collapsible": true,
"items": [
{
"key": "faq-1",
"title": "What is Orbis?",
"content": {
"type": "Text",
"content": "Orbis is a desktop application platform with plugin support."
}
},
{
"key": "faq-2",
"title": "How do I install plugins?",
"content": {
"type": "Text",
"content": "Copy WASM plugin files to the plugins directory."
}
},
{
"key": "faq-3",
"title": "Is Orbis open source?",
"content": {
"type": "Text",
"content": "Yes, Orbis is open source under the MIT license."
}
}
]
} Multiple open:
{
"type": "Accordion",
"type_": "multiple",
"defaultOpen": ["section-1"],
"items": [
{
"key": "section-1",
"title": "General Settings",
"content": {
"type": "Form",
"id": "general",
"fields": [
{ "name": "name", "fieldType": "text", "label": "Name" }
]
}
},
{
"key": "section-2",
"title": "Advanced Settings",
"content": {
"type": "Form",
"id": "advanced",
"fields": [
{ "name": "apiKey", "fieldType": "text", "label": "API Key" }
]
}
}
]
} Section
Semantic grouping with optional collapsible header.
{
"type": "Section",
"title": "User Details",
"description": "Personal information",
"children": [
{ "type": "DataDisplay", "label": "Name", "value": "{{user.name}}" },
{ "type": "DataDisplay", "label": "Email", "value": "{{user.email}}" }
]
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
title | string | - | Section title |
description | string | - | Section description |
children | array | [] | Child components (required) |
collapsible | boolean | false | Make section collapsible |
defaultCollapsed | boolean | false | Initially collapsed |
className | string | - | CSS classes |
Examples
Basic section:
{
"type": "Section",
"title": "Account Settings",
"description": "Manage your account preferences",
"children": [
{
"type": "Form",
"id": "account",
"fields": [
{ "name": "email", "fieldType": "email", "label": "Email" },
{ "name": "password", "fieldType": "password", "label": "Password" }
]
}
]
} Collapsible section:
{
"type": "Section",
"title": "Advanced Options",
"collapsible": true,
"defaultCollapsed": true,
"children": [
{ "type": "Text", "content": "Advanced configuration options..." }
]
} Icon
Display icons from lucide-react.
{
"type": "Icon",
"name": "Settings",
"size": "md"
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
name | string | - | Icon name (required) |
size | xs | sm | md | lg | xl | md | Icon size |
color | string | - | Icon color (CSS color) |
className | string | - | CSS classes |
events | object | - | Event handlers |
Sizes
| Size | Dimension |
|---|---|
xs | 12px |
sm | 16px |
md | 20px |
lg | 24px |
xl | 32px |
Events
| Event | Trigger |
|---|---|
onClick | Icon clicked |
Examples
Different sizes:
{
"type": "Flex",
"gap": "1rem",
"align": "center",
"children": [
{ "type": "Icon", "name": "Star", "size": "xs" },
{ "type": "Icon", "name": "Star", "size": "sm" },
{ "type": "Icon", "name": "Star", "size": "md" },
{ "type": "Icon", "name": "Star", "size": "lg" },
{ "type": "Icon", "name": "Star", "size": "xl" }
]
} With color:
{
"type": "Icon",
"name": "CheckCircle",
"size": "lg",
"color": "#22c55e"
} Clickable icon:
{
"type": "Icon",
"name": "Settings",
"size": "md",
"className": "cursor-pointer",
"events": {
"on_click": [{ "type": "navigate", "to": "/settings" }]
}
} Dynamic icon:
{
"type": "Icon",
"name": "{{state.status === 'success' ? 'CheckCircle' : 'AlertCircle'}}",
"color": "{{state.status === 'success' ? '#22c55e' : '#ef4444'}}"
} Common Icons
| Category | Icons |
|---|---|
| Navigation | Home, ArrowLeft, ArrowRight, ChevronDown, Menu |
| Actions | Plus, Edit, Trash, Download, Upload, Copy |
| Status | Check, X, AlertTriangle, Info, HelpCircle |
| User | User, Users, Settings, LogOut, Bell |
| Files | File, FileText, Folder, FolderOpen, Image |
| Data | Database, Table, BarChart, LineChart, PieChart |
Browse all icons at lucide.dev.
Fragment
Invisible wrapper for grouping components without extra DOM nodes.
{
"type": "Fragment",
"children": [
{ "type": "Text", "content": "First" },
{ "type": "Text", "content": "Second" }
]
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
children | array | [] | Child components (required) |
Use Cases
Return multiple elements:
{
"type": "Conditional",
"condition": "{{state.showDetails}}",
"then": {
"type": "Fragment",
"children": [
{ "type": "Divider" },
{ "type": "Text", "content": "Additional details..." },
{ "type": "Button", "label": "Learn More" }
]
}
} In loop:
{
"type": "Loop",
"dataSource": "state:items",
"template": {
"type": "Fragment",
"children": [
{ "type": "Heading", "level": 3, "text": "{{$item.title}}" },
{ "type": "Text", "content": "{{$item.description}}" },
{ "type": "Divider" }
]
}
} Slot
Placeholder for plugin-defined content.
{
"type": "Slot",
"name": "sidebar-widgets",
"fallback": { "type": "Text", "content": "No widgets available" }
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
name | string | - | Slot identifier (required) |
fallback | object | - | Fallback content when slot empty |
Use Cases
Slots allow plugins to inject content into predefined areas:
{
"type": "Container",
"children": [
{ "type": "PageHeader", "title": "Dashboard" },
{
"type": "Grid",
"columns": { "lg": 3 },
"gap": "1rem",
"children": [
{
"type": "Slot",
"name": "dashboard-widget-1",
"fallback": { "type": "Card", "title": "Widget 1" }
},
{
"type": "Slot",
"name": "dashboard-widget-2",
"fallback": { "type": "Card", "title": "Widget 2" }
},
{
"type": "Slot",
"name": "dashboard-widget-3",
"fallback": { "type": "Card", "title": "Widget 3" }
}
]
}
]
} Custom
Render a custom component registered by the host application.
{
"type": "Custom",
"component": "MySpecialChart",
"props": {
"data": "{{state.chartData}}",
"options": {
"showLegend": true
}
}
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
component | string | - | Registered component name (required) |
props | object | {} | Props to pass to component |
className | string | - | CSS classes |
Example
If the host app registers a MapView component:
{
"type": "Custom",
"component": "MapView",
"props": {
"center": "{{state.location}}",
"zoom": 14,
"markers": "{{state.markers}}"
}
} Advanced Patterns
State Machine Pattern
{
"type": "Container",
"children": [
{
"type": "Conditional",
"condition": "{{state.status}} === 'idle'",
"then": {
"type": "Button",
"label": "Start",
"events": {
"on_click": [
{ "type": "update_state", "path": "status", "value": "loading" },
{ "type": "call_api", "api": "process" }
]
}
}
},
{
"type": "Conditional",
"condition": "{{state.status}} === 'loading'",
"then": {
"type": "LoadingOverlay",
"loading": true,
"text": "Processing...",
"children": { "type": "Container" }
}
},
{
"type": "Conditional",
"condition": "{{state.status}} === 'success'",
"then": {
"type": "Alert",
"variant": "default",
"title": "Success",
"message": "Operation completed!"
}
},
{
"type": "Conditional",
"condition": "{{state.status}} === 'error'",
"then": {
"type": "Alert",
"variant": "destructive",
"title": "Error",
"message": "{{state.error}}"
}
}
]
} Dynamic Form Fields
{
"type": "Form",
"id": "dynamic-form",
"fields": [
{
"type": "Loop",
"dataSource": "state:formSchema.fields",
"template": {
"type": "Conditional",
"condition": "{{$item.visible}} !== false",
"then": {
"name": "{{$item.name}}",
"fieldType": "{{$item.type}}",
"label": "{{$item.label}}",
"bindTo": "formData.{{$item.name}}",
"options": "{{$item.options}}"
}
}
}
]
} Nested Data Display
{
"type": "Loop",
"dataSource": "state:categories",
"template": {
"type": "Accordion",
"items": [
{
"key": "{{$item.id}}",
"title": "{{$item.name}}",
"content": {
"type": "Conditional",
"condition": "{{$item.items.length}} > 0",
"then": {
"type": "Loop",
"dataSource": "{{$item.items}}",
"template": {
"type": "Card",
"title": "{{$item.name}}",
"content": { "type": "Text", "content": "{{$item.description}}" }
}
},
"else": {
"type": "EmptyState",
"title": "No items",
"icon": "Inbox"
}
}
}
]
}
} On This Page
- Conditional
- Properties
- Condition Syntax
- Examples
- Loop
- Properties
- Loop Variables
- Examples
- Accordion
- Properties
- Item Definition
- Examples
- Section
- Properties
- Examples
- Icon
- Properties
- Sizes
- Events
- Examples
- Common Icons
- Fragment
- Properties
- Use Cases
- Slot
- Properties
- Use Cases
- Custom
- Properties
- Example
- Advanced Patterns
- State Machine Pattern
- Dynamic Form Fields
- Nested Data Display