Widgets
Suite.jl components as reactive data widgets — for Sessions.jl notebooks and Therapy.jl apps.
The Big Idea
Every Suite.jl interactive component serves double duty:
UI Component
In a Therapy.jl app, call the component as a function. It returns a VNode that renders styled HTML.
Switch(checked=true)
Input(type="email", placeholder="you@example.com")Data Widget
In a Sessions.jl notebook, pass a positional argument to get a bindable struct. Use with @bind.
@bind value Suite.Slider(1:100)
@bind lang Suite.Select(["julia" => "Julia"])Positional vs Keyword
The calling convention determines which mode you get:
| Call Style | Returns | Use Case |
|---|---|---|
| Suite.Slider(1:100) | Struct (widget) | Notebook @bind |
| Suite.Slider(; min=0, max=100) | VNode (HTML) | Therapy.jl rendering |
Positional argument = struct for @bind. Keyword-only = VNode for Therapy.jl. This keeps one function name for both contexts.
Widget Mapping
Suite.jl provides styled widget replacements for @bind in notebooks:
| Widget | Suite.jl | Bound Type | Status |
|---|---|---|---|
| Slider | Suite.Slider | eltype(range) | Available |
| CheckBox | Suite.Checkbox | Bool | Planned |
| Switch | Suite.Switch | Bool | Planned |
| Select | Suite.Select | Key type | Planned |
| Radio | Suite.RadioGroup | Key type | Planned |
| TextField | Suite.Input | String | Planned |
| TextField (multi) | Suite.Textarea | String | Planned |
| DatePicker | Suite.DatePicker | Dates.Date | Planned |
Three Tiers, Two Modes
Suite.jl's three implementation tiers interact with the dual-mode widget system:
| Tier | Therapy.jl Mode | Notebook Mode |
|---|---|---|
| Pure Styling | VNode with Tailwind classes | show(io, MIME"text/html"()) with same classes |
| Island (Wasm) | @island compiled to WebAssembly | Inline <script> for interactivity |
| Widget | Island + @bind protocol | SliderWidget struct + bond methods + HTML rendering |
Zero-Cost Dependency
The notebook integration uses Julia's package extension system. If you only use Therapy.jl, the bond protocol library is never loaded:
# Project.toml
[weakdeps]
AbstractPlutoDingetjes = "6e696c72-..."
[extensions]
SuitePlutoExt = "AbstractPlutoDingetjes"
# ext/SuitePlutoExt.jl — loaded when notebook runtime is active
module SuitePlutoExt
using Suite
import AbstractPlutoDingetjes.Bonds
Bonds.initial_value(s::Suite.SliderWidget) = s.default
Bonds.transform_value(s::Suite.SliderWidget, val) = s.values[val]
endNext Steps
- The @bind Pattern — How the bond protocol works under the hood
- Examples — Full-page compositions showing components in action
- Switch — An interactive component that doubles as a widget