Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Popover): migrate opacity transition to Fade component #33424

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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'>;
Expand All @@ -14,6 +15,7 @@ export type MenuPopoverProps = ComponentProps<MenuPopoverSlots>;
* State used in rendering MenuPopover
*/
export type MenuPopoverState = ComponentState<MenuPopoverSlots> &
Pick<MenuContextValue, 'open'> &
Pick<PortalProps, 'mountNode'> & {
/**
* Root menus are rendered out of DOM order on `document.body`, use this to render the menu in DOM order
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@
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
*/
export const renderMenuPopover_unstable = (state: MenuPopoverState) => {
assertSlots<MenuPopoverSlots>(state);

const surface = (
<Fade visible={state.open}>
<state.root />
</Fade>
);

if (state.inline) {
return <state.root />;
return surface;
}

return (
<Portal mountNode={state.mountNode}>
<state.root />
</Portal>
);
return <Portal mountNode={state.mountNode}>{surface}</Portal>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
};
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type PopoverSurfaceSlots = {
* PopoverSurface State
*/
export type PopoverSurfaceState = ComponentState<PopoverSurfaceSlots> &
Pick<PopoverContextValue, 'appearance' | 'arrowRef' | 'inline' | 'mountNode' | 'size' | 'withArrow'> & {
Pick<PopoverContextValue, 'appearance' | 'arrowRef' | 'inline' | 'open' | 'mountNode' | 'size' | 'withArrow'> & {
/**
* CSS class for the arrow element
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -11,10 +12,12 @@ export const renderPopoverSurface_unstable = (state: PopoverSurfaceState) => {
assertSlots<PopoverSurfaceSlots>(state);

const surface = (
<state.root>
{state.withArrow && <div ref={state.arrowRef} className={state.arrowClassName} />}
{state.root.children}
</state.root>
<Fade visible={state.open}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should introduce a motion slot if we add an animation, otherwise there is no way to remove it/customize it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not adding any animation; we're just swapping the implementation of what was already there.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<state.root>
{state.withArrow && <div ref={state.arrowRef} className={state.arrowClassName} />}
{state.root.children}
</state.root>
</Fade>
);

if (state.inline) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -35,6 +36,7 @@ export const usePopoverSurface_unstable = (
});

const state: PopoverSurfaceState = {
open,
inline,
appearance,
withArrow,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand All @@ -43,7 +34,6 @@ export function createSlideStyles(mainAxis: number): GriffelStyle {
},

animationName: [
fadeIn,
{
from: {
transform: `translate(var(${slideDistanceVarX}), var(${slideDistanceVarY}))`,
Expand All @@ -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: {},
},
},
};
Expand Down
Loading