← Back to all sparks
V

vellumwidget

ANALYTICS
Velocity6.3

Interactive Web Widgets for Vellum Scenes

vellumwidget is dissolving its own API: interaction now lives in the plot spec, not the widget call.

r-graphicsinteractive-widgetsdeclarative-interactionshinyhtmlwidgetsaccessibility
Current state
vellumwidget compiles a vellum scene or a vellumplot plot into a self-contained client-side htmlwidget with hover, select, brush, lasso, pan/zoom and export, and no server round-trip. The two-way Shiny story is complete: interactions surface as reactive inputs keyed by output id, and vellumwidget_proxy() drives an already-rendered widget from the server without re-rendering it. The last two releases are fidelity work rather than new surface, calibrating hit-testing from the rendered positions of marks and rendering the raster base image at 2x for HiDPI screens.
Where it's heading
The direction is declarative. 0.7.0 removed the interaction-intent arguments from as_widget() outright, dropping the signature from roughly 36 arguments to 24 and moving highlight, filter and cross-filter into vellumplot's spec via select_point(), condition() and filter_by(). Each release since has enacted more of that compiled spec on the frozen scene, from conditional encodings to single-view filters to cross-view cross-filtering, leaving the widget as an interpreter of the plot rather than a configuration surface of its own. The bug fixes track the same theme the engine's do: measured geometry and rendered geometry must not drift.
Prediction
The notes name the remaining hold-outs explicitly, saying hover_mode, crosshair, legend_click, select_mode and the tooltip-appearance arguments remain only until their spec equivalents land, so the next releases most likely move those into vellumplot and shrink as_widget() further. The scale binds flagged as following the filter work are the other stated next step.

Recent moves

  1. 14d ago

    2x raster base image for HiDPI, and exact element hit-testing

    Raster mode now renders its base image at 2x so a widget stops looking soft on a retina display, while the SVG shell stays in device pixels so hit-testing and pan/zoom are unchanged. It depends on the coordinate-space fix in vellum 0.6.6, continuing the pattern where the widget's precision work waits on the engine resolving geometry first. The size argument is made in the notes rather than asserted: 446 KB to 877 KB at 30,000 keyed points, against the 14.7 MB per-element SVG it replaces.

    View source ↗
  2. 20d ago

    Interaction moves into the plot spec; as_widget() sheds a third of its arguments

    ⚡ SPARK

    This is where the trajectory turns: interaction intent stops being widget configuration and becomes part of the plot the user already declared. It arrives with the cross-view cross-filtering and conditional encodings that only a spec-level model makes possible, plus a hit-test rewrite that calibrates from real rendered mark positions instead of viewBox math.

    View source ↗
  3. 27d ago

    Axis-aware zoom re-ticks the axes instead of scaling the whole scene

    Zoom stops behaving like an image scale and starts behaving like a charting library: only the data region scales, and the axes re-tick to the visible range while the frame, titles and legend hold position. It degrades quietly, with log, date, discrete, multi-panel and raster plots falling back to whole-scene zoom, which is the same conservative posture the widget takes elsewhere. The legend-swatch fix shipped alongside is a direct consequence of the counter-scale this feature introduced.

    View source ↗
  4. 1mo ago

    Selectable native SVG text, and crisp canvas redraw when zooming raster

    The new text argument decides whether the SVG carries selectable text elements against system fonts or font-independent glyph outlines, a choice that trades accessibility and file size against pixel fidelity rather than changing how a plot looks. Zooming a raster-mode plot no longer blurs, because points are redrawn on a canvas overlay sampled from the rendered image and the element index. Both are fidelity work on the two rendering paths the widget already had, and the two new articles document the raster and crosstalk features that had outrun the docs.

    View source ↗
  5. 1mo ago

    Server-side proxy drives a rendered widget without re-rendering it

    vellumwidget_proxy() closes the loop that 0.3.0's input read-back opened: a Shiny server can select, cross-filter, zoom and reset an already-rendered widget without a renderVellumwidget() round-trip and without losing the user's pan and zoom. The verbs key off the same data_ids the widget reports back, so the read and write sides share one identifier space. Read against the arc, this is the imperative version of a story that reappears declaratively in 0.7.0.

    View source ↗
  6. 1mo ago

    Shiny input read-back, and keyboard plus screen-reader access by default

    Two additions that both treat the widget as an application component rather than a picture: user interactions surface to Shiny as reactive inputs keyed by output id, and the SVG becomes keyboard- and screen-reader-navigable with a11y on by default. The accessibility default matches the position vellum and vellumplot took at the engine and grammar layers, so this reads as an ecosystem-wide stance rather than a widget feature. The vl_* primitive rename adopted here is the routine half of the release.

    View source ↗