Skip to content

Plotly compatibility ​

Holochart reads Plotly figures. This page says how much of plotly.js it covers, in two parts:

  • Coverage: tables of trace types, attributes, layout keys and config options, generated by comparing the two libraries' attribute schemas.
  • Known deviations: where Holochart has the attribute but draws or behaves differently.

To move an existing chart over, start with Coming from Plotly.

Coverage ​

The tables compare plotly.js' plot-schema.json with Holochart's own (plot-schema.json), attribute by attribute. An attribute is named by its path, such as marker.line.width or annotations[].text, and is:

  • Supported when Holochart has the same path and accepts every value Plotly does;
  • Partial when Holochart has the path but accepts less (fewer enumeration values or flags, one value where Plotly also takes an array), or accepts the attribute without acting on it;
  • Missing when Holochart doesn't have the path. A missing attribute in a figure is ignored with a console warning.

This is a comparison of what the two libraries accept, not of what they draw. An attribute that is supported here can still behave differently; those cases are under Known deviations. Attributes that only Holochart has are not listed; they are in the attribute reference.

Compared with plotly.js 4.1.1.

SupportedPartialMissingTotal
Trace types0361147
Attributes of the 36 shared trace types4412 (80%)1808975489
Top-level layout keys59111888
Layout attributes1244 (73%)573991700
Config options1321833

A trace type or a layout key counts as supported only when every one of its Plotly attributes is, and as partial when Holochart has it but lacks or limits some of its attributes.

Holochart also has trace types that plotly.js does not: bar3d, chord, graph, graph3d.

chord, graph, graph3d need import '@mk7s/holochart/graph'.

Trace types ​

Plotly trace typeStatusSupportedPartialMissingNotes
barPartial179 (77%)1636Attributes
barpolarPartial136 (87%)219Attributes
boxPartial81 (77%)024Attributes
candlestickPartial53 (80%)013Attributes
carpetMissingNo carpet axes.
choroplethPartial110 (85%)218Attributes. Needs import '@mk7s/holochart/geo'
choroplethmapMissingNo tile maps (layout.map).
conePartial125 (86%)218Attributes
contourPartial155 (85%)225Attributes
contourcarpetMissingNo carpet axes.
densitymapMissingNo tile maps (layout.map).
funnelPartial149 (77%)1233Attributes
funnelareaPartial62 (64%)926Attributes
heatmapPartial132 (83%)225Attributes
histogramPartial191 (82%)736Attributes
histogram2dPartial130 (83%)225Attributes
histogram2dcontourPartial152 (85%)225Attributes
iciclePartial139 (74%)1436Attributes
imagePartial41 (77%)012Attributes
indicatorPartial105 (83%)121Attributes
isosurfacePartial142 (86%)221Attributes
mesh3dPartial130 (85%)221Attributes
ohlcPartial54 (81%)013Attributes
parcatsPartial113 (84%)219Attributes
parcoordsPartial122 (85%)220Attributes
piePartial65 (59%)1531Attributes
quiverMissing
sankeyPartial68 (58%)247Attributes
scatterPartial189 (79%)1337Attributes
scatter3dPartial242 (85%)1529Attributes
scattercarpetMissingNo carpet axes.
scattergeoPartial145 (82%)428Attributes. Needs import '@mk7s/holochart/geo'
scatterglMissingUse scatter: every Holochart trace is drawn on the GPU.
scattermapMissingNo tile maps (layout.map).
scatterpolarPartial151 (82%)429Attributes
scatterpolarglMissingUse scatterpolar: every Holochart trace is drawn on the GPU.
scattersmithMissingNo Smith charts (layout.smith).
scatterternaryMissingNo ternary subplots (layout.ternary).
splomPartial136 (86%)220Attributes
streamtubePartial126 (86%)318Attributes
sunburstPartial131 (75%)1132Attributes
surfacePartial155 (86%)421Attributes
tablePartial58 (75%)019Attributes
treemapPartial145 (74%)1436Attributes
violinPartial78 (83%)016Attributes
volumePartial143 (86%)221Attributes
waterfallPartial79 (68%)1027Attributes

The numbers count attributes of the Plotly trace type.

