From 43b9f78080e2925345c74733b399033883d0e140 Mon Sep 17 00:00:00 2001 From: Johan Persson Date: Fri, 27 Feb 2026 11:57:11 +0100 Subject: [PATCH] Extract shared Menu popover classNames, propDefs, and types Address review feedback: extract MenuPopoverOwnProps shared type for common props (placement, virtualized, maxWidth, maxHeight, style, className). Extract menuPopoverClassNames and menuPopoverPropDefs in definition.ts to ensure shared values stay in sync across Menu variants. Signed-off-by: Johan Persson --- packages/ui/report.api.md | 29 ++----- packages/ui/src/components/Menu/definition.ts | 85 +++++++------------ packages/ui/src/components/Menu/index.ts | 1 + packages/ui/src/components/Menu/types.ts | 35 +++----- 4 files changed, 53 insertions(+), 97 deletions(-) diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 3c379c2927..bcb4466307 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -1481,15 +1481,9 @@ export const MenuAutocompleteListbox: ( ) => JSX_2.Element; // @public (undocumented) -export type MenuAutocompleteListBoxOwnProps = { +export type MenuAutocompleteListBoxOwnProps = MenuPopoverOwnProps & { placeholder?: string; - placement?: PopoverProps_2['placement']; selectionMode?: ListBoxProps['selectionMode']; - virtualized?: boolean; - maxWidth?: string; - maxHeight?: string; - style?: React.CSSProperties; - className?: string; }; // @public (undocumented) @@ -1498,14 +1492,8 @@ export interface MenuAutocompleteListBoxProps Omit, keyof MenuAutocompleteListBoxOwnProps> {} // @public (undocumented) -export type MenuAutocompleteOwnProps = { +export type MenuAutocompleteOwnProps = MenuPopoverOwnProps & { placeholder?: string; - placement?: PopoverProps_2['placement']; - virtualized?: boolean; - maxWidth?: string; - maxHeight?: string; - style?: React.CSSProperties; - className?: string; }; // @public (undocumented) @@ -1572,14 +1560,8 @@ export interface MenuListBoxItemProps Omit {} // @public (undocumented) -export type MenuListBoxOwnProps = { - placement?: PopoverProps_2['placement']; +export type MenuListBoxOwnProps = MenuPopoverOwnProps & { selectionMode?: ListBoxProps['selectionMode']; - virtualized?: boolean; - maxWidth?: string; - maxHeight?: string; - style?: React.CSSProperties; - className?: string; }; // @public (undocumented) @@ -1588,7 +1570,10 @@ export interface MenuListBoxProps Omit, keyof MenuListBoxOwnProps> {} // @public (undocumented) -export type MenuOwnProps = { +export type MenuOwnProps = MenuPopoverOwnProps; + +// @public +export type MenuPopoverOwnProps = { placement?: PopoverProps_2['placement']; virtualized?: boolean; maxWidth?: string; diff --git a/packages/ui/src/components/Menu/definition.ts b/packages/ui/src/components/Menu/definition.ts index e789832490..ab65cf7dd1 100644 --- a/packages/ui/src/components/Menu/definition.ts +++ b/packages/ui/src/components/Menu/definition.ts @@ -27,43 +27,48 @@ import type { } from './types'; import styles from './Menu.module.css'; +// Shared classNames for all popover-based menu variants +const menuPopoverClassNames = { + root: 'bui-MenuPopover', + inner: 'bui-MenuInner', + content: 'bui-MenuContent', +} as const; + +// Shared classNames for autocomplete menu variants +const menuAutocompleteClassNames = { + ...menuPopoverClassNames, + searchField: 'bui-MenuSearchField', + searchFieldInput: 'bui-MenuSearchFieldInput', + searchFieldClear: 'bui-MenuSearchFieldClear', +} as const; + +// Shared propDefs for all popover-based menu variants +const menuPopoverPropDefs = { + placement: { default: 'bottom start' }, + virtualized: { default: false }, + maxWidth: {}, + maxHeight: {}, + style: {}, + className: {}, +} as const; + /** * Component definition for Menu * @public */ export const MenuDefinition = defineComponent()({ styles, - classNames: { - root: 'bui-MenuPopover', - inner: 'bui-MenuInner', - content: 'bui-MenuContent', - }, - propDefs: { - placement: { default: 'bottom start' }, - virtualized: { default: false }, - maxWidth: {}, - maxHeight: {}, - style: {}, - className: {}, - }, + classNames: menuPopoverClassNames, + propDefs: menuPopoverPropDefs, }); /** @internal */ export const MenuListBoxDefinition = defineComponent()({ styles, - classNames: { - root: 'bui-MenuPopover', - inner: 'bui-MenuInner', - content: 'bui-MenuContent', - }, + classNames: menuPopoverClassNames, propDefs: { - placement: { default: 'bottom start' }, + ...menuPopoverPropDefs, selectionMode: { default: 'single' }, - virtualized: { default: false }, - maxWidth: {}, - maxHeight: {}, - style: {}, - className: {}, }, }); @@ -71,22 +76,10 @@ export const MenuListBoxDefinition = defineComponent()({ export const MenuAutocompleteDefinition = defineComponent()({ styles, - classNames: { - root: 'bui-MenuPopover', - inner: 'bui-MenuInner', - content: 'bui-MenuContent', - searchField: 'bui-MenuSearchField', - searchFieldInput: 'bui-MenuSearchFieldInput', - searchFieldClear: 'bui-MenuSearchFieldClear', - }, + classNames: menuAutocompleteClassNames, propDefs: { + ...menuPopoverPropDefs, placeholder: {}, - placement: { default: 'bottom start' }, - virtualized: { default: false }, - maxWidth: {}, - maxHeight: {}, - style: {}, - className: {}, }, }); @@ -94,23 +87,11 @@ export const MenuAutocompleteDefinition = export const MenuAutocompleteListboxDefinition = defineComponent()({ styles, - classNames: { - root: 'bui-MenuPopover', - inner: 'bui-MenuInner', - content: 'bui-MenuContent', - searchField: 'bui-MenuSearchField', - searchFieldInput: 'bui-MenuSearchFieldInput', - searchFieldClear: 'bui-MenuSearchFieldClear', - }, + classNames: menuAutocompleteClassNames, propDefs: { + ...menuPopoverPropDefs, placeholder: {}, - placement: { default: 'bottom start' }, selectionMode: { default: 'single' }, - virtualized: { default: false }, - maxWidth: {}, - maxHeight: {}, - style: {}, - className: {}, }, }); diff --git a/packages/ui/src/components/Menu/index.ts b/packages/ui/src/components/Menu/index.ts index 113ba0a029..0fbd40c5b5 100644 --- a/packages/ui/src/components/Menu/index.ts +++ b/packages/ui/src/components/Menu/index.ts @@ -31,6 +31,7 @@ export type { MenuTriggerProps, SubmenuTriggerProps, MenuProps, + MenuPopoverOwnProps, MenuOwnProps, MenuListBoxProps, MenuListBoxOwnProps, diff --git a/packages/ui/src/components/Menu/types.ts b/packages/ui/src/components/Menu/types.ts index 9290879f03..14c1baa5c3 100644 --- a/packages/ui/src/components/Menu/types.ts +++ b/packages/ui/src/components/Menu/types.ts @@ -32,8 +32,12 @@ export interface MenuTriggerProps extends RAMenuTriggerProps {} /** @public */ export interface SubmenuTriggerProps extends RAMenuSubmenuTriggerProps {} -/** @public */ -export type MenuOwnProps = { +/** + * Common own props shared by all Menu popover variants. + * + * @public + */ +export type MenuPopoverOwnProps = { placement?: RAPopoverProps['placement']; virtualized?: boolean; maxWidth?: string; @@ -42,20 +46,17 @@ export type MenuOwnProps = { className?: string; }; +/** @public */ +export type MenuOwnProps = MenuPopoverOwnProps; + /** @public */ export interface MenuProps extends MenuOwnProps, Omit, keyof MenuOwnProps> {} /** @public */ -export type MenuListBoxOwnProps = { - placement?: RAPopoverProps['placement']; +export type MenuListBoxOwnProps = MenuPopoverOwnProps & { selectionMode?: RAListBoxProps['selectionMode']; - virtualized?: boolean; - maxWidth?: string; - maxHeight?: string; - style?: React.CSSProperties; - className?: string; }; /** @public */ @@ -64,14 +65,8 @@ export interface MenuListBoxProps Omit, keyof MenuListBoxOwnProps> {} /** @public */ -export type MenuAutocompleteOwnProps = { +export type MenuAutocompleteOwnProps = MenuPopoverOwnProps & { placeholder?: string; - placement?: RAPopoverProps['placement']; - virtualized?: boolean; - maxWidth?: string; - maxHeight?: string; - style?: React.CSSProperties; - className?: string; }; /** @public */ @@ -80,15 +75,9 @@ export interface MenuAutocompleteProps Omit, keyof MenuAutocompleteOwnProps> {} /** @public */ -export type MenuAutocompleteListBoxOwnProps = { +export type MenuAutocompleteListBoxOwnProps = MenuPopoverOwnProps & { placeholder?: string; - placement?: RAPopoverProps['placement']; selectionMode?: RAListBoxProps['selectionMode']; - virtualized?: boolean; - maxWidth?: string; - maxHeight?: string; - style?: React.CSSProperties; - className?: string; }; /** @public */