The showpiece pattern: a control Column wired to a Chart and a Stat
with jsdlink. These links are lifted into a page-level registry by the
static-export plugin, so the controls keep working with no kernel — drag
a slider on the published site and the chart responds.
import numpy as np
from ipywidgets import jsdlink
from manywidgets import Chart, Slider, Dropdown, Toggle, Row, Column
x = np.linspace(0, 10, 200)
chart = Chart(title="Signal", x_label="x", y_label="y", height=320, width=520)
chart.add_series(x=x, y=np.sin(x), name="sin")
chart.add_series(x=x, y=np.cos(x), name="cos")
kind = Dropdown(label="Chart type", options=["line", "bar", "scatter"], value="line")
legend = Toggle(label="Show legend", value=True)
height = Slider(label="Height", min=160, max=480, step=20, value=320)
# jsdlink (JS-side, directional) survives static export; prefer it over observe().
jsdlink((kind, "value"), (chart, "chart_type"))
jsdlink((legend, "value"), (chart, "legend_enabled"))
jsdlink((height, "value"), (chart, "height"))
Row(
Column(kind, legend, height, gap="10px"),
chart,
gap="24px", align="start",
)A Stat is just another link target. Here a budget Slider drives both an
animated NumberDisplay and a Stat — one source, two readouts.
from manywidgets import Stat, NumberDisplay
budget = Slider(label="Budget", min=0, max=10000, step=500, value=4000)
budget_out = NumberDisplay(label="Selected", format="${:,.0f}", duration=300)
revenue = Stat(label="Projected revenue", value=4000, unit="USD")
jsdlink((budget, "value"), (budget_out, "value"))
jsdlink((budget, "value"), (revenue, "value"))
Row(Column(budget, budget_out, gap="8px"), revenue, gap="24px", align="center")