Add iframe auto-resize via postMessage
Embeds now report content height to the parent frame using a ResizeObserver on document.body. The EmbedDialog snippet includes a listener script that adjusts the iframe height on each resize event. Documented the spicebook-resize protocol in llms.txt.
This commit is contained in:
parent
bfab38e954
commit
00fa420743
@ -598,6 +598,26 @@ iframe.contentWindow.postMessage(
|
||||
|
||||
Accepted values for `theme`: `"dark"`, `"light"`. Other messages are ignored.
|
||||
|
||||
### Auto-resize via postMessage
|
||||
|
||||
The embed reports its content height to the parent page whenever the layout changes (initial render, simulation results, expanded cells). The parent listens for `spicebook-resize` messages and updates the iframe height:
|
||||
|
||||
```javascript
|
||||
window.addEventListener('message', function(e) {
|
||||
if (e.data && e.data.type === 'spicebook-resize') {
|
||||
document.getElementById('spicebook-{notebook_id}').style.height = e.data.height + 'px';
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
The message payload:
|
||||
|
||||
```json
|
||||
{ "type": "spicebook-resize", "height": 1842 }
|
||||
```
|
||||
|
||||
`height` is `document.documentElement.scrollHeight` in pixels. The embed sends this message on every `ResizeObserver` callback, deduplicated to only fire when height actually changes. The **Embed** button's generated snippet includes this listener automatically.
|
||||
|
||||
### Discovering the embed snippet
|
||||
|
||||
In the notebook editor UI, the **Embed** button in the toolbar opens a popover with a ready-to-copy iframe snippet and a theme toggle.
|
||||
In the notebook editor UI, the **Embed** button in the toolbar opens a popover with a ready-to-copy iframe snippet (including auto-resize listener) and a theme toggle.
|
||||
|
||||
@ -38,6 +38,26 @@ export default function EmbedViewer({ notebookId, initialTheme }: EmbedViewerPro
|
||||
return () => window.removeEventListener('message', handleMessage);
|
||||
}, []);
|
||||
|
||||
// Report content height to parent frame for auto-resize
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined' || window.parent === window) return;
|
||||
|
||||
let lastHeight = 0;
|
||||
function reportHeight() {
|
||||
const height = document.documentElement.scrollHeight;
|
||||
if (height !== lastHeight) {
|
||||
lastHeight = height;
|
||||
window.parent.postMessage({ type: 'spicebook-resize', height }, '*');
|
||||
}
|
||||
}
|
||||
|
||||
const observer = new ResizeObserver(reportHeight);
|
||||
observer.observe(document.body);
|
||||
reportHeight();
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
// Keep a ref to notebook for use inside handleRun to avoid stale closures
|
||||
const notebookRef = useRef(notebook);
|
||||
notebookRef.current = notebook;
|
||||
|
||||
@ -14,12 +14,23 @@ export function EmbedDialog() {
|
||||
|
||||
const origin = typeof window !== 'undefined' ? window.location.origin : '';
|
||||
|
||||
const iframeId = `spicebook-${notebookId}`;
|
||||
|
||||
const snippet = `<iframe
|
||||
id="${iframeId}"
|
||||
src="${origin}/embed/${notebookId}?theme=${theme}"
|
||||
width="100%" height="600"
|
||||
style="border: 1px solid #334155; border-radius: 8px;"
|
||||
allow="clipboard-write"
|
||||
></iframe>`;
|
||||
></iframe>
|
||||
<script>
|
||||
window.addEventListener('message', function(e) {
|
||||
if (e.data && e.data.type === 'spicebook-resize') {
|
||||
var f = document.getElementById('${iframeId}');
|
||||
if (f) f.style.height = e.data.height + 'px';
|
||||
}
|
||||
});
|
||||
</script>`;
|
||||
|
||||
function handleCopy() {
|
||||
navigator.clipboard.writeText(snippet).then(() => {
|
||||
@ -72,7 +83,7 @@ export function EmbedDialog() {
|
||||
<textarea
|
||||
readOnly
|
||||
value={snippet}
|
||||
rows={5}
|
||||
rows={12}
|
||||
className="w-full resize-none rounded-md border border-slate-600 bg-slate-800 p-2 font-mono text-[11px] text-slate-300 focus:outline-none focus:border-blue-500"
|
||||
/>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user