Skip to content

autoResize misses absolutely-positioned portal growth (popover opens → no size-changed) #686

Description

@plmercereau

Problem

With autoResize: true (the useApp() default), opening any portal-based popover — a date-picker calendar, a Select dropdown, a tooltip — never emits ui/notifications/size-changed, so the host iframe stays at the pre-popover height and the popover is clipped.

Two independent gaps in setupSizeChangedNotifications (v1.7.4):

  1. Trigger gap: the ResizeObserver watches only document.documentElement and document.body border-boxes. Component libraries (Mantine, Radix, MUI, Floating UI…) render popovers into an absolutely-positioned portal appended to <body> — typically inside a zero-height positioned wrapper. Neither observed border-box changes, so no measurement is ever scheduled.
  2. Measurement gap: even when a measure does run, it reports documentElement.getBoundingClientRect().height under a transient height: max-content — which excludes out-of-flow content. An absolutely-positioned dropdown extending past the in-flow content does not contribute, so the reported height is unchanged anyway. (fix(app): autoResize collapses height:100% layouts; expose autoResize in useApp #619's proposed body.scrollHeight measure would fix this half, but not gap 1.)

Repro

Any React app embedded via the SDK:

const { app } = useApp({ appInfo, capabilities: {} }); // autoResize default
// render a Mantine <DatePickerInput /> near the bottom of the content

Click the input → calendar opens in a portal, extends ~300px past the content → no size-changed notification → host iframe clips the calendar. Verified against a host that resizes the iframe to every reported height (our wire-contract harness drives AppBridge directly).

Workaround we ship

A MutationObserver on body funnelled through the public API:

useEffect(() => {
  if (!app) return;
  const report = () =>
    app.sendSizeChanged({
      width: Math.ceil(window.innerWidth),
      height: Math.max(
        document.body.scrollHeight,
        document.documentElement.scrollHeight,
      ),
    });
  const mo = new MutationObserver(report);
  mo.observe(document.body, { childList: true, subtree: true, attributes: true });
  return () => mo.disconnect();
}, [app]);

scrollHeight includes the out-of-flow portal; the MutationObserver supplies the missing trigger.

Suggested fix

In setupSizeChangedNotifications, add a (debounced) MutationObserver on body alongside the existing ResizeObserver, and measure with Math.max(body.scrollHeight, documentElement.scrollHeight) (compatible with the direction #619 proposes) so out-of-flow portals are both detected and measured.

Related: #502 (height-management umbrella), #619 (measurement strategy), #567 (auto-resize side effects).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions