From 4562a119038148cc3594649276adf9991d8d718b Mon Sep 17 00:00:00 2001 From: yyh Date: Mon, 2 Mar 2026 20:08:09 +0800 Subject: [PATCH] refactor(web): align overlay primitive content prop pass-through - add positioner/popup/list pass-through props for select/popover/dropdown wrappers - keep existing semantic placement API while enabling Base UI behavioral extensibility - align wrapper ergonomics across overlay primitives --- .../base/ui/dropdown-menu/index.tsx | 28 +++++++++++++++++-- web/app/components/base/ui/popover/index.tsx | 12 ++++++++ web/app/components/base/ui/select/index.tsx | 22 ++++++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/web/app/components/base/ui/dropdown-menu/index.tsx b/web/app/components/base/ui/dropdown-menu/index.tsx index 68d52f320e..85a81968d4 100644 --- a/web/app/components/base/ui/dropdown-menu/index.tsx +++ b/web/app/components/base/ui/dropdown-menu/index.tsx @@ -25,14 +25,24 @@ type DropdownMenuContentProps = { alignOffset?: number className?: string popupClassName?: string + positionerProps?: Omit< + React.ComponentPropsWithoutRef, + 'children' | 'className' | 'side' | 'align' | 'sideOffset' | 'alignOffset' + > + popupProps?: Omit< + React.ComponentPropsWithoutRef, + 'children' | 'className' + > } -type DropdownMenuPopupProps = Required> & { +type DropdownMenuPopupRenderProps = Required> & { placement: Placement sideOffset: number alignOffset: number className?: string popupClassName?: string + positionerProps?: DropdownMenuContentProps['positionerProps'] + popupProps?: DropdownMenuContentProps['popupProps'] } function renderDropdownMenuPopup({ @@ -42,7 +52,9 @@ function renderDropdownMenuPopup({ alignOffset, className, popupClassName, -}: DropdownMenuPopupProps) { + positionerProps, + popupProps, +}: DropdownMenuPopupRenderProps) { const { side, align } = parsePlacement(placement) return ( @@ -53,6 +65,7 @@ function renderDropdownMenuPopup({ sideOffset={sideOffset} alignOffset={alignOffset} className={cn('outline-none', className)} + {...positionerProps} > {children} @@ -75,6 +89,8 @@ export function DropdownMenuContent({ alignOffset = 0, className, popupClassName, + positionerProps, + popupProps, }: DropdownMenuContentProps) { return renderDropdownMenuPopup({ children, @@ -83,6 +99,8 @@ export function DropdownMenuContent({ alignOffset, className, popupClassName, + positionerProps, + popupProps, }) } @@ -115,6 +133,8 @@ type DropdownMenuSubContentProps = { alignOffset?: number className?: string popupClassName?: string + positionerProps?: DropdownMenuContentProps['positionerProps'] + popupProps?: DropdownMenuContentProps['popupProps'] } export function DropdownMenuSubContent({ @@ -124,6 +144,8 @@ export function DropdownMenuSubContent({ alignOffset = 0, className, popupClassName, + positionerProps, + popupProps, }: DropdownMenuSubContentProps) { return renderDropdownMenuPopup({ children, @@ -132,6 +154,8 @@ export function DropdownMenuSubContent({ alignOffset, className, popupClassName, + positionerProps, + popupProps, }) } diff --git a/web/app/components/base/ui/popover/index.tsx b/web/app/components/base/ui/popover/index.tsx index cda7748ed2..fe9808ec52 100644 --- a/web/app/components/base/ui/popover/index.tsx +++ b/web/app/components/base/ui/popover/index.tsx @@ -19,6 +19,14 @@ type PopoverContentProps = { alignOffset?: number className?: string popupClassName?: string + positionerProps?: Omit< + React.ComponentPropsWithoutRef, + 'children' | 'className' | 'side' | 'align' | 'sideOffset' | 'alignOffset' + > + popupProps?: Omit< + React.ComponentPropsWithoutRef, + 'children' | 'className' + > } export function PopoverContent({ @@ -28,6 +36,8 @@ export function PopoverContent({ alignOffset = 0, className, popupClassName, + positionerProps, + popupProps, }: PopoverContentProps) { const { side, align } = parsePlacement(placement) @@ -39,6 +49,7 @@ export function PopoverContent({ sideOffset={sideOffset} alignOffset={alignOffset} className={cn('outline-none', className)} + {...positionerProps} > {children} diff --git a/web/app/components/base/ui/select/index.tsx b/web/app/components/base/ui/select/index.tsx index aa386c5037..68786815db 100644 --- a/web/app/components/base/ui/select/index.tsx +++ b/web/app/components/base/ui/select/index.tsx @@ -42,6 +42,18 @@ type SelectContentProps = { className?: string popupClassName?: string listClassName?: string + positionerProps?: Omit< + React.ComponentPropsWithoutRef, + 'children' | 'className' | 'side' | 'align' | 'sideOffset' | 'alignOffset' + > + popupProps?: Omit< + React.ComponentPropsWithoutRef, + 'children' | 'className' + > + listProps?: Omit< + React.ComponentPropsWithoutRef, + 'children' | 'className' + > } export function SelectContent({ @@ -52,6 +64,9 @@ export function SelectContent({ className, popupClassName, listClassName, + positionerProps, + popupProps, + listProps, }: SelectContentProps) { const { side, align } = parsePlacement(placement) @@ -63,6 +78,7 @@ export function SelectContent({ sideOffset={sideOffset} alignOffset={alignOffset} className={cn('outline-none', className)} + {...positionerProps} > - + {children}