Trace attributes ​

In every trace type ​

These gaps are the same in every shared trace type that has the attribute in Plotly, and are left out of the lists per trace type below.

Partial:

  • marker.colorbar.exponentformat, colorbar.exponentformat: without 'SI extended'
  • marker.colorbar.tickmode, colorbar.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)

Missing: hoverlabel.font.lineposition, hoverlabel.font.shadow, hoverlabel.font.style, hoverlabel.font.textcase, hoverlabel.font.variant, hoverlabel.font.weight, hoverlabel.showarrow, hovertemplatefallback, insidetextfont.lineposition, insidetextfont.shadow, insidetextfont.textcase, insidetextfont.variant, legendgrouptitle.font.lineposition, legendgrouptitle.font.shadow, legendgrouptitle.font.textcase, legendgrouptitle.font.variant, marker.colorbar.labelalias, marker.colorbar.tickformatstops.* (5), marker.pattern.path, outsidetextfont.lineposition, outsidetextfont.shadow, outsidetextfont.textcase, outsidetextfont.variant, textfont.lineposition, textfont.textcase, textfont.variant, texttemplatefallback, xcalendar, ycalendar, colorbar.labelalias, colorbar.tickformatstops.* (5)

By trace type ​

bar: 14 partial, 3 missing

Partial:

  • cliponaxis: false is not drawn yet: labels are always clipped to the subplot
  • error_x.traceref, error_x.tracerefminus, error_y.traceref, error_y.tracerefminus: Accepted for Plotly compatibility; has no effect
  • insidetextfont.family, insidetextfont.style, insidetextfont.weight, outsidetextfont.family, outsidetextfont.style, outsidetextfont.weight, textfont.family, textfont.style, textfont.weight: one value only, no array

Missing: textfont.shadow, xhoverformat, yhoverformat

box: 10 missing

Missing: selected.marker.size, unselected.marker.size, xhoverformat, xperiod, xperiod0, xperiodalignment, yhoverformat, yperiod, yperiod0, yperiodalignment

contour: 1 missing

Missing: textfont.shadow

funnel: 10 partial, 3 missing

Partial:

  • cliponaxis: false is not drawn yet: labels are always clipped to the subplot
  • insidetextfont.family, insidetextfont.style, insidetextfont.weight, outsidetextfont.family, outsidetextfont.style, outsidetextfont.weight, textfont.family, textfont.style, textfont.weight: one value only, no array

Missing: textfont.shadow, xhoverformat, yhoverformat

funnelarea: 9 partial, 5 missing

Partial:

  • insidetextfont.family, insidetextfont.style, insidetextfont.weight, textfont.family, textfont.style, textfont.weight, title.font.family, title.font.style, title.font.weight: one value only, no array

Missing: textfont.shadow, title.font.lineposition, title.font.shadow, title.font.textcase, title.font.variant

heatmap: 1 missing

Missing: textfont.shadow

histogram: 5 partial, 3 missing

Partial:

  • cliponaxis: false is not drawn yet: labels are always clipped to the subplot
  • error_x.traceref, error_x.tracerefminus, error_y.traceref, error_y.tracerefminus: Accepted for Plotly compatibility; has no effect

Missing: textfont.shadow, xhoverformat, yhoverformat

histogram2d: 1 missing

Missing: textfont.shadow

histogram2dcontour: 1 missing

Missing: textfont.shadow

icicle: 12 partial, 5 missing

Partial:

  • insidetextfont.family, insidetextfont.style, insidetextfont.weight, outsidetextfont.family, outsidetextfont.style, outsidetextfont.weight, pathbar.textfont.family, pathbar.textfont.style, pathbar.textfont.weight, textfont.family, textfont.style, textfont.weight: one value only, no array

Missing: pathbar.textfont.lineposition, pathbar.textfont.shadow, pathbar.textfont.textcase, pathbar.textfont.variant, textfont.shadow

indicator: 1 partial, 17 missing

Partial:

  • gauge.axis.exponentformat: without 'SI extended'

