diff --git a/packages/core/src/components/Menu/MenuItem/MenuItem.tsx b/packages/core/src/components/Menu/MenuItem/MenuItem.tsx index 7fdc05cc7f..08eeec8418 100644 --- a/packages/core/src/components/Menu/MenuItem/MenuItem.tsx +++ b/packages/core/src/components/Menu/MenuItem/MenuItem.tsx @@ -56,6 +56,14 @@ export interface MenuItemProps extends VibeComponentProps { splitMenuItem?: boolean; "aria-label"?: AriaAttributes["aria-label"]; submenuPosition?: SubmenuPosition; + /** + * Enables the observation of content resize for the menu item's submenu. + * When set to `true`, a ResizeObserver is attached to the popper content, + * automatically triggering repositioning when the size of the submenu's content changes. + * + * This is useful for when submenu's content may grow or shrink without a re-render being triggered. + */ + observeSubMenuContentResize?: boolean; } export interface MenuItemTitleComponentProps extends Omit { diff --git a/packages/core/src/components/Menu/MenuItem/components/MenuItemSubMenu/MenuItemSubMenu.tsx b/packages/core/src/components/Menu/MenuItem/components/MenuItemSubMenu/MenuItemSubMenu.tsx index abfd1859ce..da240a6436 100644 --- a/packages/core/src/components/Menu/MenuItem/components/MenuItemSubMenu/MenuItemSubMenu.tsx +++ b/packages/core/src/components/Menu/MenuItem/components/MenuItemSubMenu/MenuItemSubMenu.tsx @@ -12,7 +12,8 @@ const MenuItemSubMenu = ({ autoFocusOnMount, onClose, children, - submenuPosition + submenuPosition, + observeSubMenuContentResize }: MenuItemSubMenuProps) => { const childRef = useRef(null); const popperElementRef = useRef(null); @@ -36,7 +37,8 @@ const MenuItemSubMenu = ({ popperElementRef?.current, { isOpen: open, - placement: submenuPlacement + placement: submenuPlacement, + observeContentResize: observeSubMenuContentResize } ); diff --git a/packages/core/src/components/Menu/MenuItem/components/MenuItemSubMenu/MenuItemSubMenu.types.ts b/packages/core/src/components/Menu/MenuItem/components/MenuItemSubMenu/MenuItemSubMenu.types.ts index 8eac7274de..855059b843 100644 --- a/packages/core/src/components/Menu/MenuItem/components/MenuItemSubMenu/MenuItemSubMenu.types.ts +++ b/packages/core/src/components/Menu/MenuItem/components/MenuItemSubMenu/MenuItemSubMenu.types.ts @@ -1,8 +1,9 @@ import React from "react"; import { CloseMenuOption, MenuChild } from "../../../Menu/MenuConstants"; import { SubmenuPosition } from "../../MenuItem.types"; +import { MenuItemProps } from "../../MenuItem"; -export interface MenuItemSubMenuProps { +export interface MenuItemSubMenuProps extends Pick { /** * Reference to the anchor element that the submenu is related to. This is used to position the submenu correctly relative to the parent menu item. */ diff --git a/packages/core/src/hooks/usePopover.ts b/packages/core/src/hooks/usePopover.ts index 6cf3159f50..10e36606c6 100644 --- a/packages/core/src/hooks/usePopover.ts +++ b/packages/core/src/hooks/usePopover.ts @@ -4,6 +4,7 @@ import { Placement } from "./popoverConstants"; import useIsomorphicLayoutEffect from "./ssr/useIsomorphicLayoutEffect"; import useForceUpdate from "./useForceUpdate"; import type { Options, State } from "@popperjs/core"; +import { createObserveContentResizeModifier } from "../components/Dialog/modifiers/observeContentResizeModifier"; const { RIGHT_START, RIGHT_END, LEFT_START, LEFT_END } = Placement; @@ -19,10 +20,12 @@ export default function usePopover( popperElement: HTMLElement, { isOpen, - placement = RIGHT_START + placement = RIGHT_START, + observeContentResize }: { isOpen?: boolean; placement?: Placement; + observeContentResize?: boolean; } ) { const forceUpdate = useForceUpdate(); @@ -46,10 +49,11 @@ export default function usePopover( state.styles.popper.visibility = isOpen ? "visible" : "hidden"; return state; } - } + }, + createObserveContentResizeModifier(observeContentResize) ] }; - }, [isOpen, placement]); + }, [isOpen, placement, observeContentResize]); const { styles, attributes } = usePopper(referenceElement, popperElement, popperOptions);