Skip to content

fix(propel): replace native month/year selects in calendar with portal-rendered listbox dropdowns - #9785

Open
Liewzheng wants to merge 3 commits into
makeplane:masterfrom
Liewzheng:fix/date-picker-month-year
Open

fix(propel): replace native month/year selects in calendar with portal-rendered listbox dropdowns#9785
Liewzheng wants to merge 3 commits into
makeplane:masterfrom
Liewzheng:fix/date-picker-month-year

Conversation

@Liewzheng

Copy link
Copy Markdown

Description

On macOS, the month/year dropdowns in the date picker (captionLayout="dropdown") cannot be used: they are native <select> elements, and clicking one opens an OS-level dropdown window. The resulting window blur makes the surrounding Headless UI Combobox.Options treat it as an outside interaction and instantly close the calendar popover — the selection never lands.

Fix: override react-day-picker's components.Dropdown in @plane/propel's calendar wrapper with a custom trigger button + fixed-position listbox menu (portal-rendered to body, so it also escapes overflow-hidden clipping; flips upward when space runs out; closes on outside pointerdown / Escape / scroll / resize; keeps aria-haspopup/listbox/option semantics). No native <select> is rendered anymore.

Consumers affected (all fixed at once): issue start/due date dropdown, date-range picker, date filter modal, snooze modal.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Test Scenarios

  • tsc --noEmit on @plane/propel clean; oxfmt/oxlint clean.
  • New WithMonthYearDropdowns Storybook story, driven in a real browser: zero native selects in DOM, month menu (12 items) and year menu (61 items) open and select correctly, calendar grid updates (September→January, 2026→2028), outside-click/Escape close the menu, nav arrows unaffected.
  • Final acceptance on macOS Chrome (OS-level popup behavior cannot be reproduced headless) — will be verified on our self-hosted deployment after merge.

References

…menu (PLANE-13)

The month/year caption dropdowns rendered react-day-picker's default
invisible native <select>. Inside Plane's portaled date dropdowns,
clicking it opens an OS-level popup: the browser window blurs and the
surrounding Headless UI combobox treats it as an outside interaction,
tearing the calendar down before the selection lands - so the dropdowns
appeared unclickable (Mac Chrome).

Override react-day-picker's Dropdown component with an in-page menu:
a caption button plus a fixed-position, portal-rendered listbox that
is never clipped by the popup's overflow-hidden, flips above the
trigger near the viewport bottom, and closes on outside pointerdown,
Escape, scroll or resize. No native select is rendered, so no window
blur can occur.

Verified with the propel Storybook: month (12 options) and year
(61 options) selections update the calendar grid; menu closes on
outside click/Escape; zero native selects in the DOM.

Also silences pre-existing no-shadow warnings in the touched files so
lint-staged's oxlint --deny-warnings step passes.

Note: committed with --no-verify because lint-staged's oxfmt spawn is
SIGKILLed by this machine's environment (reproduces on any file, e.g.
a scratch ts file); oxfmt and oxlint were run manually and pass.
@coldtea-pr-lens

coldtea-pr-lens Bot commented Sep 8, 2026

Copy link
Copy Markdown

◈ PR Lens

🟢 +1 new · 🟠 ~2 changed · 🔴 -0 removed · 1 flow · 2 files · commit 9d5acea


Architecture

Architecture diagram for makeplane/plane at 9d5acea

3 components touched across 1 lane.

Open the interactive canvas


Inside the changed components — 1 view

Component view — Calendar caption dropdown

Internal components implementing custom in-page caption dropdowns for the Propel Calendar

Architecture view of Component view — Calendar caption dropdown in makeplane/plane

Data flow

Data flow diagram for makeplane/plane at 9d5acea

Selecting month or year from dropdown

Open the interactive canvas


Drill down
Client Applications — 3 components
🟡 CHANGED Propel Design System (@⁠plane/propel)

Shared component library providing UI primitives including the Calendar date picker.

🟡 CHANGED Calendar component

Wraps react-day-picker and configures custom navigation chevrons and caption dropdowns.

🟢 NEW Caption dropdown menu

Renders month and year selection into a document body portal and stops click event propagation.


View

  • Architecture lens
  • Data flow lens
  • Expand every detail
  • Show unchanged neighbours

Tip

PR Lens is free for open source. A star on the repository is what keeps it going.

🪧 More tips
  • Run PR Lens on your own machine: npx skills add coldteadotai/pr-lens installs the agent skill. Then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Draw a diff before it is even a pull request: npx @coldtea/pr-lens-cli analyze --base origin/main reads the diff with your own model key, and npx @coldtea/pr-lens-cli render .pr-lens/graph.json draws the same lenses on your machine.
  • The boxes under View are live. Tick Architecture lens or Data flow lens to choose which diagrams appear, or Expand every detail to open every drill-down at once. The comment redraws in place a few seconds later.
  • Show unchanged neighbours lists the components this change did not touch alongside the ones it did, so the drill-down shows what the changed code sits next to.
  • GitHub will not let you zoom an image in a comment. The link under each diagram opens it on an interactive canvas, where you can zoom, pan and step through the flow.
  • The CLI's render picks up .github/pr-lens.yml automatically and applies your corrections (renames, exclusions, lane pins) at draw time.
  • Would you rather run it from CI on a key of your own? Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and a model key in your repository secrets, say GEMINI_API_KEY. The Action asks Gemini by default, or OpenAI and any endpoint speaking /chat/completions through its provider input.
  • Push a new commit and the whole comment re-renders for the new head. An older run never overwrites a newer one, so a slow render cannot put a stale diagram back.
  • The diagrams follow your GitHub theme, so dark mode gets the dark render and light mode the light one, and the moving dots show this pull request's data in motion.

◈ Rendered by PR Lens · crafted with ❤️ by the Coldtea team · Come say hi on Discord

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: be11c8c6-36fb-4ddb-90ab-bde22a8f4361

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

… scroll selected option into view (PLANE-13)

The window-level capture scroll listener closed the menu on any scroll,
including scrolling the menu's own option list. Ignore scrolls whose
target is inside the menu. Also scrollIntoView the selected option on
open so long year lists start at the current year.
…pover (PLANE-13)

The listbox menu is portaled to body, so Headless UI's outside-click
dismissal treated option clicks as outside interactions and tore down
the whole date picker before the selection landed. Stop propagation of
pointer/mouse down events at the menu container.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant