From bc4acdcc081ad240bf9c53f6170759187e1189ba Mon Sep 17 00:00:00 2001 From: Preeti Bansal <146315451+preetibansalui@users.noreply.github.com> Date: Fri, 30 Aug 2024 01:28:48 +0530 Subject: [PATCH] 16879 collision boundary in auto align components (#17139) * feat: added hide to useFloating hook * feat: added hide to useFloating hook in Multiselect * feat: added hide to useFloating hook in FilterableMultiselect * feat: added hide to useFloating hook in Popover * feat: added hide to useFloating hook in Combobutton * fix: text case * fix: test case * fix: test case --------- Co-authored-by: Nikhil Tomar <63502271+2nikhiltom@users.noreply.github.com> --- .../react/src/components/ComboBox/ComboBox.tsx | 15 +++++++++++---- .../components/ComboButton/ComboButton-test.js | 11 +++++------ .../react/src/components/ComboButton/index.tsx | 11 ++++++++--- .../MultiSelect/FilterableMultiSelect.tsx | 10 ++++++++-- .../src/components/MultiSelect/MultiSelect.tsx | 12 ++++++++++-- packages/react/src/components/Popover/index.tsx | 12 ++++++++++-- 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/packages/react/src/components/ComboBox/ComboBox.tsx b/packages/react/src/components/ComboBox/ComboBox.tsx index 6bfb35236d09..8266ad21dbd8 100644 --- a/packages/react/src/components/ComboBox/ComboBox.tsx +++ b/packages/react/src/components/ComboBox/ComboBox.tsx @@ -45,6 +45,7 @@ import deprecate from '../../prop-types/deprecate'; import { usePrefix } from '../../internal/usePrefix'; import { FormContext } from '../FluidForm'; import { useFloating, flip, autoUpdate } from '@floating-ui/react'; +import { hide } from '@floating-ui/dom'; import { TranslateWithId } from '../../types/common'; const { @@ -381,12 +382,12 @@ const ComboBox = forwardRef( slug, ...rest } = props; - const { refs, floatingStyles } = useFloating( + const { refs, floatingStyles, middlewareData } = useFloating( autoAlign ? { placement: direction, strategy: 'fixed', - middleware: [flip()], + middleware: [flip(), hide()], whileElementsMounted: autoUpdate, } : {} @@ -395,9 +396,15 @@ const ComboBox = forwardRef( useEffect(() => { if (autoAlign) { - Object.keys(floatingStyles).forEach((style) => { + const updatedFloatingStyles = { + ...floatingStyles, + visibility: middlewareData.hide?.referenceHidden + ? 'hidden' + : 'visible', + }; + Object.keys(updatedFloatingStyles).forEach((style) => { if (refs.floating.current) { - refs.floating.current.style[style] = floatingStyles[style]; + refs.floating.current.style[style] = updatedFloatingStyles[style]; } }); if (parentWidth && refs.floating.current) { diff --git a/packages/react/src/components/ComboButton/ComboButton-test.js b/packages/react/src/components/ComboButton/ComboButton-test.js index 098324681552..9bb5a65715e2 100644 --- a/packages/react/src/components/ComboButton/ComboButton-test.js +++ b/packages/react/src/components/ComboButton/ComboButton-test.js @@ -133,8 +133,7 @@ describe('ComboButton', () => { ); await userEvent.click(screen.getAllByRole('button')[1]); - - expect(screen.getByRole('menu')).toHaveClass( + expect(document.querySelector('ul.cds--menu')).toHaveClass( `${prefix}--combo-button__${alignment}` ); }); @@ -181,10 +180,10 @@ describe('ComboButton', () => { await userEvent.click(screen.getAllByRole('button')[1]); - expect(screen.getByRole('menu')).toBeInTheDocument(); - expect(screen.getByRole('menuitem')).toHaveTextContent( - /^Additional action$/ - ); + expect(document.querySelector('ul.cds--menu')).toBeInTheDocument(); + expect( + document.querySelector('.cds--menu-item__label') + ).toHaveTextContent(/^Additional action$/); }); it('warns when MenuItemSelectable is used in children', async () => { diff --git a/packages/react/src/components/ComboButton/index.tsx b/packages/react/src/components/ComboButton/index.tsx index cc7d3f9388a8..178a5ca3fb09 100644 --- a/packages/react/src/components/ComboButton/index.tsx +++ b/packages/react/src/components/ComboButton/index.tsx @@ -21,6 +21,7 @@ import { size as floatingSize, autoUpdate, } from '@floating-ui/react'; +import { hide } from '@floating-ui/dom'; import mergeRefs from '../../tools/mergeRefs'; import { MenuAlignment } from '../MenuButton'; import { TranslateWithId } from '../../types/common'; @@ -99,7 +100,7 @@ const ComboButton = React.forwardRef( const id = useId('combobutton'); const prefix = usePrefix(); const containerRef = useRef(null); - const middlewares = [flip({ crossAxis: false })]; + const middlewares = [flip({ crossAxis: false }), hide()]; if (menuAlignment === 'bottom' || menuAlignment === 'top') { middlewares.push( @@ -134,9 +135,13 @@ const ComboButton = React.forwardRef( } = useAttachedMenu(containerRef); useLayoutEffect(() => { - Object.keys(floatingStyles).forEach((style) => { + const updatedFloatingStyles = { + ...floatingStyles, + visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible', + }; + Object.keys(updatedFloatingStyles).forEach((style) => { if (refs.floating.current) { - refs.floating.current.style[style] = floatingStyles[style]; + refs.floating.current.style[style] = updatedFloatingStyles[style]; } }); }, [floatingStyles, refs.floating, middlewareData, placement, open]); diff --git a/packages/react/src/components/MultiSelect/FilterableMultiSelect.tsx b/packages/react/src/components/MultiSelect/FilterableMultiSelect.tsx index 575bd95d59ef..93dbfd775561 100644 --- a/packages/react/src/components/MultiSelect/FilterableMultiSelect.tsx +++ b/packages/react/src/components/MultiSelect/FilterableMultiSelect.tsx @@ -57,6 +57,7 @@ import { size as floatingSize, autoUpdate, } from '@floating-ui/react'; +import { hide } from '@floating-ui/dom'; import { TranslateWithId } from '../../types/common'; const { @@ -388,6 +389,7 @@ const FilterableMultiSelect = React.forwardRef(function FilterableMultiSelect< }); }, }), + hide(), ], whileElementsMounted: autoUpdate, } @@ -396,9 +398,13 @@ const FilterableMultiSelect = React.forwardRef(function FilterableMultiSelect< useLayoutEffect(() => { if (autoAlign) { - Object.keys(floatingStyles).forEach((style) => { + const updatedFloatingStyles = { + ...floatingStyles, + visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible', + }; + Object.keys(updatedFloatingStyles).forEach((style) => { if (refs.floating.current) { - refs.floating.current.style[style] = floatingStyles[style]; + refs.floating.current.style[style] = updatedFloatingStyles[style]; } }); } diff --git a/packages/react/src/components/MultiSelect/MultiSelect.tsx b/packages/react/src/components/MultiSelect/MultiSelect.tsx index ee89bee18e61..18d2baa827a1 100644 --- a/packages/react/src/components/MultiSelect/MultiSelect.tsx +++ b/packages/react/src/components/MultiSelect/MultiSelect.tsx @@ -51,6 +51,7 @@ import { size as floatingSize, autoUpdate, } from '@floating-ui/react'; +import { hide } from '@floating-ui/dom'; const { ItemClick, @@ -371,6 +372,7 @@ const MultiSelect = React.forwardRef( }); }, }), + hide(), ], whileElementsMounted: autoUpdate, } @@ -379,9 +381,15 @@ const MultiSelect = React.forwardRef( useLayoutEffect(() => { if (autoAlign) { - Object.keys(floatingStyles).forEach((style) => { + const updatedFloatingStyles = { + ...floatingStyles, + visibility: middlewareData.hide?.referenceHidden + ? 'hidden' + : 'visible', + }; + Object.keys(updatedFloatingStyles).forEach((style) => { if (refs.floating.current) { - refs.floating.current.style[style] = floatingStyles[style]; + refs.floating.current.style[style] = updatedFloatingStyles[style]; } }); } diff --git a/packages/react/src/components/Popover/index.tsx b/packages/react/src/components/Popover/index.tsx index 286308491759..8a2fc27dd12c 100644 --- a/packages/react/src/components/Popover/index.tsx +++ b/packages/react/src/components/Popover/index.tsx @@ -29,6 +29,7 @@ import { arrow, offset, } from '@floating-ui/react'; +import { hide } from '@floating-ui/dom'; interface PopoverContext { setFloating: React.Ref; @@ -258,6 +259,7 @@ export const Popover: PopoverComponent = React.forwardRef( arrow({ element: caretRef, }), + hide(), ], whileElementsMounted: autoUpdate, } @@ -286,9 +288,15 @@ export const Popover: PopoverComponent = React.forwardRef( useEffect(() => { if (autoAlign) { - Object.keys(floatingStyles).forEach((style) => { + const updatedFloatingStyles = { + ...floatingStyles, + visibility: middlewareData.hide?.referenceHidden + ? 'hidden' + : 'visible', + }; + Object.keys(updatedFloatingStyles).forEach((style) => { if (refs.floating.current) { - refs.floating.current.style[style] = floatingStyles[style]; + refs.floating.current.style[style] = updatedFloatingStyles[style]; } });