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: collapse motion #36597

Merged
merged 3 commits into from Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions components/_util/motion.tsx
Expand Up @@ -12,8 +12,8 @@ const getCurrentHeight: MotionEventHandler = node => ({ height: node ? node.offs
const skipOpacityTransition: MotionEndEventHandler = (_, event: MotionEvent) =>
event?.deadline === true || (event as TransitionEvent).propertyName === 'height';

const collapseMotion: CSSMotionProps = {
motionName: 'ant-motion-collapse',
const initCollapseMotion = (rootCls: string = 'ant'): CSSMotionProps => ({
motionName: `${rootCls}-motion-collapse`,
onAppearStart: getCollapsedHeight,
onEnterStart: getCollapsedHeight,
onAppearActive: getRealHeight,
Expand All @@ -24,7 +24,7 @@ const collapseMotion: CSSMotionProps = {
onEnterEnd: skipOpacityTransition,
onLeaveEnd: skipOpacityTransition,
motionDeadline: 500,
};
});

const SelectPlacements = tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight');
export type SelectCommonPlacement = typeof SelectPlacements[number];
Expand All @@ -44,4 +44,4 @@ const getTransitionName = (rootPrefixCls: string, motion: string, transitionName
};

export { getTransitionName, getTransitionDirection };
export default collapseMotion;
export default initCollapseMotion;
5 changes: 3 additions & 2 deletions components/collapse/Collapse.tsx
Expand Up @@ -7,7 +7,7 @@ import * as React from 'react';
import toArray from 'rc-util/lib/Children/toArray';
import omit from 'rc-util/lib/omit';
import { ConfigContext } from '../config-provider';
import collapseMotion from '../_util/motion';
import initCollapseMotion from '../_util/motion';
import { cloneElement } from '../_util/reactNode';
import warning from '../_util/warning';
import type { CollapsibleType } from './CollapsePanel';
Expand Down Expand Up @@ -64,6 +64,7 @@ const Collapse: CollapseInterface = props => {
expandIconPosition = 'start',
} = props;
const prefixCls = getPrefixCls('collapse', customizePrefixCls);
const rootPrefixCls = getPrefixCls();
const [wrapSSR, hashId] = useStyle(prefixCls);

// Warning if use legacy type `expandIconPosition`
Expand Down Expand Up @@ -107,7 +108,7 @@ const Collapse: CollapseInterface = props => {
hashId,
);
const openMotion: CSSMotionProps = {
...collapseMotion,
...initCollapseMotion(rootPrefixCls),
motionAppear: false,
leavedClassName: `${prefixCls}-content-hidden`,
};
Expand Down
23 changes: 2 additions & 21 deletions components/collapse/style/index.tsx
@@ -1,3 +1,4 @@
import { genCollapseMotion } from '../../style/motion';
import type { FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import { resetComponent, resetIcon } from '../../style';
Expand Down Expand Up @@ -233,26 +234,6 @@ const genBorderlessStyle: GenerateStyle<CollapseToken> = token => {
};
};

const genMotion: GenerateStyle<CollapseToken> = token => ({
[token.componentCls]: {
// For common/openAnimation
[`${token.antCls}-motion-collapse-legacy`]: {
overflow: 'hidden',

'&-active': {
transition: `height ${token.motionDurationMid} ${token.motionEaseInOut},
opacity ${token.motionDurationMid} ${token.motionEaseInOut} !important`,
},
},

[`${token.antCls}-motion-collapse`]: {
overflow: 'hidden',
transition: `height ${token.motionDurationMid} ${token.motionEaseInOut},
opacity ${token.motionDurationMid} ${token.motionEaseInOut} !important`,
},
},
});

export default genComponentStyleHook('Collapse', token => {
const collapseToken = mergeToken<CollapseToken>(token, {
collapseContentBg: token.colorBgContainer,
Expand All @@ -266,6 +247,6 @@ export default genComponentStyleHook('Collapse', token => {
genBaseStyle(collapseToken),
genBorderlessStyle(collapseToken),
genArrowStyle(collapseToken),
genMotion(collapseToken),
genCollapseMotion(collapseToken),
];
});
8 changes: 6 additions & 2 deletions components/form/ErrorList.tsx
@@ -1,8 +1,9 @@
import classNames from 'classnames';
import CSSMotion, { CSSMotionList } from 'rc-motion';
import * as React from 'react';
import { useMemo } from 'react';
import { ConfigContext } from '../config-provider';
import collapseMotion from '../_util/motion';
import initCollapseMotion from '../_util/motion';
import { FormItemPrefixContext } from './context';
import type { ValidateStatus } from './FormItem';
import useDebounce from './hooks/useDebounce';
Expand Down Expand Up @@ -51,6 +52,8 @@ export default function ErrorList({
const baseClassName = `${prefixCls}-item-explain`;
const rootPrefixCls = getPrefixCls();

const collapseMotion = useMemo(() => initCollapseMotion(rootPrefixCls), [rootPrefixCls]);

// We have to debounce here again since somewhere use ErrorList directly still need no shaking
// ref: https://github.com/ant-design/ant-design/issues/36336
const debounceErrors = useDebounce(errors);
Expand All @@ -71,6 +74,7 @@ export default function ErrorList({

return (
<CSSMotion
{...collapseMotion}
motionDeadline={collapseMotion.motionDeadline}
motionName={`${rootPrefixCls}-show-help`}
visible={!!fullKeyList.length}
Expand All @@ -86,7 +90,7 @@ export default function ErrorList({
>
<CSSMotionList
keys={fullKeyList}
{...collapseMotion}
{...initCollapseMotion(rootPrefixCls)}
motionName={`${rootPrefixCls}-show-help-item`}
component={false}
>
Expand Down
3 changes: 2 additions & 1 deletion components/form/style/index.tsx
@@ -1,5 +1,5 @@
import type { CSSObject } from '@ant-design/cssinjs';
import { zoomIn } from '../../style/motion';
import { genCollapseMotion, zoomIn } from '../../style/motion';
import type { AliasToken, FullToken, GenerateStyle } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import { resetComponent } from '../../style';
Expand Down Expand Up @@ -539,6 +539,7 @@ export default genComponentStyleHook('Form', (token, { rootPrefixCls }) => {
genHorizontalStyle(formToken),
genInlineStyle(formToken),
genVerticalStyle(formToken),
genCollapseMotion(formToken),
zoomIn,
];
});
4 changes: 2 additions & 2 deletions components/menu/__tests__/index.test.js
Expand Up @@ -14,7 +14,7 @@ import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render } from '../../../tests/utils';
import Layout from '../../layout';
import Tooltip from '../../tooltip';
import collapseMotion from '../../_util/motion';
import initCollapseMotion from '../../_util/motion';
import { noop } from '../../_util/warning';

globalThis.IS_REACT_ACT_ENVIRONMENT = true;
Expand Down Expand Up @@ -522,7 +522,7 @@ describe('Menu', () => {

it('inline menu collapseMotion should be triggered', async () => {
const cloneMotion = {
...collapseMotion,
...initCollapseMotion(),
motionDeadline: 1,
};

Expand Down
4 changes: 2 additions & 2 deletions components/menu/index.tsx
Expand Up @@ -9,7 +9,7 @@ import { forwardRef } from 'react';
import { ConfigContext } from '../config-provider';
import type { SiderContextProps } from '../layout/Sider';
import { SiderContext } from '../layout/Sider';
import collapseMotion from '../_util/motion';
import initCollapseMotion from '../_util/motion';
import { cloneElement } from '../_util/reactNode';
import warning from '../_util/warning';
import type { ItemType } from './hooks/useItems';
Expand Down Expand Up @@ -122,7 +122,7 @@ const InternalMenu = forwardRef<MenuRef, InternalMenuProps>((props, ref) => {

const defaultMotions = {
horizontal: { motionName: `${rootPrefixCls}-slide-up` },
inline: collapseMotion,
inline: initCollapseMotion(rootPrefixCls),
other: { motionName: `${rootPrefixCls}-zoom-big` },
};

Expand Down
4 changes: 4 additions & 0 deletions components/menu/style/index.tsx
@@ -1,4 +1,5 @@
import { TinyColor } from '@ctrl/tinycolor';
import { genCollapseMotion } from '../../style/motion';
import type { FullToken, GenerateStyle, UseComponentStyleResult } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
import getHorizontalStyle from './horizontal';
Expand Down Expand Up @@ -487,6 +488,9 @@ export default (prefixCls: string, injectStyle: boolean): UseComponentStyleResul

// RTL
getRTLStyle(menuToken),

// Motion
genCollapseMotion(menuToken),
];
},
token => ({
Expand Down
24 changes: 24 additions & 0 deletions components/style/motion/collapse.tsx
@@ -0,0 +1,24 @@
import type { AliasToken, GenerateStyle } from '../../theme';
import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook';

const genCollapseMotion: GenerateStyle<TokenWithCommonCls<AliasToken>> = token => ({
[token.componentCls]: {
// For common/openAnimation
[`${token.antCls}-motion-collapse-legacy`]: {
overflow: 'hidden',

'&-active': {
transition: `height ${token.motionDurationMid} ${token.motionEaseInOut},
opacity ${token.motionDurationMid} ${token.motionEaseInOut} !important`,
},
},

[`${token.antCls}-motion-collapse`]: {
overflow: 'hidden',
transition: `height ${token.motionDurationMid} ${token.motionEaseInOut},
opacity ${token.motionDurationMid} ${token.motionEaseInOut} !important`,
},
},
});

export default genCollapseMotion;
2 changes: 2 additions & 0 deletions components/style/motion/index.ts
Expand Up @@ -36,6 +36,7 @@ import {
zoomUpIn,
zoomUpOut,
} from './zoom';
import genCollapseMotion from './collapse';

export {
initSlideMotion,
Expand Down Expand Up @@ -72,4 +73,5 @@ export {
moveUpIn,
moveUpOut,
initMoveMotion,
genCollapseMotion,
};
15 changes: 10 additions & 5 deletions components/tree/Tree.tsx
Expand Up @@ -5,7 +5,7 @@ import RcTree, { TreeNode } from 'rc-tree';
import type { DataNode, Key } from 'rc-tree/lib/interface';
import * as React from 'react';
import { ConfigContext } from '../config-provider';
import collapseMotion from '../_util/motion';
import initCollapseMotion from '../_util/motion';
import DirectoryTree from './DirectoryTree';
import dropIndicatorRender from './utils/dropIndicator';
import renderSwitcherIcon from './utils/iconUtil';
Expand Down Expand Up @@ -175,10 +175,19 @@ const Tree = React.forwardRef<RcTree, TreeProps>((props, ref) => {
checkable,
selectable,
draggable,
motion: customMotion,
} = props;
const prefixCls = getPrefixCls('tree', customizePrefixCls);
const rootPrefixCls = getPrefixCls();

const motion = customMotion ?? {
...initCollapseMotion(rootPrefixCls),
motionAppear: false,
};

const newProps = {
...props,
motion,
showLine: Boolean(showLine),
dropIndicatorRender,
};
Expand Down Expand Up @@ -249,10 +258,6 @@ Tree.defaultProps = {
checkable: false,
selectable: true,
showIcon: false,
motion: {
...collapseMotion,
motionAppear: false,
},
blockNode: false,
};

Expand Down
3 changes: 2 additions & 1 deletion components/tree/style/index.tsx
@@ -1,6 +1,6 @@
// deps-lint-skip-all
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import { Keyframes } from '@ant-design/cssinjs';
import { genCollapseMotion } from '../../style/motion';
import { getStyle as getCheckboxStyle } from '../../checkbox/style';
import type { DerivativeToken } from '../../theme';
import { genComponentStyleHook, mergeToken } from '../../theme';
Expand Down Expand Up @@ -477,4 +477,5 @@ export default genComponentStyleHook('Tree', (token, { prefixCls }) => [
[token.componentCls]: getCheckboxStyle(`${prefixCls}-checkbox`, token),
},
genTreeStyle(prefixCls, token),
genCollapseMotion(token),
]);
24 changes: 15 additions & 9 deletions components/upload/UploadList/index.tsx
Expand Up @@ -6,24 +6,17 @@ import classNames from 'classnames';
import type { CSSMotionListProps } from 'rc-motion';
import CSSMotion, { CSSMotionList } from 'rc-motion';
import * as React from 'react';
import { useMemo } from 'react';
import type { ButtonProps } from '../../button';
import Button from '../../button';
import { ConfigContext } from '../../config-provider';
import useForceUpdate from '../../_util/hooks/useForceUpdate';
import collapseMotion from '../../_util/motion';
import initCollapseMotion from '../../_util/motion';
import { cloneElement, isValidElement } from '../../_util/reactNode';
import type { InternalUploadFile, UploadFile, UploadListProps, UploadListType } from '../interface';
import { isImageUrl, previewImage } from '../utils';
import ListItem from './ListItem';

const listItemMotion: Partial<CSSMotionListProps> = {
...collapseMotion,
};

delete listItemMotion.onAppearEnd;
delete listItemMotion.onEnterEnd;
delete listItemMotion.onLeaveEnd;

const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProps> = (
{
listType,
Expand Down Expand Up @@ -163,6 +156,7 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp

// ============================= Render =============================
const prefixCls = getPrefixCls('upload', customizePrefixCls);
const rootPrefixCls = getPrefixCls();

const listClassNames = classNames({
[`${prefixCls}-list`]: true,
Expand All @@ -187,6 +181,18 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
motionAppear,
};

const listItemMotion: Partial<CSSMotionListProps> = useMemo(() => {
const motion = {
...initCollapseMotion(rootPrefixCls),
};

delete motion.onAppearEnd;
delete motion.onEnterEnd;
delete motion.onLeaveEnd;

return motion;
}, [rootPrefixCls]);

if (listType !== 'picture-card') {
motionConfig = {
...listItemMotion,
Expand Down
2 changes: 2 additions & 0 deletions components/upload/style/index.tsx
Expand Up @@ -6,6 +6,7 @@ import genMotionStyle from './motion';
import { genPictureCardStyle, genPictureStyle } from './picture';
import genRtlStyle from './rtl';
import { resetComponent } from '../../style';
import { genCollapseMotion } from '../../style/motion';

export interface ComponentToken {}

Expand Down Expand Up @@ -60,5 +61,6 @@ export default genComponentStyleHook('Upload', token => {
genListStyle(uploadToken),
genMotionStyle(uploadToken),
genRtlStyle(uploadToken),
genCollapseMotion(uploadToken),
];
});