PyWry Component Reference - MANDATORY SYNTAX
STOP. THIS IS THE AUTHORITATIVE REFERENCE FOR ALL COMPONENTS. YOU MUST USE THE EXACT EVENT SIGNATURES DOCUMENTED HERE. THERE ARE NO EXCEPTIONS. NO WORKAROUNDS. NO DEVIATIONS.
CRITICAL: System Events for Widget Updates
These are the ONLY events that work for updating widgets. Use send_event tool with these event types:
AG Grid Data Updates
| Event Type | Payload | Description |
|---|---|---|
grid:update-data |
{"data": [...rows...], "strategy": "set"} |
Replace all rows |
grid:update-data |
{"data": [...rows...], "strategy": "append"} |
Append rows |
grid:update-data |
{"data": [...rows...], "strategy": "update"} |
Update existing rows |
grid:update-columns |
{"columnDefs": [...]} |
Update column definitions |
grid:update-cell |
{"rowId": "row-1", "colId": "price", "value": 99.50} |
Update single cell |
AG Grid State Persistence
| Event Type | Payload | Description |
|---|---|---|
grid:request-state |
{} |
Request current grid state |
grid:request-state |
{"gridId": "my-grid"} |
Request specific grid's state |
grid:restore-state |
{"state": {...savedState...}} |
Restore saved grid state |
grid:reset-state |
{"hard": false} |
Soft reset (keeps column order) |
grid:reset-state |
{"hard": true} |
Hard reset (full reset) |
Response Event: grid:state-response with {"gridId": "...", "state": {...}}
State Object Contents:
- Column state (width, order, visibility, pinned, sort)
- Filter state (active filters per column)
- Sort state (sorted columns and direction)
Plotly Chart Updates
| Event Type | Payload | Description |
|---|---|---|
plotly:update-figure |
{"data": [...], "layout": {...}} |
Full figure update |
plotly:update-layout |
{"layout": {...}} |
Layout only update |
plotly:reset-zoom |
{} |
Reset chart zoom to original |
Plotly State Persistence
| Event Type | Payload | Description |
|---|---|---|
plotly:request-state |
{} |
Request current chart state |
plotly:request-state |
{"chartId": "my-chart"} |
Request specific chart's state |
Response Event: plotly:state-response with {"chartId": "...", "data": [...], "layout": {...}}
Plotly Data Export
| Event Type | Payload | Description |
|---|---|---|
plotly:export-data |
{} |
Export chart data |
plotly:export-data |
{"chartId": "my-chart"} |
Export specific chart's data |
Response Event: plotly:export-response with {"data": [{"traceIndex": 0, "name": "...", "x": [...], "y": [...], "type": "..."}]}
DOM Content Updates
| Event Type | Payload | Description |
|---|---|---|
pywry:set-content |
{"id": "elementId", "text": "..."} |
Set text content |
pywry:set-content |
{"id": "elementId", "html": "..."} |
Set HTML content |
pywry:set-style |
{"id": "elementId", "styles": {"color": "red"}} |
Update CSS styles |
Theme Updates
| Event Type | Payload | Description |
|---|---|---|
pywry:update-theme |
{"theme": "dark"} |
Switch theme (dark/light/system) |
pywry:update-theme |
{"theme": "ag-theme-alpine-dark"} |
AG Grid theme |
pywry:update-theme |
{"theme": "plotly_dark"} |
Plotly template |
Toast Notifications
Use show_toast tool instead, or:
| Event Type | Payload | Description |
|---|---|---|
pywry:alert |
{"message": "...", "type": "info"} |
info, success, warning, error |
Toolbar Component State (Get/Set Values)
| Event Type | Payload | Description |
|---|---|---|
toolbar:set-value |
{"componentId": "my-select", "value": "option2"} |
Set single component value |
toolbar:set-values |
{"values": {"select-1": "A", "toggle-1": true}} |
Set multiple values at once |
toolbar:request-state |
{"componentId": "my-input"} |
Request single component value |
toolbar:request-state |
{"toolbarId": "top-toolbar"} |
Request all values in toolbar |
toolbar:request-state |
{} |
Request all toolbar values |
Response Event: toolbar:state-response with {"componentId": "...", "value": ...} or {"values": {...}}
Supported Components for set-value:
select:{"componentId": "id", "value": "option-value"}multiselect:{"componentId": "id", "value": ["a", "b"]}toggle:{"componentId": "id", "value": true}checkbox:{"componentId": "id", "value": true}text/textarea/search:{"componentId": "id", "value": "text"}number:{"componentId": "id", "value": 42}slider:{"componentId": "id", "value": 50}range:{"componentId": "id", "value": {"start": 10, "end": 90}}tabs/radio:{"componentId": "id", "value": "tab-value"}
Note: secret inputs cannot be set via toolbar:set-value for security.
Table of Contents
- Button
- Select
- MultiSelect
- Toggle
- Checkbox
- RadioGroup
- TabGroup
- TextInput
- TextArea
- SearchInput
- NumberInput
- DateInput
- SliderInput
- RangeInput
- SecretInput
- Div
- Marquee
- TickerItem
Button
A clickable button that emits an event.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"button" |
✅ YES | - | Component type identifier |
label |
string |
✅ YES | - | Button text |
event |
string |
✅ YES | - | Event name (format: namespace:action) |
variant |
string |
❌ | "primary" |
Style: primary, secondary, neutral, ghost, outline, danger, warning, icon |
size |
string |
❌ | null |
Size: xs, sm, lg, xl |
data |
object |
❌ | {} |
Extra data payload sent with event |
disabled |
boolean |
❌ | false |
Disable the button |
description |
string |
❌ | "" |
Tooltip on hover |
Event Emitted
{
componentId: "button-abc123", // Auto-generated component ID
...data // Your custom data object spread in
}
Auto-Wired Actions
When event follows elementId:action pattern, these actions work automatically:
| Event Pattern | Behavior |
|---|---|
myId:increment |
Finds id="myId", parses as number, adds 1 |
myId:decrement |
Finds id="myId", parses as number, subtracts 1 |
myId:reset |
Finds id="myId", sets to 0 |
myId:toggle |
Finds id="myId", toggles true/false |
Example
{
"type": "button",
"label": "Submit",
"event": "form:submit",
"variant": "primary",
"data": {"formId": "contact"}
}
Select
A single-select dropdown.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"select" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name (format: namespace:action) |
options |
array |
✅ YES | - | Array of {label, value} objects |
selected |
string |
❌ | "" |
Initially selected value |
label |
string |
❌ | "" |
Label text |
searchable |
boolean |
❌ | false |
Enable search filtering |
disabled |
boolean |
❌ | false |
Disable the dropdown |
Event Emitted
{
value: "selected_value", // The selected option's value
componentId: "select-abc123"
}
Example
{
"type": "select",
"label": "Theme:",
"event": "theme:change",
"options": [
{"label": "Dark", "value": "dark"},
{"label": "Light", "value": "light"},
{"label": "System", "value": "system"}
],
"selected": "dark"
}
MultiSelect
A multi-select dropdown with checkboxes.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"multiselect" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
options |
array |
✅ YES | - | Array of {label, value} objects |
selected |
array |
❌ | [] |
Initially selected values |
label |
string |
❌ | "" |
Label text |
disabled |
boolean |
❌ | false |
Disable the dropdown |
Event Emitted
{
values: ["value1", "value2"], // Array of selected values
componentId: "multiselect-abc123"
}
Example
{
"type": "multiselect",
"label": "Columns:",
"event": "columns:filter",
"options": [
{"label": "Name", "value": "name"},
{"label": "Age", "value": "age"},
{"label": "City", "value": "city"}
],
"selected": ["name", "age"]
}
Toggle
A toggle switch for boolean values.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"toggle" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
boolean |
❌ | false |
Initial state |
label |
string |
❌ | "" |
Label text |
disabled |
boolean |
❌ | false |
Disable the toggle |
Event Emitted
{
value: true, // Boolean: true or false
componentId: "toggle-abc123"
}
Example
{
"type": "toggle",
"label": "Dark Mode:",
"event": "theme:toggle",
"value": true
}
Checkbox
A single checkbox for boolean values.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"checkbox" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
boolean |
❌ | false |
Initial checked state |
label |
string |
✅ YES | - | Label text (displayed next to checkbox) |
disabled |
boolean |
❌ | false |
Disable the checkbox |
Event Emitted
{
value: true, // Boolean: true or false
componentId: "checkbox-abc123"
}
Example
{
"type": "checkbox",
"label": "Enable notifications",
"event": "settings:notify",
"value": true
}
RadioGroup
A group of radio buttons for single selection.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"radio" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
options |
array |
✅ YES | - | Array of {label, value} objects |
selected |
string |
❌ | "" |
Initially selected value |
label |
string |
❌ | "" |
Group label |
direction |
string |
❌ | "horizontal" |
Layout: horizontal or vertical |
disabled |
boolean |
❌ | false |
Disable all radios |
Event Emitted
{
value: "selected_value", // The selected option's value
componentId: "radio-abc123"
}
Example
{
"type": "radio",
"label": "View:",
"event": "view:change",
"options": [
{"label": "List", "value": "list"},
{"label": "Grid", "value": "grid"},
{"label": "Card", "value": "card"}
],
"selected": "list",
"direction": "horizontal"
}
TabGroup
Tab-style buttons for single selection (visually different from RadioGroup).
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"tabs" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
options |
array |
✅ YES | - | Array of {label, value} objects |
selected |
string |
❌ | "" |
Initially selected value |
label |
string |
❌ | "" |
Group label |
size |
string |
❌ | "md" |
Size: sm, md, lg |
disabled |
boolean |
❌ | false |
Disable all tabs |
Event Emitted
{
value: "selected_value", // The selected tab's value
componentId: "tab-abc123"
}
Example
{
"type": "tabs",
"label": "Mode:",
"event": "mode:switch",
"options": [
{"label": "Edit", "value": "edit"},
{"label": "Preview", "value": "preview"},
{"label": "Split", "value": "split"}
],
"selected": "edit"
}
TextInput
A single-line text input with debounced events.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"text" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
string |
❌ | "" |
Initial value |
placeholder |
string |
❌ | "" |
Placeholder text |
label |
string |
❌ | "" |
Label text |
debounce |
integer |
❌ | 300 |
Debounce milliseconds |
disabled |
boolean |
❌ | false |
Disable the input |
Event Emitted
{
value: "user typed text", // The current input value
componentId: "text-abc123"
}
Example
{
"type": "text",
"label": "Name:",
"event": "form:name",
"placeholder": "Enter your name",
"debounce": 300
}
TextArea
A multi-line text area with resizing.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"textarea" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
string |
❌ | "" |
Initial value |
placeholder |
string |
❌ | "" |
Placeholder text |
label |
string |
❌ | "" |
Label text |
rows |
integer |
❌ | 3 |
Number of visible rows |
cols |
integer |
❌ | 40 |
Number of visible columns |
resize |
string |
❌ | "both" |
Resize: both, horizontal, vertical, none |
debounce |
integer |
❌ | 300 |
Debounce milliseconds |
disabled |
boolean |
❌ | false |
Disable the textarea |
Event Emitted
{
value: "multi-line\ntext content", // The textarea content
componentId: "textarea-abc123"
}
Example
{
"type": "textarea",
"label": "Notes:",
"event": "form:notes",
"placeholder": "Enter your notes...",
"rows": 5,
"resize": "vertical"
}
SearchInput
A search input with magnifying glass icon.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"search" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
string |
❌ | "" |
Initial value |
placeholder |
string |
❌ | "Search..." |
Placeholder text |
label |
string |
❌ | "" |
Label text |
debounce |
integer |
❌ | 300 |
Debounce milliseconds |
disabled |
boolean |
❌ | false |
Disable the input |
Event Emitted
{
value: "search query", // The search text
componentId: "search-abc123"
}
Example
{
"type": "search",
"label": "Filter:",
"event": "table:filter",
"placeholder": "Type to filter...",
"debounce": 200
}
NumberInput
A numeric input with optional constraints.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"number" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
number |
❌ | null |
Initial value |
min |
number |
❌ | null |
Minimum value |
max |
number |
❌ | null |
Maximum value |
step |
number |
❌ | null |
Step increment |
label |
string |
❌ | "" |
Label text |
disabled |
boolean |
❌ | false |
Disable the input |
Event Emitted
{
value: 42, // The numeric value
componentId: "number-abc123"
}
Example
{
"type": "number",
"label": "Quantity:",
"event": "cart:quantity",
"value": 1,
"min": 1,
"max": 100,
"step": 1
}
DateInput
A date picker input.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"date" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
string |
❌ | "" |
Initial date (YYYY-MM-DD) |
min |
string |
❌ | "" |
Minimum date (YYYY-MM-DD) |
max |
string |
❌ | "" |
Maximum date (YYYY-MM-DD) |
label |
string |
❌ | "" |
Label text |
disabled |
boolean |
❌ | false |
Disable the input |
Event Emitted
{
value: "2025-01-29", // Date string in YYYY-MM-DD format
componentId: "date-abc123"
}
Example
{
"type": "date",
"label": "Start Date:",
"event": "filter:startDate",
"value": "2025-01-01",
"min": "2020-01-01",
"max": "2030-12-31"
}
SliderInput
A single-value slider.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"slider" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
number |
❌ | 50 |
Initial value |
min |
number |
❌ | 0 |
Minimum value |
max |
number |
❌ | 100 |
Maximum value |
step |
number |
❌ | 1 |
Step increment |
show_value |
boolean |
❌ | true |
Show value display |
debounce |
integer |
❌ | 50 |
Debounce milliseconds |
label |
string |
❌ | "" |
Label text |
disabled |
boolean |
❌ | false |
Disable the slider |
Event Emitted
{
value: 75, // The slider value
componentId: "slider-abc123"
}
Example
{
"type": "slider",
"label": "Volume:",
"event": "audio:volume",
"value": 50,
"min": 0,
"max": 100,
"step": 5,
"show_value": true
}
RangeInput
A dual-handle range slider for min/max selection.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"range" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
start |
number |
❌ | 0 |
Initial start value |
end |
number |
❌ | 100 |
Initial end value |
min |
number |
❌ | 0 |
Minimum value |
max |
number |
❌ | 100 |
Maximum value |
step |
number |
❌ | 1 |
Step increment |
show_value |
boolean |
❌ | true |
Show value displays |
debounce |
integer |
❌ | 50 |
Debounce milliseconds |
label |
string |
❌ | "" |
Label text |
disabled |
boolean |
❌ | false |
Disable the slider |
Event Emitted
{
start: 25, // Start/min value
end: 75, // End/max value
componentId: "range-abc123"
}
Example
{
"type": "range",
"label": "Price Range:",
"event": "filter:price",
"start": 100,
"end": 500,
"min": 0,
"max": 1000,
"step": 10,
"show_value": true
}
SecretInput
A password/secret input with visibility toggle and copy button.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"secret" |
✅ YES | - | Component type identifier |
event |
string |
✅ YES | - | Event name |
value |
string |
❌ | "" |
Initial secret value (stored securely) |
placeholder |
string |
❌ | "" |
Placeholder text |
label |
string |
❌ | "" |
Label text |
show_toggle |
boolean |
❌ | true |
Show visibility toggle button |
show_copy |
boolean |
❌ | true |
Show copy button |
debounce |
integer |
❌ | 300 |
Debounce milliseconds |
disabled |
boolean |
❌ | false |
Disable the input |
Events Emitted
On value change:
{
value: "base64_encoded_value", // Base64 encoded secret
encoded: true,
componentId: "secret-abc123"
}
On reveal request: (event: {event}:reveal)
{
componentId: "secret-abc123"
}
On copy request: (event: {event}:copy)
{
componentId: "secret-abc123"
}
Example
{
"type": "secret",
"label": "API Key:",
"event": "settings:apiKey",
"placeholder": "Enter your API key",
"show_toggle": true,
"show_copy": true
}
Div
A container for custom HTML content.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"div" |
✅ YES | - | Component type identifier |
content |
string |
✅ YES | - | HTML content |
component_id |
string |
❌ | auto | ID for updates via set_content |
class_name |
string |
❌ | "" |
CSS class name |
style |
string |
❌ | "" |
Inline CSS styles |
children |
array |
❌ | null |
Nested toolbar items |
Event Emitted
No automatic events. Use for layout/display only, or add interactive children.
Example
{
"type": "div",
"content": "<span style=\"color: green\">Online</span>",
"component_id": "status-display",
"style": "padding: 8px; font-weight: bold"
}
Marquee
A scrolling text ticker component.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type |
"marquee" |
✅ YES | - | Component type identifier |
text |
string |
✅ YES | - | Scrolling text content |
event |
string |
❌ | - | Event name (if clickable) |
speed |
number |
❌ | 15 |
Seconds per scroll cycle (1-300) |
direction |
string |
❌ | "left" |
Direction: left, right, up, down |
behavior |
string |
❌ | "scroll" |
Behavior: scroll, alternate, slide, static |
pause_on_hover |
boolean |
❌ | true |
Pause on mouse hover |
gap |
integer |
❌ | 50 |
Gap between content (pixels) |
clickable |
boolean |
❌ | false |
Emit event on click |
separator |
string |
❌ | "" |
Separator between repeats |
component_id |
string |
❌ | auto | ID for updates |
Event Emitted (when clickable)
{
value: "the marquee text", // The text content
componentId: "marquee-abc123"
}
Update Events
Use set_content or update_marquee tools to update:
// Update text
{id: "marquee-abc123", text: "New content!"}
// Update speed
{id: "marquee-abc123", speed: 10}
// Pause/resume
{id: "marquee-abc123", paused: true}
Example
{
"type": "marquee",
"text": "Breaking News: Market is up 5% • Weather: Sunny • More updates...",
"speed": 20,
"direction": "left",
"pause_on_hover": true,
"clickable": true,
"event": "news:click"
}
TickerItem
A helper for creating updatable items within a Marquee.
Note: TickerItem is used with build_ticker_item tool, not as a direct toolbar item.
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
ticker |
string |
✅ YES | - | Unique identifier (e.g., "AAPL") |
text |
string |
❌ | "" |
Text content |
html |
string |
❌ | "" |
HTML content (overrides text) |
class_name |
string |
❌ | "" |
CSS classes |
style |
string |
❌ | "" |
Inline styles |
Update via update_ticker_item
{
ticker: "AAPL",
text: "AAPL $186.25 ▲",
styles: {color: "#22c55e"},
class_add: "stock-up",
class_remove: "stock-down"
}
Example
# Build ticker items
items = [
build_ticker_item(ticker="AAPL", text="AAPL $185.50"),
build_ticker_item(ticker="GOOGL", text="GOOGL $142.20"),
]
# Use in marquee
marquee_text = " • ".join(items)
Toolbar Container Structure
All components go inside the toolbars array. Each toolbar has:
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
position |
string |
✅ YES | - | Position: top, bottom, left, right, header, footer, inside |
items |
array |
✅ YES | - | Array of components |
class_name |
string |
❌ | "" |
CSS class for toolbar |
Complete Example
{
"html": "<div id=\"content\">Main content here</div>",
"title": "My Widget",
"height": 600,
"toolbars": [
{
"position": "top",
"items": [
{"type": "button", "label": "Save", "event": "file:save", "variant": "primary"},
{"type": "button", "label": "Cancel", "event": "file:cancel", "variant": "secondary"},
{"type": "select", "event": "file:format", "options": [
{"label": "JSON", "value": "json"},
{"label": "CSV", "value": "csv"}
], "selected": "json"}
]
},
{
"position": "bottom",
"items": [
{"type": "div", "content": "Status: Ready", "component_id": "status"},
{"type": "slider", "event": "zoom:level", "value": 100, "min": 50, "max": 200, "label": "Zoom:"}
]
}
]
}
Event Format Rules
MANDATORY FORMAT: namespace:action
All events MUST follow this pattern:
- namespace: Starts with letter, alphanumeric only (e.g.,
form,view,settings) - action: Starts with letter, can include letters, numbers, underscores, hyphens (e.g.,
submit,change,api-key)
Valid Examples
✅ form:submit
✅ view:change
✅ settings:api-key
✅ counter:increment
✅ filter:price-range
Invalid Examples
❌ submit (no namespace)
❌ form-submit (hyphen instead of colon)
❌ 123:action (namespace starts with number)
❌ :action (empty namespace)
❌ form: (empty action)
Reserved Namespaces (DO NOT USE)
pywry- Internal PyWry eventsplotly- Plotly chart events (exceptplotly:modebar-*)grid- AG Grid events
Summary: All Component Types
| Type Value | Component | Primary Event Payload |
|---|---|---|
button |
Button | {componentId, ...data} |
select |
Select | {value, componentId} |
multiselect |
MultiSelect | {values: [], componentId} |
toggle |
Toggle | {value: boolean, componentId} |
checkbox |
Checkbox | {value: boolean, componentId} |
radio |
RadioGroup | {value, componentId} |
tabs |
TabGroup | {value, componentId} |
text |
TextInput | {value, componentId} |
textarea |
TextArea | {value, componentId} |
search |
SearchInput | {value, componentId} |
number |
NumberInput | {value: number, componentId} |
date |
DateInput | {value: "YYYY-MM-DD", componentId} |
slider |
SliderInput | {value: number, componentId} |
range |
RangeInput | {start, end, componentId} |
secret |
SecretInput | {value: base64, encoded: true, componentId} |
div |
Div | No events (display only) |
marquee |
Marquee | {value, componentId} (if clickable) |
END OF REFERENCE. USE THESE EXACT STRUCTURES. NO EXCEPTIONS.