Missing: delta.font.lineposition, delta.font.shadow, delta.font.textcase, delta.font.variant, gauge.axis.labelalias, gauge.axis.tickfont.lineposition, gauge.axis.tickfont.shadow, gauge.axis.tickfont.textcase, gauge.axis.tickfont.variant, number.font.lineposition, number.font.shadow, number.font.textcase, number.font.variant, title.font.lineposition, title.font.shadow, title.font.textcase, title.font.variant

isosurface: 3 missing

Missing: contour.* (3)

mesh3d: 1 missing

Missing: zcalendar

parcats: 2 partial, 14 missing

Partial:

  • line.colorbar.exponentformat: without 'SI extended'
  • line.colorbar.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)

Missing: labelfont.lineposition, labelfont.textcase, labelfont.variant, line.coloraxis, line.colorbar.labelalias, line.colorbar.tickformatstops.* (5), line.hovertemplatefallback, tickfont.lineposition, tickfont.textcase, tickfont.variant

parcoords: 2 partial, 16 missing

Partial:

  • line.colorbar.exponentformat: without 'SI extended'
  • line.colorbar.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)

Missing: labelfont.lineposition, labelfont.textcase, labelfont.variant, line.coloraxis, line.colorbar.labelalias, line.colorbar.tickformatstops.* (5), rangefont.lineposition, rangefont.textcase, rangefont.variant, tickfont.lineposition, tickfont.textcase, tickfont.variant

pie: 15 partial, 6 missing

Partial:

  • insidetextfont.family, insidetextfont.style, insidetextfont.weight, legend, legendrank, outsidetextfont.family, outsidetextfont.style, outsidetextfont.weight, showlegend, textfont.family, textfont.style, textfont.weight, title.font.family, title.font.style, title.font.weight: one value only, no array

Missing: automargin, textfont.shadow, title.font.lineposition, title.font.shadow, title.font.textcase, title.font.variant

sankey: 2 partial, 33 missing

Partial:

  • link.hovertemplate, node.hovertemplate: one value only, no array

Missing: direction, link.hoverlabel.* (14), link.hovertemplatefallback, link.sort, node.hoverlabel.* (14), node.hovertemplatefallback, node.sort

scatter: 11 partial, 13 missing

Partial:

  • error_x.traceref, error_x.tracerefminus, error_y.traceref, error_y.tracerefminus: Accepted for Plotly compatibility; has no effect
  • fillpattern.bgcolor, fillpattern.fgcolor, fillpattern.shape, fillpattern.size, fillpattern.solidity, textfont.style, textfont.weight: one value only, no array

Missing: alignmentgroup, cliponaxis, fillpattern.path, line.backoff, marker.angleref, marker.gradient.* (2), marker.line.dash, marker.standoff, offsetgroup, textfont.shadow, xhoverformat, yhoverformat

scatter3d: 13 partial, 7 missing

Partial:

  • error_x.traceref, error_x.tracerefminus, error_y.traceref, error_y.tracerefminus, error_z.traceref, error_z.tracerefminus: Accepted for Plotly compatibility; has no effect
  • error_x.width, error_y.width, error_z.width: Accepted for Plotly compatibility: 3D error bars are drawn without caps (Plotly draws them with a width of 0 by default)
  • line.colorbar.exponentformat: without 'SI extended'
  • line.colorbar.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)
  • textfont.style, textfont.weight: one value only, no array

Missing: line.colorbar.labelalias, line.colorbar.tickformatstops.* (5), zcalendar

scattergeo: 2 partial, 6 missing

Partial:

  • textfont.style, textfont.weight: one value only, no array

Missing: marker.angleref, marker.gradient.* (2), marker.line.dash, marker.standoff, textfont.shadow

scatterpolar: 2 partial, 7 missing

Partial:

  • textfont.style, textfont.weight: one value only, no array

Missing: line.backoff, marker.angleref, marker.gradient.* (2), marker.line.dash, marker.standoff, textfont.shadow

splom: 2 missing

Missing: xhoverformat, yhoverformat

streamtube: 1 partial

Partial:

  • hoverinfo: one value only, no array
sunburst: 9 partial, 1 missing

Partial:

  • insidetextfont.family, insidetextfont.style, insidetextfont.weight, outsidetextfont.family, outsidetextfont.style, outsidetextfont.weight, textfont.family, textfont.style, textfont.weight: one value only, no array

