makeplane / makeplane/plane

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

Open
#9,750 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
59.6k
Forks
5.8k
Avg merge
1d 22h
Merged PRs (30d)
49

Description

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 #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: https://github.com/tailwindlabs/headlessui/issues/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)

Screenshots

Dropdown content rendered at the top-left corner of the page instead of next to its trigger:

dropdown rendered at top-left corner

Date picker options not clickable (options wrapper marked inert + aria-hidden):

datepicker options unclickable

All headlessui-based dropdowns in the work item properties panel are affected:

properties panel dropdowns

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start on the preview branch by reproducing the issue on a work item detail page with the state, priority, assignee, and date dropdowns. Inspect the @headlessui/react 2.2.10 behavior described in the report and the proposed pnpm patch. Done means dropdowns are anchored beside their triggers and combobox options are clickable without inert or aria-hidden blocking them.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.