ui primitives reference
Every UINode primitive exported from imperal_sdk.ui — props, render type, and examples
UI primitives are the building blocks for panel handlers. Every primitive is exported from imperal_sdk.ui. They serialize to a typed UINode wire format that the panel host renders into the actual UI.
This reference is grouped by category. For each primitive: signature, props table, behavioral notes, and a working code example. Where multiple props produce significant behavioral changes, separate cases are shown.
Imports
from imperal_sdk import ui
# or, for type hints:
from imperal_sdk.ui.base import UINode, UIActionAll primitives that render interactively accept one or more actions — produced by the ui.Call, ui.Navigate, ui.Send, and ui.Open helpers. See ui actions reference for the full action API.
Layout primitives
Layout primitives arrange children on screen. They do not render visible content themselves.
ui.Stack
Flex layout — vertical or horizontal. The primary panel building block.
from imperal_sdk import ui
panel_body = ui.Stack(
direction="v",
gap=4,
children=[
ui.Header("My Panel"),
ui.Text("Hello world"),
],
)Prop
Type
Behavioral notes: A horizontal Stack auto-wraps by default. Pass wrap=False to disable. sticky=True keeps the node visible as the user scrolls down. className is an escape hatch — prefer semantic props for spacing.
Production usage: Used in every panel as the primary layout container.
ui.Grid
CSS Grid layout — arranges children in a fixed-column grid.
from imperal_sdk import ui
stats_grid = ui.Grid(
columns=3,
gap=4,
children=[
ui.Stat(label="Users", value=120),
ui.Stat(label="Sessions", value=840),
ui.Stat(label="Errors", value=3, color="red"),
],
)Prop
Type
Behavioral notes: All columns are equal-width. For variable-width layouts, use ui.Stack(direction='h') instead.
ui.Row
Horizontal flex row. Alias for Stack(direction='h').
from imperal_sdk import ui
toolbar = ui.Row(
gap=2,
children=[
ui.Button("Save", variant="primary"),
ui.Button("Cancel", variant="ghost"),
],
)Prop
Type
ui.Column
Vertical flex column. Alias for Stack(direction='v').
from imperal_sdk import ui
sidebar_col = ui.Column(
gap=2,
children=[
ui.Header("Section", level=3),
ui.Text("Content here"),
],
)Prop
Type
ui.Page
Top-level page container with an optional title and subtitle header.
from imperal_sdk import ui
page = ui.Page(
title="Database Explorer",
subtitle="Browse your schema",
children=[
ui.Text("Select a table to begin."),
],
)Prop
Type
Behavioral notes: title and subtitle are only emitted to wire when non-empty.
ui.Section
Named group with optional collapsible behaviour.
from imperal_sdk import ui
section = ui.Section(
title="Advanced Settings",
collapsible=True,
children=[
ui.Toggle(label="Enable debug mode"),
],
)Prop
Type
ui.Tabs
Tabbed content. Each tab has a label and a child node.
from imperal_sdk import ui
tabs = ui.Tabs(
default_tab=0,
tabs=[
{"label": "Results", "content": ui.Text("Query results here")},
{"label": "Schema", "content": ui.Text("Schema here")},
],
)Prop
Type
Production usage: sql-db/panels_editor_tabs.py — query editor / results tabs.
ui.Accordion
Collapsible accordion — one or many sections expand on click.
from imperal_sdk import ui
accordion = ui.Accordion(
allow_multiple=False,
sections=[
{
"id": "s1",
"title": "Filters",
"children": [ui.Text("Filter controls here")],
},
{
"id": "s2",
"title": "Sort Options",
"children": [ui.Select(options=[{"value": "asc", "label": "Ascending"}])],
},
],
)Prop
Type
Data display primitives
Primitives that show structured data.
ui.List
Scrollable list of ListItem nodes — the primary sidebar content primitive.
from imperal_sdk import ui
# Basic list
item_list = ui.List(
searchable=True,
items=[
ui.ListItem(
id="1",
title="First item",
subtitle="A short description",
on_click=ui.Call("__panel__detail", item_id="1"),
),
],
)Infinite scroll (paginated):
from imperal_sdk import ui
paginated_list = ui.List(
items=[
ui.ListItem(id=str(i), title=f"Item {i}")
for i in range(50)
],
total_items=200,
on_end_reached=ui.Call("__panel__sidebar", page=2),
extra_info="200 items total",
)Selectable with bulk actions:
from imperal_sdk import ui
bulk_list = ui.List(
selectable=True,
bulk_actions=[
{"label": "Archive", "icon": "Archive", "action": ui.Call("archive_items")},
{"label": "Delete", "icon": "Trash2", "action": ui.Call("delete_items")},
],
items=[
ui.ListItem(id="msg-1", title="Report Q1"),
ui.ListItem(id="msg-2", title="Report Q2"),
],
)Prop
Type
Production usage: Primary list primitive across all sidebar panels (notes, tasks, sql-db).
ui.ListItem
A single row inside a List. Supports avatars, badges, hover actions, drag-and-drop, and expandable content.
from imperal_sdk import ui
item = ui.ListItem(
id="note-42",
title="Meeting notes",
subtitle="3 hours ago",
meta="4 KB",
icon="📄",
badge=ui.Badge("2", color="blue"),
on_click=ui.Call("__panel__editor", note_id="note-42"),
actions=[
{
"icon": "Trash2",
"on_click": ui.Call("delete_note", note_id="note-42"),
"confirm": "Delete this note?",
}
],
)Expandable item:
from imperal_sdk import ui
expandable_item = ui.ListItem(
id="folder-1",
title="My Folder",
icon="📁",
expandable=True,
expanded_content=[
ui.ListItem(id="note-1", title="Child note"),
],
)Prop
Type
Production usage: Notes sidebar folders and note entries; sql-db connection list; web-tools monitor list.
ui.DataTable
Sortable table with optional inline cell editing.
ui.DataColumn returns a plain dict, not a UINode. Do not wrap it in a list of UINodes — pass the list of dicts directly to DataTable(columns=...).
from imperal_sdk import ui
columns = [
ui.DataColumn("id", "ID", sortable=False),
ui.DataColumn("name", "Name", sortable=True),
ui.DataColumn("status", "Status", sortable=True, editable=True, edit_type="text"),
ui.DataColumn("active", "Active", sortable=False, editable=True, edit_type="toggle"),
]
table = ui.DataTable(
columns=columns,
rows=[
{"id": "1", "name": "Alice", "status": "active", "active": True},
{"id": "2", "name": "Bob", "status": "inactive", "active": False},
],
on_row_click=ui.Call("__panel__detail", row_id=""),
on_cell_edit=ui.Call("update_row"),
)Prop
Type
Production usage: sql-db/panels_editor_results.py — query results table.
ui.DataColumn
Column definition for ui.DataTable. Returns a plain dict, not a UINode.
from imperal_sdk import ui
col = ui.DataColumn(
key="status",
label="Status",
sortable=True,
width="100px",
editable=True,
edit_type="text",
)Prop
Type
ui.Stats
Horizontal grid of Stat cards.
from imperal_sdk import ui
stats_row = ui.Stats(
columns=3,
children=[
ui.Stat(label="Revenue", value="$12,400", trend="+8%", color="green"),
ui.Stat(label="Sessions", value=3840, trend="-2%", color="blue"),
ui.Stat(label="Errors", value=12, trend="+40%", color="red"),
],
)Prop
Type
ui.Stat
A single metric card — label + value + optional trend and icon.
from imperal_sdk import ui
stat = ui.Stat(
label="Active Users",
value=1_234,
trend="+12%",
icon="👥",
color="blue",
)Prop
Type
Production usage: Campaign overview panels (google-ads, meta-ads).
ui.Badge
Colored pill badge — used for statuses and counters.
from imperal_sdk import ui
badge = ui.Badge(label="New", color="blue")
count = ui.Badge(value=5, color="red")Prop
Type
ui.Avatar
Avatar with an image or fallback initial.
from imperal_sdk import ui
avatar_with_image = ui.Avatar(src="https://example.com/a.png", fallback="A", size="md")
avatar_initials = ui.Avatar(fallback="JD", size="lg")Prop
Type
ui.Timeline
Vertical timeline of events.
from imperal_sdk import ui
timeline = ui.Timeline(
items=[
{
"title": "Case opened",
"description": "Initial report filed",
"time": "2026-05-01 09:15",
"icon": "Plus",
"color": "blue",
},
{
"title": "Evidence added",
"description": "3 files attached",
"time": "2026-05-02 14:30",
"icon": "Paperclip",
"color": "green",
},
],
)Prop
Type
ui.Tree
Hierarchical tree view with optional icons.
from imperal_sdk import ui
tree = ui.Tree(
nodes=[
{
"id": "root",
"label": "Documents",
"icon": "FolderOpen",
"children": [
{"id": "f1", "label": "Reports", "icon": "Folder", "children": []},
{"id": "f2", "label": "Archives", "icon": "Folder", "children": []},
],
}
]
)Prop
Type
ui.KeyValue
Grid of key-value pairs — compact summary display.
from imperal_sdk import ui
kv = ui.KeyValue(
columns=2,
items=[
{"key": "Plan", "value": "Pro"},
{"key": "Region", "value": "EU"},
{"key": "Status", "value": "Active"},
{"key": "Created", "value": "2026-01-15"},
],
)Prop
Type
Display primitives
Read-only content nodes that present text, media, and decorative elements.
ui.Text
Plain text block with a semantic variant.
from imperal_sdk import ui
heading_text = ui.Text("Dashboard", variant="heading")
body_text = ui.Text("Select an item to view details.")
caption = ui.Text("Last updated 2 hours ago", variant="caption")
inline_code = ui.Text("SELECT * FROM users", variant="code")Prop
Type
ui.Header
Section heading rendered as h1–h4 with an optional subtitle.
from imperal_sdk import ui
h = ui.Header("Query Results", level=2, subtitle="42 rows returned")Prop
Type
ui.Markdown
Raw Markdown rendered to HTML by the panel host.
from imperal_sdk import ui
md = ui.Markdown(content="## Summary\n\nThis is **bold** and this is `code`.")Prop
Type
ui.Code
Syntax-highlighted code block with optional line numbers.
from imperal_sdk import ui
code_block = ui.Code(
content="SELECT id, name FROM users WHERE active = TRUE;",
language="sql",
line_numbers=True,
)Prop
Type
ui.Icon
Lucide icon rendered inline.
from imperal_sdk import ui
icon = ui.Icon(name="AlertTriangle", size=20, color="red")Prop
Type
ui.Image
Image element with optional click action, sizing, and caption.
from imperal_sdk import ui
img = ui.Image(
src="https://example.com/chart.png",
alt="Monthly revenue chart",
width="100%",
caption="Revenue trend — last 6 months",
on_click=ui.Open("https://example.com/chart.png"),
)Prop
Type
ui.Html
Raw HTML block. Sandboxed in an iframe by default.
from imperal_sdk import ui
email_body = ui.Html(
content="<p>Hello <b>world</b></p>",
sandbox=True,
max_height=400,
theme="light",
)Prop
Type
ui.Video
HTML5 video player supporting mp4, webm, ogg, and HLS streams.
from imperal_sdk import ui
video = ui.Video(
src="https://example.com/demo.mp4",
poster="https://example.com/poster.png",
title="Product walkthrough",
controls=True,
autoplay=False,
width="100%",
)Prop
Type
ui.Audio
HTML5 audio player.
from imperal_sdk import ui
audio = ui.Audio(
src="https://example.com/recording.mp3",
title="Call recording",
controls=True,
)Prop
Type
ui.Divider
Horizontal rule with an optional centered label.
from imperal_sdk import ui
plain_divider = ui.Divider()
labeled_divider = ui.Divider(label="OR")Prop
Type
Interactive primitives
Primitives that accept user input or fire actions on interaction.
ui.Button
Clickable button with variant, size, icon, and disabled state.
from imperal_sdk import ui
save_btn = ui.Button("Save", variant="primary", on_click=ui.Call("save_item"))
cancel_btn = ui.Button("Cancel", variant="ghost")
danger_btn = ui.Button(
"Delete",
variant="destructive",
icon="Trash2",
size="sm",
on_click=ui.Call("delete_item", item_id="abc"),
)
wide_btn = ui.Button("Export All", full_width=True)Prop
Type
ui.Card
Container card with optional title, subtitle, content, and footer slots.
from imperal_sdk import ui
info_card = ui.Card(
title="User Summary",
subtitle="Last active 2 hours ago",
content=ui.KeyValue(items=[
{"key": "Email", "value": "alice@example.com"},
{"key": "Plan", "value": "Pro"},
]),
footer=ui.Row(children=[
ui.Button("Edit", variant="secondary", on_click=ui.Call("edit_user")),
]),
)
clickable_card = ui.Card(
title="Open Report",
on_click=ui.Call("__panel__report"),
)Prop
Type
ui.Menu
Dropdown menu with a configurable trigger.
from imperal_sdk import ui
context_menu = ui.Menu(
trigger=ui.Button("Actions", variant="outline", icon="⬇️"),
items=[
{"label": "Edit", "icon": "Pencil", "on_click": ui.Call("edit_item")},
{"separator": True},
{"label": "Delete", "icon": "Trash2", "on_click": ui.Call("delete_item")},
],
)Prop
Type
ui.Dialog
Modal dialog with a confirm and cancel action.
from imperal_sdk import ui
confirm_dialog = ui.Dialog(
title="Delete item?",
content=ui.Text("This action cannot be undone."),
confirm_label="Delete",
cancel_label="Cancel",
on_confirm=ui.Call("delete_item", item_id="abc"),
)Prop
Type
ui.Tooltip
Hover tooltip wrapping a child node.
from imperal_sdk import ui
icon_with_tip = ui.Tooltip(
content="This field is required",
children=ui.Icon("HelpCircle", size=14),
)Prop
Type
ui.Link
Hyperlink that navigates via href or fires an action.
from imperal_sdk import ui
external_link = ui.Link("View docs", href="https://docs.imperal.io")
action_link = ui.Link("Open panel", on_click=ui.Call("__panel__editor"))
# label= and text= are equivalent (v4.2.11+); pick whichever feels natural
canonical = ui.Link(label="View docs", href="https://docs.imperal.io")
alias = ui.Link(text="View docs", href="https://docs.imperal.io")Prop
Type
ui.SlideOver
Side panel that slides in from the right — for detail views or forms.
from imperal_sdk import ui
slide_over = ui.SlideOver(
title="Edit Record",
subtitle="Update the selected row",
width="lg",
open=True,
on_close=ui.Call("__panel__main"),
children=[
ui.Form(
children=[ui.Input(placeholder="Name")],
submit_label="Save",
)
],
)Prop
Type
Form and input primitives
Input primitives collect user data. Each has a param_name prop (default varies) — the key under which the current value is merged into an action's params when the action fires.
ui.Form
Form container — collects all child input values and submits them as a single action.
from imperal_sdk import ui
create_form = ui.Form(
submit_label="Create",
action="create_note",
defaults={"title": "Untitled"},
children=[
ui.Input(placeholder="Title"),
ui.Select(
options=[
{"value": "personal", "label": "Personal"},
{"value": "work", "label": "Work"},
],
placeholder="Category",
),
],
)Prop
Type
Production usage: sql-db/panels_editor_row_form.py, web-tools/panels_setup.py.
ui.Input
Single-line text input. Fires on_submit on Enter.
from imperal_sdk import ui
search_input = ui.Input(
placeholder="Search notes…",
param_name="query",
on_submit=ui.Call("search_notes"),
)
# v4.2.6+ — type hint for the native HTML <input type=...> behaviour
email_input = ui.Input(
placeholder="you@example.com",
type="email",
param_name="email",
)Prop
Type
ui.Password
Browser-blind credential-entry input. Renders as <input type="password" autocomplete="new-password" spellcheck="false"> so values are visually masked while the user types and don't pollute the browser's autofill database.
from imperal_sdk import ui
api_key_field = ui.Form(
action="save_app_secret",
submit_label="Save",
defaults={"app_id": "ext-123", "name": "openai_api_key"},
children=[
ui.Password(
placeholder="sk-proj-...",
param_name="value",
),
],
)Prop
Type
Federal note: type="password" is a defence against shoulder-surfing, not a security control. The plaintext still travels in the POST body to the server, which is the only correctness boundary. The platform's audit chokepoint + KMS encryption are what make EXT-SECRETS-V1 federal-grade. See @ext.secret reference and Federal contract.
Required for EXT-SECRETS-V1 surfaces: Dev Portal Secrets tab, Panel SecretManagerCard equivalents, and any other extension UI that captures a credential MUST use ui.Password instead of ui.Input for write_mode='user'/'both' secrets.
Available since: v4.2.6.
Production usage: imperal-ext-developer/panels_secrets.py — Dev Portal Secrets tab in App Details dashboard.
ui.TextArea
Multi-line text area.
from imperal_sdk import ui
comment_box = ui.TextArea(
placeholder="Add a comment…",
rows=6,
param_name="comment",
on_submit=ui.Call("add_comment"),
)Prop
Type
ui.RichEditor
Rich text editor backed by TipTap. Content is an HTML string.
from imperal_sdk import ui
editor = ui.RichEditor(
content="<p>Start writing here…</p>",
placeholder="Write your note",
toolbar=True,
param_name="content",
on_save=ui.Call("save_note", note_id="abc"),
on_change=ui.Call("autosave_note", note_id="abc"),
)Prop
Type
Use content= (not value=). The prop is named content on this primitive.
Production usage: notes/panels_editor.py — primary notes editing surface.
ui.Select
Single-select dropdown.
from imperal_sdk import ui
status_select = ui.Select(
options=[
{"value": "active", "label": "Active"},
{"value": "inactive", "label": "Inactive"},
{"value": "archived", "label": "Archived"},
],
value="active",
placeholder="Select status",
param_name="status",
on_change=ui.Call("filter_by_status"),
)Prop
Type
ui.MultiSelect
Multi-select dropdown. Selected values are a list.
from imperal_sdk import ui
tag_select = ui.MultiSelect(
options=[
{"value": "python", "label": "Python"},
{"value": "javascript", "label": "JavaScript"},
{"value": "sql", "label": "SQL"},
],
values=["python"],
placeholder="Select languages",
param_name="languages",
)Prop
Type
ui.Toggle
Boolean toggle switch.
from imperal_sdk import ui
notifications_toggle = ui.Toggle(
label="Email notifications",
value=True,
param_name="enabled",
on_change=ui.Call("update_notifications"),
)Prop
Type
ui.Slider
Numeric range slider.
from imperal_sdk import ui
quality_slider = ui.Slider(
label="Compression quality",
min=0,
max=100,
value=80,
step=5,
param_name="quality",
)Prop
Type
ui.DatePicker
Date picker calendar input. Value is an ISO date string.
from imperal_sdk import ui
due_date = ui.DatePicker(
value="2026-06-01",
placeholder="Select due date",
param_name="due_date",
on_change=ui.Call("update_due_date"),
)Prop
Type
ui.FileUpload
File upload dropzone. The panel host sends base64-encoded file data in the action params.
from imperal_sdk import ui
uploader = ui.FileUpload(
accept="image/*",
max_size_mb=5,
multiple=True,
max_files=10,
blocked_extensions=["exe", "bat", "sh"],
param_name="files",
on_upload=ui.Call("upload_attachments"),
)Prop
Type
ui.TagInput
Tag/chip input with autocomplete and optional validation.
from imperal_sdk import ui
tag_input = ui.TagInput(
values=["python", "sdk"],
suggestions=["python", "javascript", "sql", "sdk", "api"],
placeholder="Add tag…",
param_name="tags",
delimiters=[",", " "],
validate=r"^[a-z0-9-]+$",
validate_message="Tags must be lowercase letters, numbers, and hyphens only.",
on_change=ui.Call("update_tags"),
)Prop
Type
Feedback primitives
Status and feedback nodes — loading states, alerts, and progress.
ui.Alert
Alert banner with severity level.
from imperal_sdk import ui
warn_alert = ui.Alert(message="Quota at 90%", title="Warning", type="warn")
error_alert = ui.Alert(message="Connection lost", title="Error", type="error")
ok_alert = ui.Alert(message="Deployment successful", title="Success", type="success")
info_alert = ui.Alert(message="Read-only mode is active", type="info")Prop
Type
ui.Loading
Loading state indicator.
from imperal_sdk import ui
spinner = ui.Loading(message="Loading connections…", variant="spinner")
skeleton = ui.Loading(message="", variant="skeleton")
dots = ui.Loading(variant="dots")Prop
Type
ui.Error
Error state with optional retry action.
from imperal_sdk import ui
error_state = ui.Error(
message="Could not load data.",
title="Connection Error",
retry=ui.Call("__panel__sidebar"),
)Prop
Type
ui.Empty
Empty state placeholder with an optional call-to-action.
from imperal_sdk import ui
empty = ui.Empty(
message="No notes yet",
icon="🗒️",
action=ui.Send("Create my first note"),
)Prop
Type
ui.Progress
Progress bar or circular indicator (0–100).
from imperal_sdk import ui
bar = ui.Progress(value=72, label="Processing…", variant="bar", color="blue")
ring = ui.Progress(value=45, label="45% complete", variant="circular", color="green")Prop
Type
ui.Chart
Line, bar, or pie chart backed by Recharts.
from imperal_sdk import ui
line_chart = ui.Chart(
data=[
{"name": "Jan", "revenue": 4200, "cost": 1800},
{"name": "Feb", "revenue": 5100, "cost": 1950},
{"name": "Mar", "revenue": 4800, "cost": 2100},
],
type="line",
x_key="name",
height=240,
colors={"revenue": "#2563eb", "cost": "#dc2626"},
)
# Mixed-scale chart: cost on the right Y-axis
mixed_chart = ui.Chart(
data=[
{"name": "Jan", "clicks": 1200, "spend": 340.50},
{"name": "Feb", "clicks": 1800, "spend": 480.20},
],
type="bar",
x_key="name",
height=220,
y2_keys=["spend"],
)Prop
Type
Production usage: SeeU-Extensions/google-ads/panels_reports.py — performance over time.
Graph primitive
ui.Graph
Interactive entity/relationship graph rendered with Cytoscape.js.
from imperal_sdk import ui
graph = ui.Graph(
nodes=[
{"id": "u1", "label": "Alice", "type": "person"},
{"id": "u2", "label": "Bob", "type": "person"},
{"id": "c1", "label": "Acme", "type": "company"},
],
edges=[
{"id": "e1", "source": "u1", "target": "c1", "label": "works_at"},
{"id": "e2", "source": "u2", "target": "c1", "label": "works_at"},
],
layout="cose-bilkent",
height=600,
color_by="type",
on_node_click=ui.Call("__panel__entity_detail"),
)Cytoscape format input (from an API response):
from imperal_sdk import ui
# SDK normalises Cytoscape {"data": {...}} wrapper automatically.
graph_from_api = ui.Graph(
nodes=[{"data": {"id": "n1", "label": "Node 1", "type": "entity"}}],
edges=[{"data": {"id": "e1", "source": "n1", "target": "n1", "label": "self"}}],
layout="circle",
height=400,
)Prop
Type
Behavioral notes: Designed for up to ~5,000 nodes. Filter upstream for larger datasets. Layout cose-bilkent produces the most readable result for entity/relationship graphs. breadthfirst is best for hierarchical data.
Actions (UIAction helpers)
Actions are not UINodes — they are UIAction objects passed as prop values (e.g. on_click, on_submit). They tell the panel host what to do when the user interacts with a node.
For the full action reference see ui actions reference.
ui.Call
Direct function call — executes a @chat.function or panel handler without going through the chat pipeline.
from imperal_sdk import ui
open_panel = ui.Call("__panel__editor", note_id="abc")
run_fn = ui.Call("archive_note", note_id="abc")ui.Navigate
Client-side navigation.
from imperal_sdk import ui
nav = ui.Navigate("/dashboard")ui.Send
Send a pre-composed message to the chat input.
from imperal_sdk import ui
send = ui.Send("Show me the latest report")ui.Open
Open a URL in a new browser tab.
from imperal_sdk import ui
open_url = ui.Open("https://docs.imperal.io")ui.TrayResponse
Return value for @ext.tray handlers. Combines a badge UINode and a panel UINode.
from imperal_sdk import ui
def build_tray_response(unread_count: int) -> ui.TrayResponse: # type: ignore[attr-defined]
badge = ui.Badge(str(unread_count), color="red" if unread_count else "gray")
panel = ui.List(items=[]) if not unread_count else None
return ui.TrayResponse(badge=badge, panel=panel)Prop
Type
@ext.tray is marked experimental. Frontend rendering support is not guaranteed in all panel host versions.
Theme utility
ui.theme(ctx)
Read the active agency's white-label theme. Returns a frozen AgencyTheme dataclass.
from imperal_sdk import ui
async def my_panel(ctx, **kwargs): # type: ignore[attr-defined]
agency_theme = ui.theme(ctx)
primary = agency_theme.colors.get("primary")
primary_hex = primary.light if primary else "#2563eb"
return ui.Card(title="Report")Prop
Type
Returns: AgencyTheme(colors: dict[str, ColorPair], density: 'compact'|'default'|'spacious', radius: 'sharp'|'default'|'rounded').
ColorPair has .light and .dark fields (CSS-valid color strings).
Most extensions do not need ui.theme(). Emit semantic intent (variant="primary", color="green") and let the panel host resolve against CSS variables. Use ui.theme() only when you need the raw color value for domain-specific pixel rendering.
Base types
UINode
All primitive constructors return UINode(type: str, props: dict). You rarely construct this directly — use the named helpers above.
from imperal_sdk.ui.base import UINode
node = UINode(type="Text", props={"content": "Hello", "variant": "body"})
wire = node.to_dict()
# {"type": "Text", "props": {"content": "Hello", "variant": "body"}}None props are omitted from the wire output. Nested UINode and UIAction objects are recursively serialized.
UIAction
Returned by ui.Call, ui.Navigate, ui.Send, and ui.Open. Serializes to a flat dict on the wire.
from imperal_sdk.ui.base import UIAction
action = UIAction(action="call", params={"function": "my_fn", "params": {"id": "1"}})
wire = action.to_dict()
# {"action": "call", "function": "my_fn", "params": {"id": "1"}}Primitive count summary
| Category | Primitives |
|---|---|
| Layout | Stack, Grid, Row, Column, Page, Section, Tabs, Accordion — 8 |
| Data display | List, ListItem, DataTable, DataColumn, Stats, Stat, Badge, Avatar, Timeline, Tree, KeyValue — 11 |
| Display | Text, Header, Markdown, Code, Icon, Image, Html, Video, Audio, Divider — 10 |
| Interactive | Button, Card, Menu, Dialog, Tooltip, Link, SlideOver — 7 |
| Form/Input | Form, Input, Password, TextArea, RichEditor, Select, MultiSelect, Toggle, Slider, DatePicker, FileUpload, TagInput — 12 |
| Feedback | Alert, Loading, Error, Empty, Progress, Chart — 6 |
| Graph | Graph — 1 |
| Actions | Call, Navigate, Send, Open, TrayResponse — 5 |
| Theme | theme — 1 |
| Total | 61 |
Cross-references
- ui actions reference — deep dive on
Call,Navigate,Send,Open - Decorators reference —
@ext.panel,@ext.tray,@chat.function - Panels concept — panel slots, refresh lifecycle, auto-action
- Panel layouts guide — composition patterns for each slot
- Panel master-detail recipe — List + detail panel wiring
- Panel auto-action on load — open a detail panel on mount
- Panel refresh after write —
refresh_panels+ event-driven refresh