Missing: textfont.shadow

surface: 2 partial, 1 missing

Partial:

  • hovertext, text: value type data_array (Plotly: string)

Missing: zcalendar

table: 8 missing

Missing: cells.font.lineposition, cells.font.shadow, cells.font.textcase, cells.font.variant, header.font.lineposition, header.font.shadow, header.font.textcase, header.font.variant

treemap: 12 partial, 5 missing

Partial:

  • insidetextfont.family, insidetextfont.style, insidetextfont.weight, outsidetextfont.family, outsidetextfont.style, outsidetextfont.weight, pathbar.textfont.family, pathbar.textfont.style, pathbar.textfont.weight, textfont.family, textfont.style, textfont.weight: one value only, no array

Missing: pathbar.textfont.lineposition, pathbar.textfont.shadow, pathbar.textfont.textcase, pathbar.textfont.variant, textfont.shadow

violin: 4 missing

Missing: selected.marker.size, unselected.marker.size, xhoverformat, yhoverformat

volume: 3 missing

Missing: contour.* (3)

waterfall: 10 partial, 3 missing

Partial:

  • cliponaxis: false is not drawn yet: labels are always clipped to the subplot
  • insidetextfont.family, insidetextfont.style, insidetextfont.weight, outsidetextfont.family, outsidetextfont.style, outsidetextfont.weight, textfont.family, textfont.style, textfont.weight: one value only, no array

Missing: textfont.shadow, xhoverformat, yhoverformat

Layout ​

Layout keyStatusSupportedPartialMissingNotes
activeselectionMissing002
activeshapeSupported200
annotationsPartial49120
autosizeSupported100
autotypenumbersMissing001
calendarMissing001
clickanywhereMissing001
clickmodeSupported100
coloraxisPartial6826
colorscaleSupported300
colorwaySupported100
computedMissing001
datarevisionSupported100
dragmodeSupported100
editrevisionMissing001
fontSupported900
geoSupported5700Needs import '@mk7s/holochart/geo'
gridSupported1300
heightSupported100
hoveranywhereMissing001
hoverdistanceSupported100
hoverlabelPartial11012
hovermodeSupported100
hoversortMissing001
hoversubplotsMissing001
imagesSupported1500
legendPartial5303
mapMissing0044
marginSupported600
metaSupported100
minreducedheightMissing001
minreducedwidthMissing001
modebarPartial430
newselectionMissing004
newshapePartial25215
paper_bgcolorSupported100
plot_bgcolorSupported100
polarPartial13663
scenePartial292226
selectdirectionSupported100
selectionrevisionMissing001
selectionsSupported1400
separatorsSupported100
shapesPartial37418
showlegendSupported100
slidersSupported5500
smithMissing0071
spikedistanceSupported100
templateSupported100
ternaryMissing00184
titleSupported3100
transitionSupported300
uirevisionSupported100
uniformtextSupported200
updatemenusSupported3500
widthSupported100
xaxisPartial15539
yaxisPartial12339
barcornerradiusSupported100With bar, histogram traces
bargapSupported100With bar, barpolar, histogram traces
bargroupgapSupported100With bar, histogram traces
barmodeSupported100With bar, barpolar, histogram traces
barnormSupported100With bar, histogram traces
boxgapSupported100With box, candlestick traces
boxgroupgapSupported100With box, candlestick traces
boxmodeSupported100With box, candlestick traces
funnelgapSupported100With funnel traces
funnelgroupgapSupported100With funnel traces
funnelmodeSupported100With funnel traces
extendfunnelareacolorsSupported100With funnelarea traces
funnelareacolorwaySupported100With funnelarea traces
hiddenlabelsSupported100With funnelarea, pie traces
extendiciclecolorsSupported100With icicle traces
iciclecolorwaySupported100With icicle traces
extendpiecolorsSupported100With pie traces
piecolorwaySupported100With pie traces
scattergapMissing001With scatter traces
scattermodeMissing001With scatter traces
extendsunburstcolorsSupported100With sunburst traces
sunburstcolorwaySupported100With sunburst traces
extendtreemapcolorsSupported100With treemap traces
treemapcolorwaySupported100With treemap traces
violingapSupported100With violin traces
violingroupgapSupported100With violin traces
violinmodeSupported100With violin traces
waterfallgapSupported100With waterfall traces
waterfallgroupgapSupported100With waterfall traces
waterfallmodeSupported100With waterfall traces

