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.

julia
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.

julia
@bind value Suite.Slider(1:100)
@bind lang Suite.Select(["julia" => "Julia"])

Positional vs Keyword

The calling convention determines which mode you get:

Call StyleReturnsUse 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:

WidgetSuite.jlBound TypeStatus
SliderSuite.Slidereltype(range)Available
CheckBoxSuite.CheckboxBoolPlanned
SwitchSuite.SwitchBoolPlanned
SelectSuite.SelectKey typePlanned
RadioSuite.RadioGroupKey typePlanned
TextFieldSuite.InputStringPlanned
TextField (multi)Suite.TextareaStringPlanned
DatePickerSuite.DatePickerDates.DatePlanned

Three Tiers, Two Modes

Suite.jl's three implementation tiers interact with the dual-mode widget system:

TierTherapy.jl ModeNotebook Mode
Pure StylingVNode with Tailwind classesshow(io, MIME"text/html"()) with same classes
Island (Wasm)@island compiled to WebAssemblyInline <script> for interactivity
WidgetIsland + @bind protocolSliderWidget 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:

julia
# 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]
end

Next 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