Skip to content

feat: PopoverPanel + Dropdown deprecation#566

Open
adrienzheng-cb wants to merge 6 commits intomasterfrom
adrien/deprecate-dropdown
Open

feat: PopoverPanel + Dropdown deprecation#566
adrienzheng-cb wants to merge 6 commits intomasterfrom
adrien/deprecate-dropdown

Conversation

@adrienzheng-cb
Copy link
Copy Markdown
Contributor

@adrienzheng-cb adrienzheng-cb commented Mar 30, 2026

What changed? Why?

Popover (internal)

  • Replace Popper.js positioning with @floating-ui/react-dom: useFloating, autoUpdate,
    offset (skid/gap), flip + shift + limitShift for fixed placements, and autoPlacement
    for placement values that start with "auto".
  • Wrap the component in forwardRef and merge the consumer ref with the Floating UI
    reference ref (useMergeRefs).
  • Add optional style and className on the subject (trigger) root.

PopoverPanel / PopoverPanelContent

  • Add PopoverPanel: trigger + floating or phone modal layout, content as node or
    (closePopover) => node, optional enableMobileModal, sizing (panelWidth, min/max
    width/height), showOverlay, contentPosition, ref with openPopover/closePopover.
  • Add PopoverPanelContent: animated VStack surface for the panel body.
  • Wire useComponentConfig for PopoverPanel and PopoverPanelContent; register both in
    core/componentConfig.ts.
  • Export from packages/web overlays barrel and new package entry @coinbase/cds-web/popover
    (package.json exports).
  • Add Storybook stories, unit tests, and Docusaurus (docgen, examples, props table,
    styles explorer, sidebar, webMetadata).

useResponsivePanelMaxHeight (renamed from useResponsiveHeight in popover)

  • New module overlays/popover/useResponsivePanelMaxHeight.ts (canonical hook for
    PopoverPanel).
  • Rename the hook to useResponsivePanelMaxHeight; return value is panelMaxHeight
    (was dropdownHeight in the shared logic).
  • Rename the measured bounds argument to panelBounds (was dropdownBounds) for panel
    sizing; keep the same viewport / calc(100vh - …) responsive behavior.
  • Support ResponsiveProp with resolveResponsiveMaxHeight aligned to
    phone/tablet/desktop breakpoints via useBreakpoints.
  • Legacy packages/web/src/dropdown/useResponsiveHeight.ts remains for Dropdown only,
    with the original non-responsive maxHeight API; deprecate in favor of importing
    useResponsivePanelMaxHeight from @coinbase/cds-web/popover (removal v10) and add a
    short comment that new behavior lives under overlays/popover.

Dropdown deprecation

  • Deprecate Dropdown, DropdownContent, DropdownProps-related types, and docs
    Dropdown webMetadata warning: use PopoverPanel / PopoverPanelContent instead
    (expected removal v10).

Other

  • ModalWrapper: when hideOverlay is true, render a transparent fixed VStack that still
    receives overlay press so dismiss works without a visible Overlay.
  • Jest: extend @floating-ui/react-dom mock with limitShift.

Breaking / migration notes for consumers

  • Popover: possible subtle positioning and DOM structure differences vs Popper; new
    ref and subject style/className are additive.
  • Dropdown: deprecated; migrate to PopoverPanel.
  • Popover-adjacent hook: prefer useResponsivePanelMaxHeight from @coinbase/cds-web/popover;
    dropdown/useResponsiveHeight is legacy and deprecated.

UI changes

storybook
docs

Screen.Recording.2026-04-02.at.1.15.52.AM.mov

Testing

How has it been tested?

  • Unit tests
  • Interaction tests
  • Pseudo State tests
  • Manual - Web
  • Manual - Android (Emulator / Device)
  • Manual - iOS (Emulator / Device)

Testing instructions

Illustrations/Icons Checklist

