Runtime UI Capabilities¶
What the Dazzle runtime actually renders for each DSL construct. Use this to understand what UI features your DSL declarations produce — the gap between "what can I declare?" and "what will the user see?"
List Surfaces (mode: list)¶
A surface with mode: list renders a DataTable component. The base table always includes:
- Rows with click-to-navigate to detail view
- Row action menu (View, Edit, Delete) with confirmation dialog on delete
- Pagination (page buttons below table)
- HTMX-powered partial updates (no full page reloads)
With sort: directive¶
Renders: - All column headers become clickable with hover state - Active sort column shows a direction indicator arrow (up/down) - Clicking a sorted column toggles direction (asc/desc) - Clicking a different column sorts by that column (asc default) - Sort state is preserved across pagination
The first sort: entry becomes the default sort on page load.
With filter: directive¶
Renders a filter bar above the table with per-field inputs:
| Field Type | Rendered As |
|---|---|
| Enum field | <select> dropdown with all enum values + "All" option |
| Bool field | <select> dropdown with Yes/No/All options |
| State machine field | <select> dropdown with all states + "All" option |
| Text/other fields | Debounced text input (300ms delay) |
- Filter changes trigger an HTMX request that swaps just the table body
- Multiple filters combine (AND logic)
- Filter state is preserved across pagination
- Empty filter values are ignored (selecting "All" clears that filter)
With search: directive¶
Renders:
- Search input field with debounced type-ahead (300ms delay)
- Clear button appears when search has text
- Search targets the fields listed in the directive
- Combines with active filters and sort
- Supported repository operators: __contains (text), __gte/__lte (dates/numbers), __in (lists)
Without search:, no search input is rendered.
With empty: directive¶
Renders: Custom message in the empty state row when no items match the current filters/search. Without this directive, defaults to "No items found."
Column Visibility¶
When a table has more than 3 columns, a "Columns" dropdown button appears next to the "New" button. Users can toggle column visibility. Preferences persist in localStorage.
Combined Example¶
surface task_list "Tasks":
uses entity Task
mode: list
section main:
field title "Title"
field status "Status"
field priority "Priority"
field due_date "Due"
ux:
sort: due_date asc
filter: status, priority
search: title, description
empty: "No tasks yet. Create your first task!"
Produces: A table with sortable headers, status dropdown filter, priority dropdown filter, search bar, custom empty message, column visibility toggle, and stateful pagination.
Attention Signals¶
ux:
attention critical:
when: due_date < today and status != done
message: "Overdue task"
action: task_edit
Renders: Row-level visual indicators based on data conditions. Signal levels map to CSS severity classes:
| Level | CSS Class | Typical Use |
|---|---|---|
critical |
danger (red) |
Data loss risk, compliance violations |
warning |
warning (amber) |
Approaching deadlines, threshold breaches |
notice |
info (blue) |
Stale data, items needing review |
info |
secondary (grey) |
Informational flags |
Signals with an action: link to the referenced surface for quick resolution.
Persona Variants¶
ux:
for admin:
scope: all
purpose: "Manage all tasks"
action_primary: task_create
for member:
scope: assigned_to = current_user
purpose: "View my tasks"
read_only: true
Renders: Role-filtered views from a single surface definition:
scope:— Server-side data filtering (admin sees all, member sees own)show:/hide:— Controls which columns/fields are visible per personaread_only: true— Hides create/edit/delete actionsaction_primary:— Highlights the primary CTA for that personadefaults:— Pre-populates form fields on create surfaces
Form Surfaces (mode: create / mode: edit)¶
Base form rendering:
| Field Type | Rendered As |
|---|---|
str |
Text input |
text |
Textarea |
int, decimal, money |
Number input |
bool |
Checkbox |
date |
Date picker |
datetime |
Datetime picker |
email |
Email input |
enum |
Select dropdown with enum values |
| State machine field | Select dropdown with valid states |
Field with source: |
Search-select widget (debounced autocomplete from external API) |
Search-Select Widget (source:)¶
Renders: Autocomplete input that queries an external API with debounce. Shows results in a dropdown with primary/secondary display fields. Selecting a result can autofill other form fields.
Detail Surfaces (mode: view)¶
- Read-only field display
- Edit and Delete action buttons
- Back navigation link
- State machine transitions — rendered as action buttons for valid transitions from current state
Workspace Layouts¶
Workspaces group surfaces into navigable sections. The runtime renders:
- Sidebar navigation with workspace items
- Active state highlighting on current route
- Collapsible sidebar on mobile
- App name and branding in the header
System Endpoints¶
/health¶
Always-public endpoint. Returns a JSON object with the current health status of the running app:
{
"status": "healthy",
"app": "my_app",
"version": "0.48.2",
"dsl_hash": "a3f9c1e2",
"uptime_seconds": 142.3
}
| Field | Description |
|---|---|
status |
Always "healthy" when the server is up |
app |
The module name from your DSL |
version |
Dazzle framework version |
dsl_hash |
First 8 hex chars of the SHA-256 of the compiled IR — changes whenever the DSL changes |
uptime_seconds |
Seconds since server startup |
Use dsl_hash in deployment pipelines to confirm a new DSL has been loaded without downtime.
/_diagnostics¶
Admin-only endpoint (requires a session with admin, super_admin, or trust_admin role). Returns a richer snapshot for operational use:
{
"entities": 12,
"surfaces": 8,
"workspaces": 3,
"features": {
"auth": true,
"files": false,
"feedback_widget": true
},
"database": {
"connected": true,
"pending_migrations": 0
},
"dsl_hash": "a3f9c1e2",
"version": "0.48.2"
}
Returns HTTP 403 for any authenticated user without an admin role. Returns HTTP 401 when no session is present.
Feedback Widget¶
When feedback_widget: enabled is declared at the module level, the runtime:
- Auto-generates a
FeedbackReportentity with fields for category, severity, description, and auto-captured context (URL, persona, viewport, user agent, console errors, navigation history, page snapshot, screenshot, and annotation data). - Injects the widget JavaScript and CSS into every authenticated page via the base template.
- Exposes the widget status in
/_diagnosticsunderfeatures.feedback_widget.
feedback_widget: enabled
position: bottom-right
shortcut: backtick
categories: [bug, ux, visual, behaviour, enhancement, other]
severities: [blocker, annoying, minor]
capture: [url, persona, viewport, user_agent, console_errors, nav_history, page_snapshot]
All fields except enabled are optional — the defaults above are used when omitted.
| Option | Default | Description |
|---|---|---|
position |
bottom-right |
Screen corner for the floating button |
shortcut |
backtick |
Keyboard shortcut to open the panel |
categories |
6 values | Dropdown options for feedback type |
severities |
3 values | Dropdown options for severity |
capture |
7 fields | Context automatically attached to each report |
The widget is only injected on authenticated pages. Public surfaces (declared with access: public) do not receive the widget.