Skip to content

Conversation

@gggritso
Copy link
Member

@gggritso gggritso commented Dec 9, 2025

Right now, SlideOverPanel can be opened/closed by passing <SlideOverPanel open={isPanelOpen} or by conditionally rendering it with isPanelOpen && <SlideOverPanel. This is problematic because when there are two ways to open/close something, it means there are multiple ways we need to account for when thinking about animations and deferring rendering the contents.

This PR removes the open prop. SlideOverPanel now must be rendered conditionally with && in JSX. This required an update to how the contents are deferred on mount, but otherwise behaviour is preserved.

I was pushed towards the isOpen && API due to a practical problem in Dashboards, but I also think it's a reasonable choice overall.

Rationale

Consider:

<Container>
  <SlideOverPanel ...
  <PreviewWidget /...
</Container>

Imagine that the container has a panel, and a preview which both take up half the screen and slide in from opposite sides. The container takes up the full screen, and is shown over some background content. It's offset against the main sidebar.

  • the container must exist to account for the sidebar, and to correctly split space between the panel and preview
  • the container must take up the whole screen, which means it prevents clicks on content underneath
  • I need to hide/show the container, panel, preview when users click on buttons in the UI
  • the panel and preview both have a slight animation to make it less jarring when they open-close
+-------------------------+
| +---------++---------+  |
| |         ||         |  |
| |         ||         |  |
| | Panel   || Preview |  |
| |         ||         |  |
| |         ||         |  |
| |         ||         |  |
| +---------++---------+  |
|                         |
|  Container              |
|                         |
+-------------------------+

There are two major problems.

  1. How should I go about hiding/showing the container? The container blocks the content underneath. When the panel and the preview close, how do I hide the container? I could either make it "invisible" by turning off opacity and pointer events, or use display: none. The former is messy, and error prone. It's easy to accidentally leave this in, and cause issues with clicks. The latter is difficult, how do I coordinate setting display: none vs. the panel and preview when they slide? This is the case in the Widget Builder.
  2. What if I need to remount the Container for some reason? e.g., the container might have some kind of context, or something else that needs to be remounted or re-rendered that might cause a re-mount of the panel. In that case, deferring the content of the panel won't work, since it's relying on the open prop state changing, but on initial mount there is no change. This is also the case in the Widget Builder. It's not possible to have a deferral mechanism that works both on mount and on prop change!

If the API is isOpen && these problems are solved. I can just mount/unmount the entire tree, and everything works as expected. Since there is only one way to show/hide the panel, I can use one deferral method, and I don't need explanations in the doc for how to handle animations and deferral.

In short, controlling mounting/unmounting is a lot easier than controlling an open prop because I don't have to worry about keeping surrounding components in the DOM just to make animations and deferred rendering work.

Instead, we expect the panel to be rendered conditionally.
@gggritso gggritso requested review from a team as code owners December 9, 2025 21:34
@linear
Copy link

linear bot commented Dec 9, 2025

@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Dec 9, 2025
@gggritso gggritso changed the title fix: Force conditional rendering of SlideOverPanel fix: Remove open prop of SlideOverPanel Dec 9, 2025
@codecov
Copy link

codecov bot commented Dec 9, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff            @@
##           master   #104627   +/-   ##
========================================
  Coverage   80.52%    80.52%           
========================================
  Files        9330      9330           
  Lines      400755    400740   -15     
  Branches    25695     25689    -6     
========================================
- Hits       322721    322713    -8     
+ Misses      77568     77563    -5     
+ Partials      466       464    -2     

</Container>
</SlideOverPanel>
{isPanelOpen && (
<SlideOverPanel position="right">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gggritso how would you feel about about making SlideOverPanel extend the Container component? Does that make sense and would it be helpful? The reason I ask is because having a child container with border=primary feels like it's specifying border on the wrong component

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds like a good idea! If we do that,

  1. I could throw out the panelWidth prop and let people pass in a width more naturally, if needed
  2. I could set some good default styles, like a left border (missing in some UIs) and maybe a little box shadow on the left for depth
  3. Get rid of some wrapper elements, like you pointed out

Copy link
Collaborator

@TkDodo TkDodo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great work 🙌

@gggritso gggritso merged commit 4fd4f6d into master Dec 10, 2025
48 checks passed
@gggritso gggritso deleted the georgegritsouk/dain-1123-remove-open-prop-from-slideoverpanel branch December 10, 2025 18:18
gggritso added a commit that referenced this pull request Dec 11, 2025
As of #104627, the contents of
the Widget Builder are "deferred", which means that the panel opens up
early, and the contents render while it's animating. Unfortunately by
default, the panel is blank while loading.

This PR adds a loading skeleton with placeholders. I also had to change
how we set up the intersection observers. In short, we can't use normal
refs anymore because the containers for the chart mount _late_. Instead,
I'm using callback refs, which fire once the elements are mounted.

**e.g.,**


https://github.com/user-attachments/assets/0549f98a-19c1-482c-b6c0-743e05b1628f

This PR is best enjoyed with whitespace off!
@github-actions github-actions bot locked and limited conversation to collaborators Dec 26, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants