Skip to content

🐛 Bug: headlessui dropdowns render at top-left corner and options are unclickable (React 19 + headlessui v2) #9750

Description

@Liewzheng

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

On the current preview branch (React 19 + @headlessui/react 2.2.10), headlessui-based dropdowns (state, priority, member, module, cycle, date, etc.) are broken in two ways:

  1. Wrong position: dropdown content renders at the top-left corner of the page (left: 0; top: 0) instead of next to its trigger button.
  2. Options not clickable: for combobox-style dropdowns that render Combobox.Input inside the portaled Combobox.Options, clicking an option does nothing — the options wrapper is marked inert + aria-hidden.

Expected: dropdowns open anchored to their trigger and options are clickable.

Steps to reproduce

  1. Run the current preview branch (React 19.2.x, @headlessui/react 2.2.10).
  2. Open any work item detail page.
  3. Click the state / priority / assignee dropdown trigger.
  4. Observe the dropdown content appearing at the top-left corner of the page; in combobox dropdowns (e.g. member select with search input), options cannot be clicked.

Root cause analysis

Two separate upstream headlessui v2 behaviors combine here:

  1. Frozen clobbers child refs. Combobox.Options (and other overlays) wrap children in the internal Frozen component, which does cloneElement(child, { ref }). Since no ref is forwarded to Frozen, that config ref is null and it overrides the child's own ref, so ref={setPopperElement} on popper content never fires. With popperElement stuck at null, react-popper never creates an instance and the dropdown keeps its initial left:0/top:0 position. (Became visible after the React 19 upgrade in chore: upgrade React to 19 and React Router to 8 #9530, which bumped headlessui v1 → v2.2.10.)

  2. useInertOthers over-marks inert subtrees. Combobox.Options is modal by default and marks every element that does not contain an allowed element as inert. Because these dropdowns render Combobox.Input inside the portaled options and wrap options in a scrollable div, that wrapper receives inert + aria-hidden, making all options unclickable. Upstream: Inert is over extending into elements inside the combo box tailwindlabs/headlessui#3421 (open since Aug 2024).

Related: #9694 fixed the headlessui v2 Fragment-check crash from the same React 19 upgrade; this issue covers the remaining positioning/interactivity regressions.

I have a fix ready as a pnpm patch for @headlessui/react@2.2.10 and will open a PR referencing this issue.

Environment

Production / self-hosted and local dev on preview branch

Browser

Google Chrome

Version

preview branch (post React 19 upgrade, @headlessui/react 2.2.10)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions