feat(useResizeObserver): observe a chosen box model - #1695
Conversation
A ResizeObserver only reports changes of the box it was asked to observe, and the shared observer always asked for the content box. Border and padding growth around an unchanged content box therefore raised no callback -- the gap that makes `borderBoxMeasurer` report stale sizes. An optional fourth argument selects the box; observers are now kept one per box model, since a single instance cannot serve two of them.
`borderBoxMeasurer` read border box sizes while the hook still observed content box changes, so a padding-only change left the returned measures stale. The third argument picks the observed box.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1695 +/- ##
==========================================
+ Coverage 83.19% 83.25% +0.05%
==========================================
Files 62 62
Lines 839 842 +3
Branches 151 151
==========================================
+ Hits 698 701 +3
Misses 16 16
Partials 125 125 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds explicit box-model selection to useResizeObserver (and threads it through useMeasure) to close a correctness gap where a measurer could read border-box sizes but the underlying observer only triggered on content-box changes.
Changes:
- Extend
useResizeObserver(target, callback, enabled, box?)to forward{ box }toResizeObserver.observeand maintain one singleton observer per box model. - Extend
useMeasure(enabled, measurer, box?)to pass the chosenboxthrough touseResizeObserver. - Update/add DOM tests to assert
{ box: ... }is forwarded and that separate observers are allocated per box model.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/useResizeObserver/index.ts | Adds box parameter support and keys observer singletons by box model. |
| src/useResizeObserver/index.dom.test.ts | Updates existing expectations and adds tests for box forwarding + per-box singleton behavior. |
| src/useMeasure/index.ts | Adds optional box param and passes it through to useResizeObserver. |
| src/useMeasure/index.dom.test.ts | Adds a test asserting useMeasure forwards the requested box to observation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
🎉 This PR is included in version 26.1.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Closes the correctness gap flagged when #1603 landed:
borderBoxMeasurerreads border box sizes, but the hook underneath only ever observed the content box.Problem
A
ResizeObservernotifies on changes to the box it was asked to observe. The shared singleton calledobserver.observe(target)— content box, the spec default. So:useMeasure(true, borderBoxMeasurer)keeps returning the previous sizeChange
useResizeObserver(target, callback, enabled, box?)anduseMeasure(enabled, measurer, box?)— both optional, both defaulting to'content-box', so existing calls behave exactly as before.Observers are now kept one per box model:
One instance cannot serve two box models, and elements may be observed by several observers, so this stays within the same "one observer, many subscribers" design — just keyed.
Usage for the border-box case the measurer was written for:
The pairing is documented on both hooks' JSDoc, including the failure mode when the two disagree.
Tests
useResizeObserverforwards{box}toobserveand allocates a separate observer per box modeluseMeasurethreads itsboxargument through — mutation-checked: dropping the argument fails withexpected "vi.fn()" to be called with arguments: [ <div></div>, { box: 'border-box' } ]{box: 'content-box'}callVerification
vp fmt,tsc --noEmit,vp lint,vp test --run(117 files / 532 tests), and the build all pass. Emitted signatures confirm the additions are optional: