Skip to content

feat: Add Component.sizeSignal() for tracking component size via ResizeObserver#23618

Draft
Artur- wants to merge 1 commit intomainfrom
component-size-signal
Draft

feat: Add Component.sizeSignal() for tracking component size via ResizeObserver#23618
Artur- wants to merge 1 commit intomainfrom
component-size-signal

Conversation

@Artur-
Copy link
Member

@Artur- Artur- commented Feb 21, 2026

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.

@github-actions
Copy link

github-actions bot commented Feb 21, 2026

Test Results

1 264 files   -    95  1 264 suites   - 95   1h 28m 45s ⏱️ -46s
8 611 tests  - 1 250  8 504 ✅  - 1 236  52 💤  - 17  9 ❌ ±0  46 🔥 +3 
9 084 runs   - 1 228  8 966 ✅  - 1 214  61 💤  - 17  9 ❌ ±0  48 🔥 +3 

For more details on these failures and errors, see this check.

Results for commit 501f5d9. ± Comparison against base commit a5a8666.

This pull request removes 1298 and adds 48 tests. Note that renamed tests count towards both.
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplate
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplateWithComments_commentsProperlyIgnored
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplate_codeInRenderBeforeHtml_templateProperlyParsed
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplate_codeWithHtmlAfterRender_templateProperlyParsed
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplate_codeWithHtmlBeforeRender_templateProperlyParsed
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_disabled_exceptionIsThrown
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_setAttributeBinding_attributeIsIgnored
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_setClass_classIsSetAsAttribute
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_setDynamicValue_attributeIsIgnored
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_setHref_hrefIsSetAsAttribute
…
com.vaadin.flow.component.ComponentSizeSignalTest ‑ sizeSignal_defaultValue_isZeroByZero
com.vaadin.flow.component.ComponentSizeSignalTest ‑ sizeSignal_isReadOnly
com.vaadin.flow.component.ComponentSizeSignalTest ‑ sizeSignal_returnsSameInstance
com.vaadin.flow.component.ComponentSizeSignalTest ‑ sizeSignal_updatesOnResizeEvent
com.vaadin.flow.navigate.ConnectionIndicatorIT(production) ‑ offline_goingOnline_customisedMessageShown[any_Chrome_]
com.vaadin.flow.navigate.ConnectionIndicatorIT(production) ‑ offline_serverConnectionAttempted_customisedMessageShown[any_Chrome_]
com.vaadin.flow.navigate.ConnectionIndicatorIT(production) ‑ offline_serverConnectionAttempted_javaCustomisedMessagesShown[any_Chrome_]
com.vaadin.flow.navigate.ConnectionIndicatorIT(production) ‑ online_goingOffline_customisedMessageShown[any_Chrome_]
com.vaadin.flow.navigate.NavigateBetweenViewsIT(production) ‑ navigateFromViewWithSpecialCharactersInRoute[any_Chrome_]
com.vaadin.flow.navigate.NavigateBetweenViewsIT(production) ‑ navigateToViewWithSpecialCharactersInRoute[any_Chrome_]
…
This pull request removes 19 skipped tests and adds 2 skipped tests. Note that renamed tests count towards both.
com.vaadin.flow.server.frontend.BundleValidationTest ‑ bundleMissesSomeEntries_devMode_skipBundleBuildSet_noBundleRebuild(Mode)[1]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ commercialBannerBuild_commercialBannerComponentChanged_rebuildRequired(Mode)[2]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ commercialBannerBuild_commercialBannerComponentMissing_rebuildRequired(Mode)[2]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ commercialBannerBuild_commercialBannerComponentNotChanged_rebuildNotRequired(Mode)[2]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ compressedProdBundleExists_noBuildRequired(Mode)[2]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ defaultDevBundleExists_noCompressedDevBundleFile_reactDisabled_buildRequired(Mode)[1]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ defaultProdBundleExists_noCompressedProdBundleFileAndWithVersionsJsonExclusions_noBuildRequired(Mode)[2]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ defaultProdBundleExists_noCompressedProdBundleFile_noBuildRequired(Mode)[2]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ defaultProdBundleExists_noCompressedProdBundleFile_reactDisabled_buildRequired(Mode)[2]
com.vaadin.flow.server.frontend.BundleValidationTest ‑ developmentMode_commercialBannerComponentNotPresent_rebuildNotRequired(Mode)[1]
…
com.vaadin.flow.navigate.ServiceWorkerOnNestedMappingIT(production) ‑ Unknown test
com.vaadin.viteapp.ThemeReloadIT ‑ updateStyle_changeIsReloaded[any_Chrome_]

♻️ This comment has been updated with latest results.

@Legioth
Copy link
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
Member Author

Artur- commented Feb 23, 2026

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

@Legioth
Copy link
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
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

Artur- added a commit to vaadin/signals-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
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/signals-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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants