react-spectrum icon indicating copy to clipboard operation
react-spectrum copied to clipboard

Popovers: issues transitioning child elements

Open OliverJAsh opened this issue 8 months ago โ€ข 2 comments

Provide a general summary of the issue here

Given the following (full reduced test case here) where we attempt to define an enter/exit transition for a popover child element:

import { DialogTrigger, Button, Popover, Dialog } from 'react-aria-components';

export default function App() {
  return (
    <DialogTrigger>
      <Button>Open popover</Button>
      <Popover placement="bottom right">
        <Dialog>
          <div className="content">This is a popover.</div>
        </Dialog>
      </Popover>
    </DialogTrigger>
  );
}

.react-aria-Popover .content {
  border: 1px solid;
  transition: opacity 1s;
}

.react-aria-Popover[data-entering] .content,
.react-aria-Popover[data-exiting] .content {
  opacity: 0;
}

๐Ÿค” Expected Behavior?

I would expect the enter/exit transition to work.

๐Ÿ˜ฏ Current Behavior

The enter/exit transition does not work.

๐Ÿ’ Possible Solution

I was able to get the enter transition to work with the following change, but I do not understand why:

.react-aria-Popover .content {
  border: 1px solid;
  transition: opacity 1s;

  @starting-style {
    opacity: 0;
  }
}

.react-aria-Popover[data-exiting] .content {
  opacity: 0;
}

As for the exit transition, it seems that React Aria only listens/waits for transitionend events on the popover root element, not its children. This is problematic because we need to transition children for certain effects: https://github.com/adobe/react-spectrum/issues/5195

๐Ÿ”ฆ Context

No response

๐Ÿ–ฅ๏ธ Steps to Reproduce

https://stackblitz.com/edit/vitejs-vite-vrzdb1dm?file=src%2Fmain.css,src%2FApp.tsx&terminal=dev

Version

1.8.0

What browsers are you seeing the problem on?

Chrome

If other, please specify.

No response

What operating system are you using?

macOS

๐Ÿงข Your Company/Team

Unsplash

๐Ÿ•ท Tracking Issue

No response

OliverJAsh avatar May 01 '25 07:05 OliverJAsh

I'm not sure how we'd detect this automatically. We just look to see if the popover element has a transition applied using element.getAnimations(), but this would require traversing the DOM to find all child elements as well. Can you apply a transition on something like visibility to the popover itself as well and match up the durations?

devongovett avatar May 06 '25 00:05 devongovett

Ah actually looks like there is an option for this: element.getAnimations({subtree: true}).

devongovett avatar May 29 '25 03:05 devongovett

Going to close this. There's not a good way to determine which animations on elements inside a popover are related to entry or exit animations and which one are independent. We could potentially add some API for that, e.g. a data attribute, a callback prop, etc. For now it's possible to work around this by adding an animation to the popover element itself as well. This can be something invisible such as visibility: hidden with a transition-delay matching the duration of the animations inside.

devongovett avatar Jun 28 '25 02:06 devongovett