diff --git a/components/_util/wave.tsx b/components/_util/wave/index.tsx similarity index 95% rename from components/_util/wave.tsx rename to components/_util/wave/index.tsx index 18a918ae44..9a19afa651 100644 --- a/components/_util/wave.tsx +++ b/components/_util/wave/index.tsx @@ -2,10 +2,11 @@ import { updateCSS } from 'rc-util/lib/Dom/dynamicCSS'; import { composeRef, supportRef } from 'rc-util/lib/ref'; import * as React from 'react'; import { forwardRef } from 'react'; -import type { ConfigConsumerProps, CSPConfig } from '../config-provider'; -import { ConfigConsumer, ConfigContext } from '../config-provider'; -import raf from './raf'; -import { cloneElement } from './reactNode'; +import type { ConfigConsumerProps, CSPConfig } from '../../config-provider'; +import { ConfigConsumer, ConfigContext } from '../../config-provider'; +import raf from '../raf'; +import { cloneElement } from '../reactNode'; +import useStyle from './style'; let styleForPseudo: HTMLStyleElement | null; @@ -228,8 +229,9 @@ class InternalWave extends React.Component { } } -const Wave = forwardRef((props, ref) => ( - -)); +const Wave = forwardRef((props, ref) => { + useStyle(); + return ; +}); export default Wave; diff --git a/components/_util/wave/style.ts b/components/_util/wave/style.ts new file mode 100644 index 0000000000..352a7dfe9a --- /dev/null +++ b/components/_util/wave/style.ts @@ -0,0 +1,80 @@ +import { Keyframes, useStyleRegister } from '@ant-design/cssinjs'; +import { useContext } from 'react'; +import { ConfigContext } from '../../config-provider'; +import type { AliasToken, GenerateStyle, UseComponentStyleResult } from '../../theme'; +import { useToken } from '../../theme'; + +interface WaveToken extends AliasToken { + hashId: string; + clickAnimatingNode: string; + clickAnimatingTrue: string; + clickAnimatingWithoutExtraNodeTrue: string; + clickAnimatingWithoutExtraNodeTrueAfter: string; +} + +const genWaveStyle: GenerateStyle = token => { + const waveEffect = new Keyframes('waveEffect', { + '100%': { + boxShadow: `0 0 0 6px ${token.colorPrimary}`, + }, + }); + + const fadeEffect = new Keyframes('fadeEffect', { + '100%': { + opacity: 0, + }, + }); + + return [ + { + [`${token.clickAnimatingWithoutExtraNodeTrue}, + ${token.clickAnimatingTrue}`]: { + position: 'relative', + }, + [`${token.clickAnimatingWithoutExtraNodeTrueAfter}, + & ${token.clickAnimatingNode}`]: { + position: 'absolute', + top: 0, + insetInlineStart: 0, + insetInlineEnd: 0, + bottom: 0, + display: 'block', + borderRadius: 'inherit', + boxShadow: `0 0 0 0 ${token.colorPrimary}`, + opacity: 0.2, + animation: `${fadeEffect.getName(token.hashId)} 2s ${ + token.motionEaseOutCirc + }, ${waveEffect.getName(token.hashId)} 0.4s ${token.motionEaseOutCirc}`, + animationFillMode: 'forwards', + content: '""', + pointerEvents: 'none', + }, + }, + waveEffect, + fadeEffect, + ]; +}; + +export default (): UseComponentStyleResult => { + const [theme, token, hashId] = useToken(); + const { getPrefixCls } = useContext(ConfigContext); + const rootPrefixCls = getPrefixCls(); + + const clickAnimatingTrue = `[${rootPrefixCls}-click-animating='true']`; + const clickAnimatingWithoutExtraNodeTrue = `[${rootPrefixCls}-click-animating-without-extra-node='true']`; + const clickAnimatingNode = `.${rootPrefixCls}-click-animating-node`; + + const waveToken: WaveToken = { + ...token, + hashId, + clickAnimatingNode, + clickAnimatingTrue, + clickAnimatingWithoutExtraNodeTrue, + clickAnimatingWithoutExtraNodeTrueAfter: `${clickAnimatingWithoutExtraNodeTrue}::after`, + }; + + return [ + useStyleRegister({ theme, token, hashId, path: ['wave'] }, () => [genWaveStyle(waveToken)]), + hashId, + ]; +};