#4120·primitives

Expose the resolved `side` of Popper-based content to JS

Author: kkroeger-tipluCreated Aug 17, 2026Updated Aug 17, 2026

Feature request

Overview

There is no public way to read the resolved side of Popper-based content in JS. data-side covers styling, but not logic that depends on the placement.

PopperContentProps.onPlaced fires exactly when the placement settles, but the wrappers omit it from their types (popover.tsx:399, tooltip.tsx:488, hover-card.tsx:234, menu.tsx:357), and Select names it SelectPopperPrivateProps (select.tsx:611) — so it is clearly meant to stay internal. At runtime it still arrives via the props spread (popover.tsx:502), which means re-declaring the prop locally works, but that relies on behaviour you never promised.

Two ways I could see this exposed:

  • a callback on the wrapper's content, e.g. onPlacedSideChange?: (side: Side) => void
  • the resolved placement through context, e.g. a usePopperSide() hook

The hook would suit my case better, since the value is usually consumed by a child of the content rather than by the content element itself.

Examples in other libraries

Floating UI, which Popper wraps, returns the resolved placement as a value from useFloating() — Popper destructures it itself in popper.tsx:228. Popper.js exposes the same through usePopper()'s state.placement. In both cases the placement is available to the consumer, not only as a DOM attribute.

Who does this impact? Who is this for?

Anyone whose content has to be arranged differently depending on the side it opened on. My case is a dropdown anchored to an input, where the search / "create entry" row should stay next to that input: below the options when the content opens upwards, above them otherwise.

CSS order is not sufficient there, because keyboard navigation follows the DOM order. Reordering only visually makes ArrowUp/ArrowDown and Tab move in the wrong direction, so the content has to be rendered in a different order — which needs the side as a value.

Additional context

If there is a supported way to do this that I have missed, I would be glad to be pointed at it.

@radix-ui/react-popover 1.1.23, @radix-ui/react-popper 1.3.7, React 19