Complete "Pausing computation-heavy widgets" pattern documentation
Add `IntersectionObserver` pattern for pausing expensive operations (animations, WebGL, polling) when widgets scroll out of view. - Add `visibilityBasedPause` example to `patterns.tsx` with play/pause callbacks and `onteardown` cleanup - Document pattern in `patterns.md` with link to MDN docs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
05e07a76e7
commit
3398ed49b4
2 changed files with 37 additions and 0 deletions
|
|
@ -68,6 +68,12 @@ To persist widget state across conversation reloads (e.g., current page in a PDF
|
||||||
|
|
||||||
> **Note:** For model-visible state (informing the LLM about what the user is viewing), use {@link app!App.updateModelContext updateModelContext} instead. Widget state persistence is for UI state that should survive page reloads but doesn't need to be seen by the model.
|
> **Note:** For model-visible state (informing the LLM about what the user is viewing), use {@link app!App.updateModelContext updateModelContext} instead. Widget state persistence is for UI state that should survive page reloads but doesn't need to be seen by the model.
|
||||||
|
|
||||||
|
## Pausing computation-heavy widgets when out of view
|
||||||
|
|
||||||
|
Widgets with animations, WebGL rendering, or polling can consume significant CPU/GPU even when scrolled out of view. Use [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to pause expensive operations when the widget isn't visible:
|
||||||
|
|
||||||
|
{@includeCode ./patterns.tsx#visibilityBasedPause}
|
||||||
|
|
||||||
## Lowering perceived latency
|
## Lowering perceived latency
|
||||||
|
|
||||||
Use {@link app!App.ontoolinputpartial ontoolinputpartial} to receive streaming tool arguments as they arrive, allowing you to show a loading preview before the complete input is available.
|
Use {@link app!App.ontoolinputpartial ontoolinputpartial} to receive streaming tool arguments as they arrive, allowing you to show a loading preview before the complete input is available.
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,36 @@ function persistWidgetState(app: App) {
|
||||||
//#endregion persistData
|
//#endregion persistData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example: Pausing computation-heavy widgets when out of view
|
||||||
|
*/
|
||||||
|
function visibilityBasedPause(
|
||||||
|
app: App,
|
||||||
|
container: HTMLElement,
|
||||||
|
animation: { play: () => void; pause: () => void },
|
||||||
|
) {
|
||||||
|
//#region visibilityBasedPause
|
||||||
|
// Use IntersectionObserver to pause when widget scrolls out of view
|
||||||
|
const observer = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
animation.play();
|
||||||
|
} else {
|
||||||
|
animation.pause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
observer.observe(container);
|
||||||
|
|
||||||
|
// Clean up when the host tears down the widget
|
||||||
|
app.onteardown = async () => {
|
||||||
|
observer.disconnect();
|
||||||
|
animation.pause();
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
//#endregion visibilityBasedPause
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example: Supporting both iframe & MCP Apps in same binary
|
* Example: Supporting both iframe & MCP Apps in same binary
|
||||||
*/
|
*/
|
||||||
|
|
@ -183,5 +213,6 @@ void hostStylingVanillaJs;
|
||||||
void hostStylingReact;
|
void hostStylingReact;
|
||||||
void persistWidgetStateServer;
|
void persistWidgetStateServer;
|
||||||
void persistWidgetState;
|
void persistWidgetState;
|
||||||
|
void visibilityBasedPause;
|
||||||
void iframeAndMcpApps;
|
void iframeAndMcpApps;
|
||||||
void migrateFromOpenai;
|
void migrateFromOpenai;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue