Summary
Displaying a FacetChart in Jupyter breaks the notebook's layout: the facet grid spills across cell boundaries and the surrounding cells look wrong. Regular Charts display fine.
Repro
import numpy as np
import xy
rng = np.random.default_rng(42)
g = np.array(["A", "B", "C", "D"])[rng.integers(0, 4, 8000)]
x = rng.normal(0, 1, 8000)
y = x * np.array([0.2, 0.8, -0.5, 1.5])[np.searchsorted(["A", "B", "C", "D"], g)] + rng.normal(0, 0.4, 8000)
xy.facet_chart(
xy.scatter(x="x", y="y", size=3.0, opacity=0.5),
by="g", cols=2,
data={"x": x, "y": y, "g": g},
width=900, height=500,
)
Run in a notebook → the output renders but leaks outside its cell, visually corrupting neighboring cells.
Root cause
-
No widget display path. Chart displays via _ipython_display_ → the anywidget FigureWidget, contained in the output area. FacetChart only implements _repr_html_ (components.py:3293), which delegates to FacetGrid.to_html() (facets.py:170) — a full standalone HTML document (<!doctype html><html><head>…). Jupyter injects that markup inline into the output div, so its document-level stylesheet applies to the notebook page:
html,body{margin:0;width:100%;min-height:100%;font-family:system-ui,sans-serif;background:#fff;}
plus full-width grid styles — hence the spill.
-
Compounding: height is per-panel for facets. FacetGrid.panel_height returns self.height verbatim (facets.py:154) while width is total and divided across columns (panel_width, facets.py:150). height=500 with 2 rows quietly composes a ~1012px grid. The width/height asymmetry is easy to hit and isn't documented in facet_chart's docstring.
Suggested fix
- Give
FacetChart a real notebook path: _ipython_display_ that either composes panel FigureWidgets in a container widget, or at minimum wraps the standalone doc in an <iframe srcdoc=…> so its CSS stays sandboxed. (The iframe wrapper is a working user-side workaround today.)
- Scope the standalone doc's CSS to a root class instead of
html,body so inline injection degrades gracefully.
- Either make facet
height mean total height (divided across rows, symmetric with width) or call out the per-panel semantics in the facet_chart docstring.
Environment: Jupyter (ipywidgets/anywidget transport), Linux, xy editable install of main @ 541a7da, Python 3.14.
Summary
Displaying a
FacetChartin Jupyter breaks the notebook's layout: the facet grid spills across cell boundaries and the surrounding cells look wrong. RegularCharts display fine.Repro
Run in a notebook → the output renders but leaks outside its cell, visually corrupting neighboring cells.
Root cause
No widget display path.
Chartdisplays via_ipython_display_→ the anywidgetFigureWidget, contained in the output area.FacetChartonly implements_repr_html_(components.py:3293), which delegates toFacetGrid.to_html()(facets.py:170) — a full standalone HTML document (<!doctype html><html><head>…). Jupyter injects that markup inline into the output div, so its document-level stylesheet applies to the notebook page:plus full-width grid styles — hence the spill.
Compounding:
heightis per-panel for facets.FacetGrid.panel_heightreturnsself.heightverbatim (facets.py:154) whilewidthis total and divided across columns (panel_width,facets.py:150).height=500with 2 rows quietly composes a ~1012px grid. The width/height asymmetry is easy to hit and isn't documented infacet_chart's docstring.Suggested fix
FacetCharta real notebook path:_ipython_display_that either composes panelFigureWidgets in a container widget, or at minimum wraps the standalone doc in an<iframe srcdoc=…>so its CSS stays sandboxed. (The iframe wrapper is a working user-side workaround today.)html,bodyso inline injection degrades gracefully.heightmean total height (divided across rows, symmetric withwidth) or call out the per-panel semantics in thefacet_chartdocstring.Environment: Jupyter (ipywidgets/anywidget transport), Linux,
xyeditable install ofmain@ 541a7da, Python 3.14.