All notable changes to this project will be documented in this file.
Treemapwidget: newhovered_pathtraitlet that updates as the cursor moves over rectangles, allowing Python code to react to hover without requiring a click.
Treemapwidget: zoomable hierarchical treemap rendered on canvas with hover previews, clickable path navigation, leaf selection, contextual recoloring during zoom, and constructors for direct{name, value, children}dicts, path mappings, records, or dataframes. Ported from the Svelte components inkoaning/pytest-duration-insights.NestedTablewidget: recursive expandable table showing name, summed value, and share of the root total. Shares the same hierarchy shape andfrom_paths/from_records/from_dataframeclassmethods asTreemap.
TangleSlidernow accepts an optionalstepsparameter for non-linear value ranges. When provided, the slider cycles through the explicit list of values instead of using linear min/max/step bounds.
- ProgressBar demo now uses
.widget.valueto correctly update progress when wrapped withmo.ui.anywidget(). - ProgressBar gallery links in docs and README now point to the correct
demos/progressbar.pyinstead ofdemos/htmlwidget.py.
ApiDoc.to_markdown()method to export API documentation as a Markdown string for use in READMEs.ApiDocsignature block now has Python syntax highlighting, matching code blocks in docstrings.
- Moved example notebooks from
examples/todemos/folder. - Added infinite zoom (Droste effect) example to the docs gallery.
Painttoolbar icons: replaced generic pencil icons with a distinct pen (brush) and highlighter (marker) to make the tools easier to tell apart.
- Removed accidental
python-dotenvandumap-learncore dependencies that were not used by any widget.
Paintwidget redesigned: replaced MS Paint window chrome with a minimal toolbar (brush, marker, eraser, undo, clear, color picker). Dropped Tailwind CSS dependency in favor of scoped CSS variables with dark mode support.
Paintcanvas now respects thewidthandheighttraitlets instead of expanding to fill the host container.Paintwithinit_imagenow resizes the image to match target dimensions upfront, soget_pil()returns the correct resolution before the first stroke.
PlaySlidernow has avaluesproperty that returns all discrete values in the range, useful for pre-caching downstream results before hitting play.ParallelCoordinatesnow exposes aselectionsproperty that returns the full filtering state: completed Keep/Exclude steps plus the active brush, enabling decision-tree-style filtering audit trails.ParallelCoordinatesnow haskeep(),exclude(), andrestore()methods for programmatic control from Python.
PlaySliderno longer produces floating-point rounding artifacts (e.g.,0.30000000000000004) when using fractional step values. Both the displayed label and the synced Python value are now rounded to the step's precision.ParallelCoordinatesaxis tick labels no longer get highlighted during brush/drag interactions.
forecast_chartdemo now usesAltairWidgetfor flicker-free updates in marimo wasm mode.
AltairWidgetnow embeds the full spec (with data) on initial render, fixing blank charts for layered specs with named datasets.
forecast_chartutility function that creates a time series Altair chart with a robust exponential forecast.
ParallelCoordinatesdefault height reduced from 600px to 500px so the widget fits within marimo's default output clip without scrolling.
ThreeWidgetnow supports per-point opacity via an optionalopacitykey in each data dict (0.0–1.0, defaults to 1.0).ThreeWidgetnow acceptsxlim,ylim, andzlimparameters to fix axis bounds instead of auto-fitting from data.ThreeWidgetnow acceptscamera_azimuthandcamera_elevationparameters (in degrees) to control the initial viewing angle.ParallelCoordinatesnow accepts acolor_mapparameter to assign explicit CSS colors to categorical values (e.g.color_map={"a": "red", "b": "#0000ff"}). Any CSS color format is accepted and auto-converted.PlaySliderwidget: a range slider with a play/pause button that auto-advances the value on a configurable interval. Supports looping, step size, interval control, and light/dark themes.
ThreeWidgetno longer resets the camera on data updates, so auto-rotation continues smoothly when points change.ParallelCoordinatescategorical color assignment is now deterministic regardless of data row order. Unique values are sorted before mapping to the default palette.ParallelCoordinatesKeep/Exclude/Restore buttons now correctly updatefiltered_indices,filtered_data, andselected_indices. Previously only axis brush drags were tracked; the Keep/Exclude row filtering events from HiPlot were silently dropped.
TangleSlider,TangleChoice, andTangleSelectnow respond to external model changes viamodel.on("change:...")handlers. Previously, setting traitlet values from Python or external frameworks (e.g., Panel) had no effect on the displayed widget.TangleChoiceESM readmodel.get("value")instead ofmodel.get("choice")at initialization, causing the initial index lookup to always fall back to 0.- Removed stray
console.logfromTangleSliderESM.
AnnotationWidgetnow has adisabledtraitlet. When set, accept/fail/defer buttons, mic, and note input are greyed out while previous and save remain active.AnnotationWidgetnow has ashow_savetraitlet. WhenFalse, the save button is hidden and removed from the keyboard/gamepad shortcut reference.
ProgressBarredesigned with a cleaner, minimal style: flat dark background, configurable fill color, simpler border radius, and text below the bar. Removed gradient fills, box shadows, inset borders, and percentage overlay from the old design.ProgressBarnow supportscolor,show_text,width, andheighttraitlets for customization.ProgressBardemo moved into its own standalone notebook (demos/progressbar.py), separated from the HTML widget demos.- Annotation demo: progress bar now tracks position and shows 8/8 when all items are annotated.
- Annotation demo: annotation dict is now updated immutably via dict spread instead of mutating state in place.
ParallelCoordinatesnow works with polars DataFrames. The polarsto_dictscheck is performed before the pandasto_dictcheck, since polars also exposes.to_dict.
ParallelCoordinatesdemo notebook and docstring examples now use polars instead of pandas.
- New
examples/fashion-mnist-parallel-coords.pyexample notebook showing PCA + parallel coordinates on Fashion MNIST.
ParallelCoordinatesadded to the docs and gallery.SplineDraw.redraw()method to retrigger spline recomputation or swap in a newspline_fnat runtime.
- New
SplineDrawwidget for drawing scatter points with a Python-computed spline curve overlay. Accepts any callable with signature(x, y) -> (x_curve, y_curve)for flexible curve fitting. - New
ApiDocwidget for rendering Python class and function API documentation directly in notebooks. Introspects signatures, parameters, docstrings, methods, and properties viainspect. Features collapsible sections, colored badges, syntax highlighting, and light/dark theme support.
KeystrokeWidgetcanvas now includes a genericmonospacefallback in the font stack.AltairWidgetnow correctly renders layered and concatenated Altair charts that use multiple datasets.
- New
AltairWidgetfor flicker-free Altair chart rendering. Uses Vega's persistent View API to patch data in-place via changesets, preserving interactive state across updates.
ScatterWidgetis now re-exported from thedrawdatapackage. The importfrom wigglystuff import ScatterWidgetstill works.
- New
DiffViewerwidget for rich file diffs. Supports split and unified diff styles with syntax highlighting, dark mode, and configurable expansion of unchanged lines.
- New
ScatterWidgetfor painting multi-class 2D datasets directly in notebooks. Includes class selection, brush controls, undo/reset, and synced point data with helper conversions (data_as_pandas,data_as_polars,data_as_X_y). ScatterWidget.n_classesis now validated on assignment (not only at construction), enforcing the1..4range.ScatterWidget.data_as_X_ynow returns stable output shapes based on configured mode (n_classes==1for regression,n_classes>1for classification).
ChartSelect.from_callbackandChartPuck.from_callbacknow use proper init proxies so user callbacks that call widget helpers during the initial render no longer crash.
ChartSelectandChartPucknow work correctly with log-scale matplotlib axes. Coordinate transforms are done in Python (log10 space) so the JS frontend uses plain linear math.
Neo4jWidgetfor interactive Neo4j graph exploration. Features Cypher query input with schema-aware autocomplete, force-directed graph visualization, node/edge selection (click, ctrl-click, lasso), double-click node expansion, and zoom/pan navigation. Requires aneo4jdriver instance.
WandbChartwidget for live wandb run visualization with configurable smoothing (rolling mean, EMA, gaussian). Supports multiple runs, auto-polling, and an interactive smoothing dropdown.
- Removed
wandbfrom core dependencies. It was accidentally added as a required dependency but should only be an optional extra (pip install wigglystuff[wandb]).
ModuleTreeWidgetfor visualising PyTorchnn.Modulearchitecture as an interactive tree with parameter counts, shapes, and trainable/frozen/buffer badges.- Shared parameter detection: tied weights are marked with a "shared" badge and counted only once in totals.
- Lazy parameter detection:
nn.LazyLinearand similar modules show a "lazy" badge with "uninitialized" instead of a shape. - Unregistered module detection: warns when
nn.Moduleinstances are stored in plain Python lists instead ofnn.ModuleList. - Convenience properties:
total_param_count,total_trainable_count,total_size_bytes. - New "molab" gallery section for widgets that depend on 3rd party packages.
- Removed
**kwargsfromModuleTreeWidget.__init__.
ChartPuck.puck_colornow accepts a list of CSS colors for per-puck coloring. A single string still applies to all pucks.- New
throttleparameter onChartPuckto control how often puck positions sync to Python during drag. Set to an integer for millisecond throttling or"dragend"to sync only on release.
- Removed
**kwargsfromChartPuck.__init__; all parameters are now explicit.
- ColorPicker now shows the hex value next to the input by default (toggle with
show_label).
- ColorPicker now keeps its hex label in sync when the color is updated programmatically.
EnvConfig.get(name, default=None)method for dict-like access.- Optional
variablesparameter toEnvConfig.require_valid()to check only a subset of configured variables.
- New
ChartSelectwidget for interactive region selection on matplotlib charts. Supports box and lasso modes, returns selection coordinates in data space, and includes helper methods (get_mask(),get_indices(),get_bounds(),contains_point()). Also supportsfrom_callback()factory for auto-updating charts.
- Removed
scikit-learnfrom core dependencies. It was accidentally added but is only used by the optionalChartPuck.export_kmeans()method.
- Breaking:
ChartPuck.from_callbacknow passes the widget to the draw function instead of scalar coordinates. Signature changed fromdraw_fn(ax, x, y)todraw_fn(ax, widget), giving access to all puck positions viawidget.xandwidget.y.
- New
redraw()method onChartPuckfor manually triggering chart re-renders when external state changes. Only available for widgets created viafrom_callback(). - Added Step, Nearest, Quadratic, and Barycentric interpolation methods to the ChartPuck spline demo.
- New
ChartPuckwidget for overlaying draggable pucks on matplotlib charts. Supports single or multiple pucks, customizable styling, afrom_callbackfactory for auto-updating charts, andexport_kmeans()for using puck positions as KMeans initial centroids.
- Playwright browser integration tests for
SortableListwidget, verifying full browser-to-Python round-trip communication. - New
test-browseroptional dependency group and CI workflow for running browser tests with marimo.
- Removed unused
pydantic-aidependency that was pulling inopenaiand breaking WASM demos.
EnvConfignow displays values in input fields even when validation fails.- Removed footer color changes in
EnvConfig. Individual row highlighting is now the sole status indicator.
- New
EnvConfigwidget for environment variable configuration with validation. Displays a form UI for setting API keys with password-style masking, optional validator callbacks, and arequire_valid()method to block execution until all variables are configured.
- New
TextComparewidget for side-by-side text comparison with match highlighting. Features hover-based highlighting that syncs between panels and configurable minimum match length viamin_match_words.
- New
PulsarChartwidget for stacked waveform visualization. Features clickable rows with selection state synced back to Python, customizable overlap, stroke width, fill opacity, and peak scale.
- Fixed "Maximum call stack size exceeded" error when rendering
Slider2Don latest marimo. The widget had an infinite loop where model change handlers would trigger redraws that updated the model again.