The numbers count the attributes under each key. xaxis and yaxis stand for every axis (xaxis2, …), and likewise scene, polar, coloraxis and legend.

annotations: 12 partial

Partial:

  • annotations[].hoverlabel.bgcolor, annotations[].hoverlabel.bordercolor, annotations[].hoverlabel.font.color, annotations[].hoverlabel.font.family, annotations[].hoverlabel.font.lineposition, annotations[].hoverlabel.font.shadow, annotations[].hoverlabel.font.size, annotations[].hoverlabel.font.style, annotations[].hoverlabel.font.textcase, annotations[].hoverlabel.font.variant, annotations[].hoverlabel.font.weight: Hover label style (declared; not drawn yet)
  • annotations[].hovertext: Hover text (declared; hover labels for annotations are not drawn yet)
coloraxis: 2 partial, 6 missing

Partial:

  • coloraxis.colorbar.exponentformat: without 'SI extended'
  • coloraxis.colorbar.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)

Missing: coloraxis.colorbar.labelalias, coloraxis.colorbar.tickformatstops.* (5)

hoverlabel: 12 missing

Missing: hoverlabel.font.lineposition, hoverlabel.font.shadow, hoverlabel.font.style, hoverlabel.font.textcase, hoverlabel.font.variant, hoverlabel.font.weight, hoverlabel.grouptitlefont.lineposition, hoverlabel.grouptitlefont.shadow, hoverlabel.grouptitlefont.style, hoverlabel.grouptitlefont.textcase, hoverlabel.grouptitlefont.variant, hoverlabel.grouptitlefont.weight

legend: 3 missing

Missing: legend.groupdoubleclick, legend.titleclick, legend.titledoubleclick

modebar: 3 partial

Partial:

  • modebar.add, modebar.remove: value type info_array (Plotly: string)
  • modebar.uirevision: Accepted for Plotly compatibility; the modebar has no state of its own yet
newshape: 2 partial, 15 missing

Partial:

  • newshape.legendgroup: Legend group (declared; not used yet)
  • newshape.showlegend: Legend entry for this shape (declared; not drawn yet)

Missing: newshape.label.texttemplatefallback, newshape.legend, newshape.legendgrouptitle.* (10), newshape.legendrank, newshape.legendwidth, newshape.name

polar: 6 partial, 3 missing

Partial:

  • polar.angularaxis.categoryorder, polar.radialaxis.categoryorder: without 'geometric mean ascending', 'geometric mean descending'
  • polar.angularaxis.exponentformat, polar.radialaxis.exponentformat: without 'SI extended'
  • polar.angularaxis.tickmode, polar.radialaxis.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)

Missing: polar.angularaxis.labelalias, polar.radialaxis.calendar, polar.radialaxis.labelalias

scene: 22 partial, 6 missing

Partial:

  • scene.annotations[].hoverlabel.bgcolor, scene.annotations[].hoverlabel.bordercolor, scene.annotations[].hoverlabel.font.color, scene.annotations[].hoverlabel.font.family, scene.annotations[].hoverlabel.font.lineposition, scene.annotations[].hoverlabel.font.shadow, scene.annotations[].hoverlabel.font.size, scene.annotations[].hoverlabel.font.style, scene.annotations[].hoverlabel.font.textcase, scene.annotations[].hoverlabel.font.variant, scene.annotations[].hoverlabel.font.weight: Hover label style (declared; not drawn yet)
  • scene.annotations[].hovertext: Hover text (declared; hover labels for annotations are not drawn yet)
  • scene.uirevision: Accepted for Plotly compatibility; layout.uirevision governs them
  • scene.xaxis.categoryorder, scene.yaxis.categoryorder, scene.zaxis.categoryorder: without 'geometric mean ascending', 'geometric mean descending'
  • scene.xaxis.exponentformat, scene.yaxis.exponentformat, scene.zaxis.exponentformat: without 'SI extended'
  • scene.xaxis.tickmode, scene.yaxis.tickmode, scene.zaxis.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)

