Skip to content

Commit 24e3162

Browse files
authored
Avoid a flash of incorrect sizing by forwarding fill potential before displaying the view (#136)
1 parent 780f029 commit 24e3162

File tree

5 files changed

+24
-29
lines changed

5 files changed

+24
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [UNRELEASED]
99

10+
* Widgets no longer have a "flash" of incorrect size when first rendered. (#133)
1011
* `@render_widget` now works properly with `Widget`s that aren't `DOMWidget`s (i.e., widgets that aren't meant to be displayed directly). As a result, you can now use `@render_widget` to gain a reference to the widget instance, and then use that reference to update the widget's value. (#133)
1112

1213
## [0.3.0] - 2024-01-25

examples/outputs/app.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
bokeh_dependency(),
2727
ui.output_ui("figure", fill=True, fillable=True),
2828
title="Hello Jupyter Widgets in Shiny for Python",
29+
fillable=True,
2930
)
3031

3132

js/src/output.ts

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ class IPyWidgetOutput extends Shiny.OutputBinding {
8585
el.style.visibility = "inherit";
8686
}
8787

88+
// Only forward the potential to fill if `output_widget(fillable=True)`
89+
// _and_ the widget instance wants to fill
90+
const fill = data.fill && el.classList.contains("html-fill-container");
91+
if (fill) el.classList.add("forward-fill-potential");
92+
8893
// At this time point, we should've already handled an 'open' message, and so
8994
// the model should be ready to use
9095
const model = await manager.get_model(data.model_id);
@@ -102,30 +107,9 @@ class IPyWidgetOutput extends Shiny.OutputBinding {
102107
el.removeChild(el.childNodes[0]);
103108
}
104109

105-
// Only carry the potential to fill (i.e., add fill classes)
106-
// if `output_widget(fillable=True)` _and_ the widget wants to fill
107-
const fill = data.fill && el.classList.contains("html-fill-container");
108-
109110
// The ipywidgets container (.lmWidget)
110111
const lmWidget = el.children[0] as HTMLElement;
111112

112-
if (fill) {
113-
// Make lmWidget a fill carrier
114-
// el should already be a fill carrier (done during markup generation)
115-
lmWidget?.classList.add("html-fill-container", "html-fill-item");
116-
117-
// lmWidget's children is the actual widget implementation.
118-
// Ideally this would be a single element, but some widget
119-
// implementations (e.g., pydeck, altair) have multiple direct children.
120-
// It seems relatively safe to make all of them fill items, but there's
121-
// at least one case where it's problematic (pydeck)
122-
lmWidget.childNodes.forEach((child) => {
123-
if (!(child instanceof HTMLElement)) return;
124-
if (child.classList.contains("deckgl-ui-elements-overlay")) return;
125-
child.classList.add("html-fill-item");
126-
});
127-
}
128-
129113
this._maybeResize(lmWidget);
130114
}
131115
_maybeResize(lmWidget: HTMLElement): void {

0 commit comments

Comments
 (0)