diff --git a/change/@fluentui-react-menu-6d777269-9ba0-4bc9-bcc4-35ccd0b6588b.json b/change/@fluentui-react-menu-6d777269-9ba0-4bc9-bcc4-35ccd0b6588b.json new file mode 100644 index 0000000000000..c34a1ff560b38 --- /dev/null +++ b/change/@fluentui-react-menu-6d777269-9ba0-4bc9-bcc4-35ccd0b6588b.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "refactor(MenuPopover): migrate opacity transition to Fade component", + "packageName": "@fluentui/react-menu", + "email": "robertpenner@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@fluentui-react-popover-9cbd1ae2-b716-4325-a154-6f0766f13802.json b/change/@fluentui-react-popover-9cbd1ae2-b716-4325-a154-6f0766f13802.json new file mode 100644 index 0000000000000..826594988b61d --- /dev/null +++ b/change/@fluentui-react-popover-9cbd1ae2-b716-4325-a154-6f0766f13802.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "refactor(Popover): migrate opacity transition to Fade component", + "packageName": "@fluentui/react-popover", + "email": "robertpenner@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@fluentui-react-positioning-a236325b-e9a5-4ad8-bace-083cf9b4d846.json b/change/@fluentui-react-positioning-a236325b-e9a5-4ad8-bace-083cf9b4d846.json new file mode 100644 index 0000000000000..1c3f18c625331 --- /dev/null +++ b/change/@fluentui-react-positioning-a236325b-e9a5-4ad8-bace-083cf9b4d846.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "refactor(react-positioning): migrate opacity transition to Fade component", + "packageName": "@fluentui/react-positioning", + "email": "robertpenner@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-menu/library/package.json b/packages/react-components/react-menu/library/package.json index cb1698fff1be9..10f8043db99ca 100644 --- a/packages/react-components/react-menu/library/package.json +++ b/packages/react-components/react-menu/library/package.json @@ -24,6 +24,7 @@ "@fluentui/react-aria": "^9.13.10", "@fluentui/react-context-selector": "^9.1.70", "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-motion-components-preview": "^0.3.2", "@fluentui/react-portal": "^9.4.39", "@fluentui/react-positioning": "^9.15.13", "@fluentui/react-shared-contexts": "^9.21.1", diff --git a/packages/react-components/react-menu/library/src/components/MenuPopover/MenuPopover.types.ts b/packages/react-components/react-menu/library/src/components/MenuPopover/MenuPopover.types.ts index b460bce616691..e5c0ea85c97b8 100644 --- a/packages/react-components/react-menu/library/src/components/MenuPopover/MenuPopover.types.ts +++ b/packages/react-components/react-menu/library/src/components/MenuPopover/MenuPopover.types.ts @@ -1,5 +1,6 @@ import type { PortalProps } from '@fluentui/react-portal'; import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities'; +import { MenuContextValue } from '../../contexts/menuContext'; export type MenuPopoverSlots = { root: Slot<'div'>; @@ -14,6 +15,7 @@ export type MenuPopoverProps = ComponentProps; * State used in rendering MenuPopover */ export type MenuPopoverState = ComponentState & + Pick & Pick & { /** * Root menus are rendered out of DOM order on `document.body`, use this to render the menu in DOM order diff --git a/packages/react-components/react-menu/library/src/components/MenuPopover/renderMenuPopover.tsx b/packages/react-components/react-menu/library/src/components/MenuPopover/renderMenuPopover.tsx index 3fa0c19f2619f..a5ed27b3dcb5a 100644 --- a/packages/react-components/react-menu/library/src/components/MenuPopover/renderMenuPopover.tsx +++ b/packages/react-components/react-menu/library/src/components/MenuPopover/renderMenuPopover.tsx @@ -3,6 +3,7 @@ import { assertSlots } from '@fluentui/react-utilities'; import { MenuPopoverSlots, MenuPopoverState } from './MenuPopover.types'; import { Portal } from '@fluentui/react-portal'; +import { Fade } from '@fluentui/react-motion-components-preview'; /** * Render the final JSX of MenuPopover @@ -10,13 +11,15 @@ import { Portal } from '@fluentui/react-portal'; export const renderMenuPopover_unstable = (state: MenuPopoverState) => { assertSlots(state); + const surface = ( + + + + ); + if (state.inline) { - return ; + return surface; } - return ( - - - - ); + return {surface}; }; diff --git a/packages/react-components/react-menu/library/src/components/MenuPopover/useMenuPopover.ts b/packages/react-components/react-menu/library/src/components/MenuPopover/useMenuPopover.ts index a555f0dd69a13..5eb7a4ffb17c8 100644 --- a/packages/react-components/react-menu/library/src/components/MenuPopover/useMenuPopover.ts +++ b/packages/react-components/react-menu/library/src/components/MenuPopover/useMenuPopover.ts @@ -97,5 +97,5 @@ export const useMenuPopover_unstable = (props: MenuPopoverProps, ref: React.Ref< } onKeyDownOriginal?.(event); }); - return { inline, mountNode, components: { root: 'div' }, root: rootProps }; + return { inline, mountNode, open, components: { root: 'div' }, root: rootProps }; }; diff --git a/packages/react-components/react-popover/library/package.json b/packages/react-components/react-popover/library/package.json index 9d8bd096cee72..086eb42c391d7 100644 --- a/packages/react-components/react-popover/library/package.json +++ b/packages/react-components/react-popover/library/package.json @@ -24,6 +24,7 @@ "@fluentui/keyboard-keys": "^9.0.8", "@fluentui/react-aria": "^9.13.10", "@fluentui/react-context-selector": "^9.1.70", + "@fluentui/react-motion-components-preview": "^0.3.2", "@fluentui/react-portal": "^9.4.39", "@fluentui/react-positioning": "^9.15.13", "@fluentui/react-shared-contexts": "^9.21.1", diff --git a/packages/react-components/react-popover/library/src/components/PopoverSurface/PopoverSurface.types.ts b/packages/react-components/react-popover/library/src/components/PopoverSurface/PopoverSurface.types.ts index 3fedd34f669ea..21e606bca0c55 100644 --- a/packages/react-components/react-popover/library/src/components/PopoverSurface/PopoverSurface.types.ts +++ b/packages/react-components/react-popover/library/src/components/PopoverSurface/PopoverSurface.types.ts @@ -17,7 +17,7 @@ export type PopoverSurfaceSlots = { * PopoverSurface State */ export type PopoverSurfaceState = ComponentState & - Pick & { + Pick & { /** * CSS class for the arrow element */ diff --git a/packages/react-components/react-popover/library/src/components/PopoverSurface/renderPopoverSurface.tsx b/packages/react-components/react-popover/library/src/components/PopoverSurface/renderPopoverSurface.tsx index ebc5920a9ae10..48fcf90c758ad 100644 --- a/packages/react-components/react-popover/library/src/components/PopoverSurface/renderPopoverSurface.tsx +++ b/packages/react-components/react-popover/library/src/components/PopoverSurface/renderPopoverSurface.tsx @@ -3,6 +3,7 @@ import { assertSlots } from '@fluentui/react-utilities'; import { Portal } from '@fluentui/react-portal'; import type { PopoverSurfaceSlots, PopoverSurfaceState } from './PopoverSurface.types'; +import { Fade } from '@fluentui/react-motion-components-preview'; /** * Render the final JSX of PopoverSurface @@ -11,10 +12,12 @@ export const renderPopoverSurface_unstable = (state: PopoverSurfaceState) => { assertSlots(state); const surface = ( - - {state.withArrow &&
} - {state.root.children} - + + + {state.withArrow &&
} + {state.root.children} + + ); if (state.inline) { diff --git a/packages/react-components/react-popover/library/src/components/PopoverSurface/usePopoverSurface.ts b/packages/react-components/react-popover/library/src/components/PopoverSurface/usePopoverSurface.ts index 56bbcb3713483..1f0715249330a 100644 --- a/packages/react-components/react-popover/library/src/components/PopoverSurface/usePopoverSurface.ts +++ b/packages/react-components/react-popover/library/src/components/PopoverSurface/usePopoverSurface.ts @@ -19,6 +19,7 @@ export const usePopoverSurface_unstable = ( ): PopoverSurfaceState => { const contentRef = usePopoverContext_unstable(context => context.contentRef); const openOnHover = usePopoverContext_unstable(context => context.openOnHover); + const open = usePopoverContext_unstable(context => context.open); const setOpen = usePopoverContext_unstable(context => context.setOpen); const mountNode = usePopoverContext_unstable(context => context.mountNode); const arrowRef = usePopoverContext_unstable(context => context.arrowRef); @@ -35,6 +36,7 @@ export const usePopoverSurface_unstable = ( }); const state: PopoverSurfaceState = { + open, inline, appearance, withArrow, diff --git a/packages/react-components/react-positioning/src/createSlideStyles.ts b/packages/react-components/react-positioning/src/createSlideStyles.ts index af6ebd24b9bc9..7dfc51100998c 100644 --- a/packages/react-components/react-positioning/src/createSlideStyles.ts +++ b/packages/react-components/react-positioning/src/createSlideStyles.ts @@ -8,21 +8,12 @@ import { DATA_POSITIONING_PLACEMENT } from './constants'; * @returns Griffel styles to spread to a slot */ export function createSlideStyles(mainAxis: number): GriffelStyle { - const fadeIn = { - from: { - opacity: 0, - }, - to: { - opacity: 1, - }, - }; - const slideDistanceVarX = '--fui-positioning-slide-distance-x'; const slideDistanceVarY = '--fui-positioning-slide-distance-y'; return { - // The fade has absolute values, whereas the slide amount is relative. - animationComposition: 'replace, accumulate', + // The slide amount is relative + animationComposition: 'accumulate', animationDuration: tokens.durationSlower, animationTimingFunction: tokens.curveDecelerateMid, [slideDistanceVarX]: `0px`, @@ -43,7 +34,6 @@ export function createSlideStyles(mainAxis: number): GriffelStyle { }, animationName: [ - fadeIn, { from: { transform: `translate(var(${slideDistanceVarX}), var(${slideDistanceVarY}))`, @@ -55,17 +45,16 @@ export function createSlideStyles(mainAxis: number): GriffelStyle { // Note: at-rules have more specificity in Griffel '@media(prefers-reduced-motion)': { [`&[${DATA_POSITIONING_PLACEMENT}]`]: { - animationComposition: 'replace', - animationDuration: '1ms', - animationName: fadeIn, + // Omit the slide animation + animationName: {}, }, }, // Tested in Firefox 79 '@supports not (animation-composition: accumulate)': { [`&[${DATA_POSITIONING_PLACEMENT}]`]: { - animationComposition: 'replace', - animationName: fadeIn, + // Omit the slide animation + animationName: {}, }, }, };