Required if this PR changes files under packages/illustrations/** or packages/icons/**

  • verified visreg changes with Terran (include link to visreg run/approval)
  • all illustration/icons names have been reviewed by Dom and/or Terran

Change management

type=routine
risk=low
impact=sev5

automerge=false

Copy link
Copy Markdown
Contributor

@cb-ekuersch cb-ekuersch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we can recommend switching to Popover we should at least:

  1. audit Popover to make sure it can handle any/all use cases that Dropdown can. Any storybook stories from Dropdown should be able to be effortlessly migrated to Popover stories
  2. add docsite pages for Popover

@adrienzheng-cb adrienzheng-cb force-pushed the adrien/deprecate-dropdown branch from ca7a9d9 to 1bcca8d Compare April 2, 2026 04:49
@adrienzheng-cb adrienzheng-cb marked this pull request as draft April 2, 2026 04:50
@adrienzheng-cb adrienzheng-cb force-pushed the adrien/deprecate-dropdown branch from 102cbda to 4f73334 Compare April 2, 2026 15:11
@adrienzheng-cb adrienzheng-cb changed the base branch from cds-v9 to master April 2, 2026 15:11
@cb-heimdall
Copy link
Copy Markdown
Collaborator

cb-heimdall commented Apr 2, 2026

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 1
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1
CODEOWNERS 🟡 See below

🟡 CODEOWNERS

Code Owner Status Calculation
ui-systems-eng-team 🟡 0/1
Denominator calculation
Additional CODEOWNERS Requirement
Show calculation
Sum 0
0
From CODEOWNERS 1
Sum 1

@adrienzheng-cb adrienzheng-cb changed the title chore: deprecate Dropdown feat: PopoverPanel + Dropdown deprecation Apr 2, 2026
@adrienzheng-cb adrienzheng-cb force-pushed the adrien/deprecate-dropdown branch from 5246936 to 5aa2102 Compare April 2, 2026 18:59
- Add PopoverPanel, PopoverPanelContent, tests, stories, and @coinbase/cds-web/popover export
- Document PopoverPanel (docgen, sidebar, component docs)
- Deprecate Dropdown, DropdownProps-related types, and DropdownContent for removal in v10
- Popover: forwardRef with mergeRefs for Floating UI reference; flatten to one root div; add style/className to PopoverProps
- Re-export PopoverPanel from overlays index; add Dropdown docs warning
fix ModalWrapper not closing when clicked outside without overlay
add support for componentConfig
import React, { memo, useCallback, useMemo } from 'react';
import React, { forwardRef, memo, useCallback, useMemo } from 'react';
import { zIndex } from '@coinbase/cds-common/tokens/zIndex';
import { useMergeRefs } from '@coinbase/cds-common/hooks/useMergeRefs';
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will replace with mergeRefs after merging into v9

type Placement as FloatingPlacement,
shift,
useFloating,
} from '@floating-ui/react-dom';
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

originally replacing with popper with floating UI in popover was done in v9 feature branch, but moved it here since we needed to have PopoverPanel before v9 and Popover is affected

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-breaking since all props are the same

/** Can optionally pass a maxHeight.
* @default 300
*/
maxPanelHeight?: React.CSSProperties['maxHeight'];
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxPanelWidth/Height instead of maxHeight to make it clear to which element dimension is set

onClick={!disableOverlayPress ? onOverlayPress : undefined}
testID="modal-overlay"
/>
) : (
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding this here so Modal without overlay can still be closed when clicking outside

/**
* @deprecated Import `useResponsiveHeight` from `@coinbase/cds-web/popover` instead. This will be removed in a future major release.
* @deprecationExpectedRemoval v10
*/
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a replacement under popover directory. the replacement handle can handle maxHeight with responsive value

onBlur?: (event?: React.FocusEvent) => void;
/** Callback fired when a mouse down event is fired on the subject */
onMouseDown?: (event: React.MouseEvent) => void;
/**
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added style can className support to Popover

@adrienzheng-cb adrienzheng-cb marked this pull request as ready for review April 2, 2026 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants