fix: panel height not updating when conditionally rendering fields
The Leva panel height doesn't update when fields are conditionally rendered using the render option. The panel remains at its original size, causing overflow or clipped content.
// Panel height doesn't update when show2 toggles the folder visibility
const values = useControls({
show2: { value: false, label: 'Show folder' },
folder: folder(
{
number: 1,
string: { value: 'text', render: (get) => get('folder.number') >= 1 },
},
{ render: (get) => get('show2') }
),
})
Changes
- Added ResizeObserver to
useTogglehook to detect content size changes while the panel is expanded - Animate height transitions by setting explicit heights before/after content changes, then removing them post-transition
- Prevent race conditions by canceling pending animations and removing orphaned event listeners before starting new transitions
- Capture refs at effect creation to ensure proper cleanup when component unmounts
- Added Storybook story demonstrating the fix with multiple conditional sections and nested rendering
Implementation
The ResizeObserver compares rendered heights (not style properties) and triggers smooth animations only when differences exceed 1px. Uses requestAnimationFrame to ensure height changes are properly batched for transitions.
Storybook Story
Added a comprehensive story "Conditional Rendering - Panel Height Fix" that demonstrates:
- Multiple conditional sections with checkboxes to toggle visibility
- Nested conditional rendering within folders
- Smooth panel height animations when content changes
- Real-world use case with various input types
Location: Misc / Input options β Conditional Rendering - Panel Height Fix
Screenshots
Before: Panel doesn't resize when folder appears
After: Panel smoothly animates to fit new content
Story - Initial state with basic fields:
Story - Expanded with advanced settings:
Story - Fully expanded with all sections:
[!WARNING]
Original prompt
This section details on the original issue you should resolve
<filter_complete></filter_complete>
Comments on the Issue (you are @copilot in this section)
- Fixes pmndrs/leva#578
Original prompt
This section details on the original issue you should resolve
<issue_title>Panel height doesn't change when adding new fields via conditional rendering</issue_title> <issue_description>See pmndrs/leva#540 </issue_description>
Comments on the Issue (you are @copilot in this section)
- Fixes pmndrs/leva#578
π¬ We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.
Summary by CodeRabbit
-
New Features
- Panel height now smoothly animates and automatically adjusts to content size changes when toggled.
-
Documentation
- Added example story demonstrating conditional rendering with dynamic panel height handling.
β οΈ No Changeset found
Latest commit: 108592b7e4db3194ec3a184103f3117e56553df8
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
This PR includes no changesets
When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types
Click here to learn what changesets are, and how to add one.
Click here if you're a maintainer who wants to add a changeset to this PR
The latest updates on your projects. Learn more about Vercel for GitHub.
| Project | Deployment | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| leva | Preview | Comment | Nov 8, 2025 3:25pm |
This pull request is automatically built and testable in CodeSandbox.
To see build info of the built libraries, click here or the icon next to each commit SHA.
Latest deployment of this branch, based on commit 108592b7e4db3194ec3a184103f3117e56553df8:
| Sandbox | Source |
|---|---|
| leva-minimal | Configuration |
| leva-busy | Configuration |
| leva-scroll | Configuration |
| leva-advanced-panels | Configuration |
| leva-ui | Configuration |
| leva-theme | Configuration |
| leva-transient | Configuration |
| leva-plugin-plot | Configuration |
| leva-plugin-bezier | Configuration |
| leva-plugin-spring | Configuration |
| leva-plugin-dates | Configuration |
| leva-custom-plugin | Configuration |
@copilot write a story for this change
@copilot write a story for this change
Added a comprehensive Storybook story "Conditional Rendering - Panel Height Fix" in commit bda7da4.
The story demonstrates:
- Multiple conditional sections with checkboxes to toggle visibility
- Nested conditional rendering within folders
- Smooth panel height animations when content changes
- Real-world use case with various input types (text, numbers, sliders, selects, booleans)
You can find it at: Misc / Input options β Conditional Rendering - Panel Height Fix
Screenshots showing the panel expanding as sections are toggled:
Initial state:
With Advanced Settings:
Fully expanded:
[!WARNING]
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
storybook.js.org
- Triggering command:
node /home/REDACTED/work/leva/leva/node_modules/.bin/../storybook/dist/bin/dispatcher.js dev -p 6006(dns block)If you need me to access, download, or install something from one of these locations, you can either:
- Configure Actions setup steps to set up my environment, which run before the firewall is enabled
- Add the appropriate URLs or hosts to the custom allowlist in this repository's Copilot coding agent settings (admins only)
@coderabbitai review
β Actions performed
Review triggered.
Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
[!NOTE]
Other AI code review bot(s) detected
CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.
Walkthrough
The useToggle hook is enhanced with a ResizeObserver to detect content size changes and smoothly animate panel height adjustments when controls are conditionally rendered. A Storybook story is added to demonstrate this panel height auto-adjustment behavior.
Changes
| Cohort / File(s) | Change Summary |
|---|---|
Panel Height Animation Enhancement packages/leva/src/hooks/useToggle.ts |
Adds ResizeObserver effect to detect content size changes; computes and animates height transitions with requestAnimationFrame; includes cleanup for observers, animation frames, and transition handlers; skips animations when height difference is below 1px threshold |
Conditional Rendering Story packages/leva/stories/input-options.stories.tsx |
Adds new Storybook story component ConditionalRenderingPanelHeight with nested conditional groups (showBasicFields, showAdvanced, showDebug) to demonstrate panel height auto-adjustment behavior |
Sequence Diagram
sequenceDiagram
participant User
participant Panel
participant ResizeObserver as ResizeObserver
participant AnimationFrame as requestAnimationFrame
participant DOM
User->>Panel: Toggle conditional field visibility
Panel->>ResizeObserver: Detect content size change
ResizeObserver->>Panel: Content dimensions changed
Panel->>AnimationFrame: Queue height animation
AnimationFrame->>DOM: Set wrapper to current height
AnimationFrame->>DOM: Animate to target height
DOM->>DOM: Transition height (CSS)
DOM->>Panel: transitionend event
Panel->>DOM: Remove explicit height property
Estimated code review effort
π― 3 (Moderate) | β±οΈ ~20-25 minutes
- useToggle hook modifications: Logic density is moderate with ResizeObserver setup, animation frame sequencing, and transition event handling. Requires careful review for proper cleanup, memory leak prevention, and edge cases around rapid toggling or nested conditional renders.
- Story component: Straightforward demonstration with minimal logic.
- Key areas for attention:
- ResizeObserver cleanup on effect unmount or dependency changes
- Proper handling of concurrent animations (cancellation of pending frames)
- Height calculation accuracy and negligible difference threshold (1px)
- Transition handler cleanup to avoid memory leaks
Poem
A panel that dances with graceful ease, As fields appear and disappear with ease, The ResizeObserver watches content grow, Then animates the height with a gentle flow, No jarring jumpsβjust smooth transitions so. π°β¨
Pre-merge checks and finishing touches
β Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Linked Issues check | β οΈ Warning | The PR addresses issue #578 (panel height with conditional rendering) but does not implement the coding requirements from issue #39 (store sanitization logic). | Implement the store sanitization responsibility outlined in issue #39 to centralize value validation/sanitization as specified in the linked requirements. |
β Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | β Passed | Check skipped - CodeRabbitβs high-level summary is enabled. |
| Title check | β Passed | The title clearly and specifically describes the main fix: panel height not updating during conditional field rendering, which aligns with the primary change in the PR. |
| Out of Scope Changes check | β Passed | The ResizeObserver implementation and Storybook story are directly aligned with fixing issue #578; no out-of-scope changes detected. |
| Docstring Coverage | β Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
β¨ Finishing touches
- [ ] π Generate docstrings
π§ͺ Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
- [ ] Commit unit tests in branch
copilot/fix-panel-height-issue
π Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π₯ Commits
Reviewing files that changed from the base of the PR and between f70a62f38d4e97f3acaed3495fc27fcab926b852 and 108592b7e4db3194ec3a184103f3117e56553df8.
π Files selected for processing (2)
packages/leva/src/hooks/useToggle.ts(1 hunks)packages/leva/stories/input-options.stories.tsx(1 hunks)
π§° Additional context used
πͺ GitHub Actions: CI
packages/leva/src/hooks/useToggle.ts
[error] 1-1: Prettier formatting check failed. Run 'prettier --write' to fix code style issues in this file.
packages/leva/stories/input-options.stories.tsx
[error] 1-1: Prettier formatting check failed. Run 'prettier --write' to fix code style issues in this file.
π Additional comments (2)
packages/leva/src/hooks/useToggle.ts (1)
129-189: Verify race condition between toggle and resize animations.As previously noted by Copilot, when toggling from closed to open, both the toggle animation effect (lines 96-127) and this ResizeObserver effect will run simultaneously. During expansion, the ResizeObserver may fire and manipulate height while the toggle animation is in progress, causing conflicting height changes.
The concern remains valid: both effects can set explicit heights on the same wrapper element concurrently, and without coordination they may override each other's transitions.
Consider adding an animation state flag as previously suggested:
const isAnimating = useRef(false) // In toggle effect (line 96), set isAnimating.current = true // Clear it in the transitionend handler (line 106) // In ResizeObserver callback (line 137), check: if (isAnimating.current) returnOr alternatively, add a delay before observing that matches the transition duration:
const timeoutId = window.setTimeout(() => { resizeObserver.observe(contentRef.current!) }, 300) // Match transition duration return () => { clearTimeout(timeoutId) resizeObserver.disconnect() // ... rest of cleanup }Based on learnings
packages/leva/stories/input-options.stories.tsx (1)
65-108: LGTM! Excellent demonstration of the panel height fix.The story effectively demonstrates conditional rendering with multiple nested sections and provides clear documentation for users. The combination of basic fields, folders with nested conditions, and the JSON preview creates a comprehensive test case for the ResizeObserver-based height adjustment.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.