Skip to content

feat: Add Element.sizeSignal() for tracking element size via ResizeObserver#23618

Open
Artur- wants to merge 8 commits into
mainfrom
component-size-signal
Open

feat: Add Element.sizeSignal() for tracking element size via ResizeObserver#23618
Artur- wants to merge 8 commits into
mainfrom
component-size-signal

Conversation

@Artur-
Copy link
Copy Markdown
Member

@Artur- Artur- commented Feb 21, 2026

Summary

  • Add Element.sizeSignal(), a lazily-initialized read-only signal that tracks the element's current pixel size as reported by the browser's ResizeObserver API.
  • Introduce 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.
  • Use a single per-UI ResizeObserver (managed by the internal ElementSizeObserver) that dispatches size updates to individual element signals via a debounced
    DOM 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 to sizeSignal() on the same element return the same underlying signal (backed by an internal SizeSignalFeature node
feature).

The browser-side helper lives in flow-client/src/main/frontend/ComponentSizeObserver.ts and is imported from Flow.ts, so it ships with the Flow client bundle without needing a @JsModule annotation — matching the pattern used by Geolocation.ts and PageVisibility.ts. Size deltas are coalesced and dispatched as a single vaadin-component-resize event on the UI element with all changed sizes batched together.

Fixes #22032

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 21, 2026

Test Results

 1 409 files  +1   1 409 suites  +1   1h 25m 26s ⏱️ + 3m 11s
10 154 tests +4  10 084 ✅ +4  70 💤 ±0  0 ❌ ±0 
10 629 runs  +4  10 550 ✅ +4  79 💤 ±0  0 ❌ ±0 

Results for commit eff775b. ± Comparison against base commit c823904.

♻️ This comment has been updated with latest results.

@Legioth
Copy link
Copy Markdown
Member

Legioth commented Feb 23, 2026

I'd keep this one on hold until we have refined the big picture related to responsive layouting APIs. Some open questions to consider:

  • Most responsive layouting is based on specific breakpoints rather than exact pixel values. Would it be useful to express those breakpoints in the API for better ergonomics or to allow client-side filtering of events?
  • How important is it to be able to apply certain effect (e.g. adding or removing a CSS class name when some size crosses a breakpoint) immediately in the client without relying on a server round trip?

@Artur-
Copy link
Copy Markdown
Member Author

Artur- commented Feb 23, 2026

I would see this as the building block for higher level features

@Legioth
Copy link
Copy Markdown
Member

Legioth commented Feb 23, 2026

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)

@Artur-
Copy link
Copy Markdown
Member Author

Artur- commented Mar 15, 2026

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.
@Artur- Artur- force-pushed the component-size-signal branch from 709c9d4 to 501f5d9 Compare March 15, 2026 10:12
@sonarqubecloud
Copy link
Copy Markdown

Artur- added a commit to vaadin/use-cases that referenced this pull request Mar 15, 2026
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.
@Legioth
Copy link
Copy Markdown
Member

Legioth commented Mar 16, 2026

Which are the real concerns here?

I'm concerned about polluting the very prominent Component API with low-level functionality. More specifically, I'd want to make sure that we can soon-ish introduce a high-level API in a way that leads users towards using that API primarily and falling back to a low-level API only when appropriate.

Would it make sense to introduce this low-level API on the Element level instead of Component?

Legioth pushed a commit to vaadin/use-cases that referenced this pull request Mar 16, 2026
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.
@mshabarov mshabarov moved this from 🔎Iteration reviews to 🟢Ready to Go in Vaadin Flow | Hilla | Kits ongoing work Apr 1, 2026
@mshabarov mshabarov moved this from 🟢Ready to Go to 🪵Product backlog in Vaadin Flow | Hilla | Kits ongoing work Apr 22, 2026
Artur- added 4 commits May 7, 2026 13:57
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.
@Artur- Artur- changed the title feat: Add Component.sizeSignal() for tracking component size via ResizeObserver feat: Add Element.sizeSignal() for tracking element size via ResizeObserver May 7, 2026
@Artur- Artur- requested a review from Legioth May 7, 2026 11:38
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.
@Artur- Artur- marked this pull request as ready for review May 7, 2026 13:38
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: 🪵Product backlog

Development

Successfully merging this pull request may close these issues.

Create a ResizeObserver

3 participants