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

Add origin-aware animations CSS variable to the popover components based on the `placement` prop

Open sadeghbarati opened this issue 9 months ago โ€ข 5 comments

Provide a general summary of the feature here

Just like the radix-ui, it would be nice to have --radix-popper-transform-origin CSS variable for these component

  • Popover
    • Combobox
    • Menu
    • Select
    • DatePicker/DateRangePicker
  • Tooltip

๐Ÿค” Expected Behavior?

Please check this shadcn PR video

https://github.com/shadcn-ui/ui/pull/6945

๐Ÿ˜ฏ Current Behavior

Components are doesn't have origin aware animations

๐Ÿ’ Possible Solution

No response

๐Ÿ”ฆ Context

For context please check the radix-ui popper component

https://github.com/radix-ui/primitives/blob/main/packages/react/popper/src/popper.tsx#L241C11-L244C23

๐Ÿ’ป Examples

No response

๐Ÿงข Your Company/Team

No response

๐Ÿ•ท Tracking Issue

No response

sadeghbarati avatar Apr 19 '25 06:04 sadeghbarati

function getPopoverAnimationClassName(values: PopoverRenderProps): string {
  return clsx(
    "fill-mode-forwards",
    values.placement &&
      {
        bottom: "origin-top",
        top: "origin-bottom",
        left: "origin-right",
        right: "origin-left",
        center: "origin-center",
      }[values.placement],
    values.isEntering && "animate-in fade-in",
    values.isExiting && "animate-out fade-out zoom-out-95",
  );
}

Found this in argos-ci which is using statis TailwindCSS origin classes based on the placement props which is good but,

I need transform-origin value be more accurate

sadeghbarati avatar Apr 19 '25 08:04 sadeghbarati

This should already be possible with the data-placement attribute, or placement render prop. https://react-spectrum.adobe.com/react-aria/Popover.html#popover-2

.react-aria-Popover {
  &[data-placement=top] {
    transform-origin: bottom;
  }
}

devongovett avatar Apr 19 '25 15:04 devongovett

appreciate for the response ๐ŸŒป

sadeghbarati avatar Apr 20 '25 04:04 sadeghbarati

Unfortunately data-placement doesn't provide the full placement (e.g. bottom right), only the placement axis (e.g. bottom): https://github.com/adobe/react-spectrum/issues/6825

@devongovett Would be great to get your thoughts on that issue.

OliverJAsh avatar Apr 27 '25 18:04 OliverJAsh

In my work at Unsplash, I'm trying to implement a popover enter/exit animation that makes the popover appear to "pop in" and slide-in from the anchor point where it's attached to the trigger. See this reduced test case for example. It works in my reduced test case, but it's not origin-aware, meaning it won't work with different placements. To solve this I think React Aria might need something like a data-crossplacement attribute to go along with data-placement (https://github.com/adobe/react-spectrum/pull/8163).

For comparison, here's what Radix is doing. It exposes a CSS variable.

I also encountered other issues whilst attempting to implement this animation. It seems to require an extra child element for the scale transform, and I couldn't get [data-entering] to work on the child, rather I had to use @starting-style instead. See this reduced test case for example. I would appreciate any input on this.

I've already shipped this to production at Unsplash using a patch for https://github.com/adobe/react-spectrum/pull/8163. One thing I noticed is that data-crossplacement unfortunately falls short when the cross placement is adjusted to prevent collisions. For example, here we specify placement={"top end"}. Due to collision prevention the popover appears in the top start position, however data-crossplacement is still right, meaning the animation appears to have the wrong origin.

https://github.com/user-attachments/assets/f1f9090a-54ad-4e45-b451-1845fb752a63

OliverJAsh avatar May 01 '25 06:05 OliverJAsh