Missing: scene.xaxis.calendar, scene.xaxis.labelalias, scene.yaxis.calendar, scene.yaxis.labelalias, scene.zaxis.calendar, scene.zaxis.labelalias

shapes: 4 partial, 18 missing

Partial:

  • shapes[].legendgroup: Legend group (declared; not used yet)
  • shapes[].showlegend: Legend entry for this shape (declared; not drawn yet)
  • shapes[].xref, shapes[].yref: one value only, no array

Missing: shapes[].label.texttemplatefallback, shapes[].legend, shapes[].legendgrouptitle.* (10), shapes[].legendrank, shapes[].legendwidth, shapes[].x0shift, shapes[].x1shift, shapes[].y0shift, shapes[].y1shift

xaxis: 3 partial, 9 missing

Partial:

  • xaxis.categoryorder: without 'geometric mean ascending', 'geometric mean descending'
  • xaxis.exponentformat: without 'SI extended'
  • xaxis.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)

Missing: xaxis.calendar, xaxis.insiderange, xaxis.labelalias, xaxis.modebardisable, xaxis.ticklabelindex, xaxis.tickson, xaxis.uirevision, xaxis.unifiedhovertitle.*, xaxis.zerolinelayer

yaxis: 3 partial, 9 missing

Partial:

  • yaxis.categoryorder: without 'geometric mean ascending', 'geometric mean descending'
  • yaxis.exponentformat: without 'SI extended'
  • yaxis.tickmode: sync aligns with the overlaid axis (reserved; behaves as auto)

Missing: yaxis.calendar, yaxis.insiderange, yaxis.labelalias, yaxis.modebardisable, yaxis.ticklabelindex, yaxis.tickson, yaxis.uirevision, yaxis.unifiedhovertitle.*, yaxis.zerolinelayer

Config ​

Config optionStatusNotes
autosizableMissing
displaylogoPartialAccepted for Plotly compatibility and ignored: the modebar has no logo
displayModeBarSupported
displayNotifierMissing
doubleClickSupported
doubleClickDelaySupported
editableSupported
editsSupported
editSelectionMissing
fillFrameMissing
frameMarginsMissing
localeSupported
localesSupported
loggingMissing
modeBarButtonsMissing
modeBarButtonsToAddSupported
modeBarButtonsToRemoveSupported
notifyOnLoggingMissing
plotGlPixelRatioMissing
plotlyServerURLMissing
queueLengthMissing
responsiveSupported
scrollZoomPartialwithout 'gl3d'
setBackgroundMissing
showAxisDragHandlesMissing
showAxisRangeEntryBoxesMissing
showSendToCloudMissing
showTipsMissing
staticPlotSupported
toImageButtonOptionsSupported
topojsonURLSupported
typesetMathMissing
watermarkMissing

Known deviations ​

Holochart follows plotly.js' behavior unless there is a reason not to. These are the places where it differs on purpose, or where a Plotly behavior is not implemented yet. Each chart page has the full list for its trace type under "Plotly migration notes"; the main ones are collected here.

API and events ​

  • The functional API takes an HTMLElement, not an element id, and resolves to a Chart object instead of the element. Figure data and events are on the chart (chart.data, chart.on), not on the element. See Coming from Plotly.
  • unhover carries an empty points list. Plotly sends the points that were hovered.
  • plotly_autosize, plotly_react, plotly_update, plotly_beforeexport, plotly_afterexport, plotly_exportfail and plotly_framework are not emitted. resize takes the place of plotly_autosize.
  • A click listener that returns false cancels a sunburst, treemap or icicle drill-down. The drill-down is a restyle of level and emits restyle; Plotly animates it with animate.
  • A parcoords brush also writes the new constraintrange into the figure; Plotly only emits the event. A parcoords axis drop and a table column drag emit restyle only when the order changed.
  • Selection events of polar subplots have no range or lassoPoints, and a histogram's lists one point per selected sample where Plotly lists one per bin.
  • toImage and downloadImage make PNG, JPEG and WebP images. There is no SVG export. Sliders, update menus and the modebar are page elements and are not in the image.
  • Promises of interrupted animations settle, rejecting with an Error named AnimationInterrupted. Plotly's may never settle, or reject with undefined. See Transitions.

Dates and text ​

  • A JavaScript Date is shown at its UTC time. Plotly shows it at the browser's local time. Date strings without a UTC offset are read alike, without a time zone; Holochart converts a string with an offset (Z, +01:00) to UTC. There is no layout.timezone, and no non-Gregorian calendar (xcalendar, layout.calendar).
  • Text is drawn from font files. A font.family that isn't registered is drawn with the built-in font, TeX Gyre Heros, on every platform, where Plotly uses the fonts installed on the computer.
  • LaTeX ($…$) is not rendered. Unknown tags in text are shown literally. In titles, annotations, legends and axis labels a newline breaks the line, where Plotly shows a space. See Text.
  • In the default en-US locale, %x, %X and %c follow d3's US English (3/5/2024, 12:30:00 PM); Plotly writes 03/05/2024 and 12:30:00. See Locales.

Look ​

  • Figures without layout.template get Holochart's dark default look, not Plotly's. template: 'plotly-classic' gives Plotly's. See Default look.
  • Default colorscales come from the template too: a figure that relied on Plotly's default RdBu or Viridis gets the template's scale unless it sets colorscale.

Layout and interaction ​

  • Shapes and images above the traces are drawn below axis lines, tick labels, the legend and annotations; Plotly draws them over axis lines and tick labels. See Shapes.
  • Value-based categoryorder sorts median numerically (Plotly compares strings), and has no 'geometric mean …' orders.
  • xperiod and yperiod alignment also works on linear axes; in Plotly it applies to date axes only.
  • On axes with rangebreaks, OHLC bars, candles and heatmap cells next to a break keep their full width; Plotly narrows them.
  • Maps move under a drag in dragmode: 'zoom' as in 'pan'; Plotly moves them in 'pan' only. geo.uirevision is not read (layout.uirevision is). See Maps.
  • Pinch zoom works on cartesian subplots, and a vertical swipe scrolls the page in zoom mode. See Interaction.
  • Sliders and update menus are DOM controls with keyboard support; their labels are plain text without Plotly's markup. See Controls.
  • Transitions animate every trace type and follow autoranged axes while they move. See Transitions.

Maps ​

  • scattergeo, choropleth and layout.geo are in a package the full bundle does not register: a figure with a map needs import '@mk7s/holochart/geo'.
  • The base map is bundled Natural Earth data and nothing is fetched by default (config.topojsonURL is empty; Plotly's default is its CDN). Coastlines and borders differ slightly from Plotly's files, and disputed borders are drawn by de facto control.
  • A scoped map keeps whole every country polygon that reaches into the scope's box; Plotly's scope files are cut at the box.
  • The graticule keeps its last meridian unless it is the first one again; Plotly drops the last meridian of every map.
  • There are no modebar buttons for maps yet. Tile maps (layout.map) are not available.
  • See Maps for the rest.

3D scenes ​

  • Tick labels and axis titles face the camera; Plotly draws them along the axes.
  • A double-click resets the camera.
  • Hover picks on the GPU and respects depth: you hover what you see.
  • Holochart doesn't write the computed aspectratio and aspectmode back into the input layout.
  • Camera changes in react and in animation frames animate.
  • See 3D scenes for the rest.

Deviations by trace type ​

The main deviations of each trace type, with a link to its full migration notes.

  • scatter: scattergl is scatter. line.simplify decimates per pixel column and re-runs on zoom. A 'tonext…' fill keeps the trace order instead of moving the trace down. No marker.gradient, marker.angleref, marker.standoff, line.backoff or scattermode: 'group'. Notes: scatter, lines, areas.
  • bar: No marker.pattern.path. Default pattern colors are computed when drawing, so they are not in fullData (see patterns). Notes: bar.
  • pie: Hiding a slice re-flows the others without a transition. Outside labels don't push the margins. Notes: pie.
  • table: Rows are virtualized. Cells of a wrapped row share one baseline. columnorder in fullData is normalized to display ranks. Notes: table.
  • histogram: Restyling one member of a bingroup re-bins that trace only, until the next full recalculation. No xbins.adaptive. Notes: histogram.
  • histogram2d: A click point's pointNumber is a flat cell index, not [row, col]. Notes: histogram2d.
  • box, violin: No xperiod / yperiod. Violin scale groups are shared within a subplot, not across the figure, and the outline is not spline-smoothed. Notes: box, violin.
  • splom: Default hover labels read label: value for both dimensions; Plotly shows (x, y). Notes: splom.
  • parcoords: Unselected lines are drawn in the same pass as selected ones. Lines are 1 px wide. No line.coloraxis. Notes: parcoords.
  • parcats: A trace-level hovertemplate also applies to paths. Clicking a category band emits no click. Notes: parcats.
  • heatmap, image: zsmooth: 'fast' is bilinear filtering on the GPU. Heatmap grids over 4096 × 4096 cells are not drawn. Notes: heatmap, image.
  • contour, histogram2dcontour: A value exactly on a level counts as above it (Plotly: below). Contour smoothing runs in grid space, so smoothed lines differ slightly. Notes: contour, histogram2dcontour.
  • scatterpolar, barpolar: scatterpolargl is scatterpolar. thetaunit: 'gradians' converts gradians; plotly.js reads them as radians. Notes: scatterpolar, barpolar.
  • candlestick, ohlc: In boxmode: 'group', candles group with candlesticks only, not with boxes. %{change} and %{changepercent} are added to hovertemplate. Notes: candlestick, ohlc.
  • waterfall, funnel: In between mode, waterfall bars are not lengthened by the connector width. A funnel's marker.opacity is applied, and %{percentTotal} is formatted as a percentage. Notes: waterfall, funnel.
  • indicator: Transitions lay the number out for every in-between value, and animate delta.reference. Notes: indicator.
  • sunburst, treemap, icicle: Labels fade in at the end of a drill-down instead of moving with their sectors. Treemap and icicle labels wrap before they shrink. Notes: sunburst, treemap, icicle.
  • sankey: Cyclic graphs are laid out and drawn with loops, so node placement can differ. No node.hoverlabel or link.hoverlabel. 'snap' drags have no force simulation. Notes: sankey.
  • scattergeo: 'ISO-3' codes match in any case. Unmatched locations are named in one warning. A toself fill takes the smaller of the two regions its path bounds. No marker.gradient, marker.angleref, marker.standoff or marker.line.dash. Notes: scattergeo.
  • choropleth: A geojson wound the RFC 7946 way is rewound, with a warning. With 'geojson-id', a location given twice is drawn twice. The hover label falls back to the pointer when the region's label point is hidden. Notes: choropleth.
  • scatter3d: Projections are camera-facing sprites on the walls; Plotly flattens them onto the wall. The error bars' width is ignored. Notes: scatter3d.
  • surface: The grid is drawn as given; Plotly resamples small grids for smoother shading. Contour levels don't follow the camera. Hover reports pointNumber as [row, column]. Notes: surface.
  • mesh3d, cone: Cone sizes and alphahull scale by the trace's own data span, not by the span of every trace in the scene. A mesh's contour.width is honored. Notes: mesh3d, cone.
  • streamtube: Tubes are integrated with Runge–Kutta (RK4) steps instead of Euler steps, so curved flow is followed accurately. Colors use each sample's own norm. Notes: streamtube.
  • isosurface, volume: The triangles are Plotly's. Hover snaps to the nearest grid point. No contour. Notes: isosurface, volume.

Express lists the differences from plotly.express.

How the tables are made ​

pnpm --filter @mk7s/holochart-docs gen:compat runs apps/docs/scripts/gen-plotly-compat.ts, which the docs build runs too. It reads Holochart's schema as the docs build generates it from the registered trace types and components, and a reduced copy of plotly.js' dist/plot-schema.json (attribute names, value types and enumeration values; plotly.js is MIT licensed) kept in apps/docs/scripts/plotly-compat/. The plotly.js version is stated at the top of the coverage section.

Released under the MIT License.