refactor: collapse motion (#36597)

* chore: v5.0.0-experimental.5

* refactor: collapse motion
This commit is contained in:
MadCcc 2022-07-19 22:53:38 +08:00 committed by GitHub
parent 2449eaee5d
commit 357750e081
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 80 additions and 49 deletions

View File

@ -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,
@ -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];
@ -44,4 +44,4 @@ const getTransitionName = (rootPrefixCls: string, motion: string, transitionName
};
export { getTransitionName, getTransitionDirection };
export default collapseMotion;
export default initCollapseMotion;

View File

@ -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';
@ -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`
@ -107,7 +108,7 @@ const Collapse: CollapseInterface = props => {
hashId,
);
const openMotion: CSSMotionProps = {
...collapseMotion,
...initCollapseMotion(rootPrefixCls),
motionAppear: false,
leavedClassName: `${prefixCls}-content-hidden`,
};

View File

@ -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';
@ -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,
@ -266,6 +247,6 @@ export default genComponentStyleHook('Collapse', token => {
genBaseStyle(collapseToken),
genBorderlessStyle(collapseToken),
genArrowStyle(collapseToken),
genMotion(collapseToken),
genCollapseMotion(collapseToken),
];
});

View File

@ -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';
@ -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);
@ -71,6 +74,7 @@ export default function ErrorList({
return (
<CSSMotion
{...collapseMotion}
motionDeadline={collapseMotion.motionDeadline}
motionName={`${rootPrefixCls}-show-help`}
visible={!!fullKeyList.length}
@ -86,7 +90,7 @@ export default function ErrorList({
>
<CSSMotionList
keys={fullKeyList}
{...collapseMotion}
{...initCollapseMotion(rootPrefixCls)}
motionName={`${rootPrefixCls}-show-help-item`}
component={false}
>

View File

@ -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';
@ -539,6 +539,7 @@ export default genComponentStyleHook('Form', (token, { rootPrefixCls }) => {
genHorizontalStyle(formToken),
genInlineStyle(formToken),
genVerticalStyle(formToken),
genCollapseMotion(formToken),
zoomIn,
];
});

View File

@ -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;
@ -522,7 +522,7 @@ describe('Menu', () => {
it('inline menu collapseMotion should be triggered', async () => {
const cloneMotion = {
...collapseMotion,
...initCollapseMotion(),
motionDeadline: 1,
};

View File

@ -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';
@ -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` },
};

View File

@ -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';
@ -487,6 +488,9 @@ export default (prefixCls: string, injectStyle: boolean): UseComponentStyleResul
// RTL
getRTLStyle(menuToken),
// Motion
genCollapseMotion(menuToken),
];
},
token => ({

View File

@ -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;

View File

@ -36,6 +36,7 @@ import {
zoomUpIn,
zoomUpOut,
} from './zoom';
import genCollapseMotion from './collapse';
export {
initSlideMotion,
@ -72,4 +73,5 @@ export {
moveUpIn,
moveUpOut,
initMoveMotion,
genCollapseMotion,
};

View File

@ -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';
@ -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,
};
@ -249,10 +258,6 @@ Tree.defaultProps = {
checkable: false,
selectable: true,
showIcon: false,
motion: {
...collapseMotion,
motionAppear: false,
},
blockNode: false,
};

View File

@ -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';
@ -477,4 +477,5 @@ export default genComponentStyleHook('Tree', (token, { prefixCls }) => [
[token.componentCls]: getCheckboxStyle(`${prefixCls}-checkbox`, token),
},
genTreeStyle(prefixCls, token),
genCollapseMotion(token),
]);

View File

@ -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,
@ -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,
@ -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,

View File

@ -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 {}
@ -60,5 +61,6 @@ export default genComponentStyleHook('Upload', token => {
genListStyle(uploadToken),
genMotionStyle(uploadToken),
genRtlStyle(uploadToken),
genCollapseMotion(uploadToken),
];
});