Recalculate body padding after SPA navigation#987
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses a visual/layout bug where the debugbar caches document.body padding on initialization and later reapplies stale values after SPA-style navigations (e.g., Livewire/Turbo/HTMX), causing incorrect padding restoration when navigating between pages with different layouts.
Changes:
- Adds SPA navigation event listeners (
livewire:navigated,turbo:load,htmx:afterSettle) to trigger a recalculation step. - Introduces
recalculateBodyPadding()to refresh cached body padding values and re-runrecomputeBottomOffset().
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| recalculateBodyPadding() { | ||
| // Clear inline styles to read the page's actual CSS values | ||
| document.body.style.paddingTop = ''; | ||
| document.body.style.paddingBottom = ''; | ||
|
|
There was a problem hiding this comment.
recalculateBodyPadding() clears document.body.style.paddingTop/paddingBottom unconditionally. If options.bodyBottomInset is false, recomputeBottomOffset() is a no-op, so this listener would permanently wipe any existing inline body padding after SPA navigation. Even when bodyBottomInset is true, clearing these properties can remove application-defined inline padding (e.g. <body style="padding-top: …">) before you measure it, causing the cached values to be wrong. Consider early-returning when !this.options.bodyBottomInset, and/or preserving/restoring the previous inline padding values (or deriving the “original” padding by subtracting the debugbar offset from the current computed padding) instead of blanking the inline styles.
resources/debugbar.js
Outdated
| this.bodyPaddingTopHeight = Number.parseInt(bodyStyles.paddingTop); | ||
| this.bodyPaddingBottomHeight = Number.parseInt(bodyStyles.paddingBottom); |
There was a problem hiding this comment.
Number.parseInt(bodyStyles.paddingTop/paddingBottom) will truncate fractional pixel values from getComputedStyle() (e.g. 12.5px -> 12), which can introduce small layout drift when recomputing offsets. Using Number.parseFloat(...) (and updating the initial cached reads in initialize() for consistency) avoids precision loss.
| this.bodyPaddingTopHeight = Number.parseInt(bodyStyles.paddingTop); | |
| this.bodyPaddingBottomHeight = Number.parseInt(bodyStyles.paddingBottom); | |
| this.bodyPaddingTopHeight = Number.parseFloat(bodyStyles.paddingTop); | |
| this.bodyPaddingBottomHeight = Number.parseFloat(bodyStyles.paddingBottom); |
|
I think this makes sense, but should we make this configurable? Maybe set a list of eventNames somewhere? Otherwise every framework needs to add their own event. |
When using SPA navigation frameworks (Livewire, Turbo, HTMX), the body's padding may change between pages. The debugbar captures body padding at initialization time and uses these cached values in recomputeBottomOffset(). This causes issues when navigating between pages with different layouts - for example, from a page with a sticky header (large padding-top) to a page without one (no padding). The debugbar would incorrectly restore the old padding value after navigation. This fix adds listeners for configurable SPA navigation events and recalculates the cached body padding values after navigation completes. Default events: livewire:navigated, turbo:load, htmx:afterSettle Changes: - Add spaNavigationEvents option (array of event names, configurable) - Skip recalculation when bodyBottomInset is disabled - Use parseFloat instead of parseInt to avoid precision loss
f47f94c to
bf41e44
Compare
Good idea @barryvdh, I have made them configurable via PHP and move the defaults there. |
|
Looks good :) |
Sure, all done! Big fan of your work BTW, the debugbar has saved so much time and it was actually one of the reasons I wanted to try Laravel back in the day. |
|
Thanks! |
Problem
When using SPA navigation frameworks (Livewire, Turbo, HTMX), the body's padding may change between pages. The debugbar captures body padding at initialization time (lines 702-704) and uses these cached values in
recomputeBottomOffset().This causes a visual bug when navigating between pages with different layouts. For example, navigating from a page with a sticky header (large
padding-toplike177px) to a page without one (no padding), the debugbar incorrectly restores the old padding value after navigation completes.Steps to reproduce (using Livewire 4)
bodyBottomInset: trueandtoolbarPosition: 'top'padding-top: 177px)wire:navigateto navigate to the page without the sticky headerpadding-top: 177pxeven though the new page has no paddingTimeline of the bug
Solution
This PR adds listeners for common SPA navigation events and recalculates the cached body padding values after navigation completes:
livewire:navigated(Livewire 4)turbo:load(Turbo/Hotwire)htmx:afterSettle(HTMX)The new
recalculateBodyPadding()method:recomputeBottomOffset()with the correct valuesTesting
Tested with Livewire 4 wire:navigate between pages with different body padding values. The debugbar now correctly respects each page's actual padding.