diff --git a/change/@fluentui-react-portal-aa25b18c-fd1c-479e-a98c-f045187327b7.json b/change/@fluentui-react-portal-aa25b18c-fd1c-479e-a98c-f045187327b7.json new file mode 100644 index 00000000000000..4b214bb0b7ff3f --- /dev/null +++ b/change/@fluentui-react-portal-aa25b18c-fd1c-479e-a98c-f045187327b7.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "revert: revert removal of Griffel dependency from usePortalMount #35994", + "packageName": "@fluentui/react-portal", + "email": "dmytrokirpa@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNode.ts b/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNode.ts index 8c260da5b05103..f62e4184c05701 100644 --- a/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNode.ts +++ b/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNode.ts @@ -6,9 +6,10 @@ import { useFluent_unstable as useFluent, usePortalMountNode as usePortalMountNodeContext, } from '@fluentui/react-shared-contexts'; +import { mergeClasses } from '@griffel/react'; import { useFocusVisible } from '@fluentui/react-tabster'; -import { usePortalMountNodeStyles } from './usePortalMountNodeStyles'; +import { usePortalMountNodeStylesStyles } from './usePortalMountNodeStyles.styles'; const useInsertionEffect = (React as never)['useInsertion' + 'Effect'] as typeof React.useLayoutEffect | undefined; @@ -200,14 +201,16 @@ const useModernElementFactory: UseElementFactory = options => { return; } - elementProxy.setAttribute('class', className); + const classesToApply = className.split(' ').filter(Boolean); + + elementProxy.classList.add(...classesToApply); elementProxy.setAttribute('dir', dir); elementProxy.setAttribute('data-portal-node', 'true'); focusVisibleRef.current = elementProxy; return () => { - elementProxy.removeAttribute('class'); + elementProxy.classList.remove(...classesToApply); elementProxy.removeAttribute('dir'); }; }, [className, dir, elementProxy, focusVisibleRef]); @@ -243,6 +246,7 @@ export const usePortalMountNode = (options: UsePortalMountNodeOptions): HTMLElem // eslint-disable-next-line @typescript-eslint/no-deprecated const focusVisibleRef = useFocusVisible() as React.MutableRefObject; + const classes = usePortalMountNodeStylesStyles(); const themeClassName = useThemeClassName(); const factoryOptions: UseElementFactoryOptions = { @@ -250,11 +254,9 @@ export const usePortalMountNode = (options: UsePortalMountNodeOptions): HTMLElem disabled: options.disabled, focusVisibleRef, - className: [themeClassName, options.className].filter(Boolean).join(' '), + className: mergeClasses(themeClassName, classes.root, options.className), targetNode: mountNode ?? targetDocument?.body, }; - usePortalMountNodeStyles(options.disabled); - return useElementFactory(factoryOptions); }; diff --git a/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNodeStyles.styles.ts b/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNodeStyles.styles.ts new file mode 100644 index 00000000000000..ed71de80786792 --- /dev/null +++ b/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNodeStyles.styles.ts @@ -0,0 +1,18 @@ +'use client'; + +import { makeStyles } from '@griffel/react'; + +export const usePortalMountNodeStylesStyles = makeStyles({ + root: { + // Creates new stacking context to prevent z-index issues + // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context + // + // Also keeps a portal on top of a page to prevent scrollbars from appearing + position: 'absolute', + top: 0, + left: 0, + right: 0, + + zIndex: 1000000, + }, +}); diff --git a/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNodeStyles.test.tsx b/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNodeStyles.test.tsx deleted file mode 100644 index af3093466b5189..00000000000000 --- a/packages/react-components/react-portal/library/src/components/Portal/usePortalMountNodeStyles.test.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { renderHook } from '@testing-library/react-hooks'; -import { Provider_unstable as Provider } from '@fluentui/react-shared-contexts'; -import * as React from 'react'; - -import { usePortalMountNodeStyles, PORTAL_STYLE_ELEMENT_ID, setPortalRefCount } from './usePortalMountNodeStyles'; - -function queryStyleElement(): HTMLStyleElement | null { - return document.head.querySelector(`#${PORTAL_STYLE_ELEMENT_ID}`); -} - -function createWrapper(targetDocument: Document | undefined) { - return (props: { children?: React.ReactNode }) => ( - {props.children} - ); -} - -describe('usePortalMountNodeStyles', () => { - afterEach(() => { - // Clean up any leftover style elements and reset the ref count - queryStyleElement()?.remove(); - setPortalRefCount(document, 0); - }); - - it('injects a