feat: Add Element.sizeSignal() for tracking element size via ResizeObserver#23618
feat: Add Element.sizeSignal() for tracking element size via ResizeObserver#23618Artur- wants to merge 8 commits into
Conversation
|
I'd keep this one on hold until we have refined the big picture related to responsive layouting APIs. Some open questions to consider:
|
|
I would see this as the building block for higher level features |
|
I see it as highly visible API that has the risk of not being a practical building block (e.g. if client-side breakpoints are needed) |
|
The basic building block for server side responsive layout is the ability to get the size of a component and update the view according to that. This is implemented in the signals-cases project https://github.com/vaadin/signals-cases/blob/447ea8fe247d7a729c138502ac7ee331c7995235/src/main/java/com/example/usecase11/UseCase11View.java#L282 and also in Viritin https://github.com/viritin/flow-viritin/blob/v25/src/main/java/org/vaadin/firitin/util/ResizeObserver.java Which are the real concerns here? Sure, you can do client side responsive layouting in other ways, but how is it related to this? |
…zeObserver Adds a lazily-initialized, read-only signal on Component that tracks the element's size using the browser's ResizeObserver API. A per-UI ComponentSizeObserver manages a single shared ResizeObserver instance and dispatches size updates to individual component signals.
709c9d4 to
501f5d9
Compare
|
Extract ResizeObserver setup into a reusable MissingAPI.sizeSignal() method that mirrors the future Component.sizeSignal() API (vaadin/flow#23618). UseCase11View now uses this instead of manual JS setup/teardown.
I'm concerned about polluting the very prominent Would it make sense to introduce this low-level API on the |
Extract ResizeObserver setup into a reusable MissingAPI.sizeSignal() method that mirrors the future Component.sizeSignal() API (vaadin/flow#23618). UseCase11View now uses this instead of manual JS setup/teardown.
Move the componentSizeObserver script from a flow-server META-INF resource (loaded via @jsmodule on UI) to a TypeScript file in flow-client/src/main/frontend, imported from Flow.ts. This matches the pattern already used by Geolocation and PageVisibility, so the script is bundled with the Flow client and no per-class @jsmodule annotation is needed.
Per PR review feedback, move the low-level resize-observer API from Component to Element so that the prominent Component API is not polluted with this functionality and a future high-level responsive-layout API can be added on top of it without overlap. The signal is now stored in a small SizeSignalFeature node feature so subsequent calls on the same element return the same signal instance. ComponentSizeObserver is renamed to ElementSizeObserver and updated to deal in Element.Size. The JS side (window.Vaadin.Flow.componentSizeObserver and the vaadin-component-resize event) is unchanged.
Move the Size record out of Element as nested type and into com.vaadin.flow.component.Size so the same record can back any future size-related signal (window, viewport, content, ...). Page.windowSizeSignal still returns WindowSize since that record is part of the released 25.1 API.
Align the internal JS-side names with the Element-based public API: TS file ComponentSizeObserver -> ElementSizeObserver, global window.Vaadin.Flow.componentSizeObserver -> window.Vaadin.Flow.elementSizeObserver, DOM event vaadin-component-resize -> vaadin-element-resize, and the private element fields _componentSizeId / _componentSizeObserver -> _elementSizeId / _elementSizeObserver. All of these are internal, so no released API is affected.
|



Summary
Element.sizeSignal(), a lazily-initialized read-only signal that tracks the element's current pixel size as reported by the browser'sResizeObserverAPI.com.vaadin.flow.component.Size(int width, int height)as a reusable top-level record so future size-related signals can share the same type.ResizeObserver(managed by the internalElementSizeObserver) that dispatches size updates to individual element signals via a debouncedDOM event, so adding more observed elements does not multiply browser-side observers.
Details
The signal starts at
Size(0, 0)and is updated once the browser reports the actual size. It automatically starts observing when the element is attached and stops when it is detached; subsequent calls tosizeSignal()on the same element return the same underlying signal (backed by an internalSizeSignalFeaturenodefeature).
The browser-side helper lives in
flow-client/src/main/frontend/ComponentSizeObserver.tsand is imported fromFlow.ts, so it ships with the Flow client bundle without needing a@JsModuleannotation — matching the pattern used byGeolocation.tsandPageVisibility.ts. Size deltas are coalesced and dispatched as a singlevaadin-component-resizeevent on the UI element with all changed sizes batched together.Fixes #22032