Skip to content

Commit 0ee0e2e

Browse files
zombieJvouis
authored andcommitted
fix: Standalone Badge motion style (ant-design#28240)
* fix: badge motion style * chore: Clean up related code * test: Update test case
1 parent 6351885 commit 0ee0e2e

File tree

5 files changed

+101
-33
lines changed

5 files changed

+101
-33
lines changed

components/badge/ScrollNumber.tsx

+12-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from 'react';
2+
import { useState } from 'react';
23
import classNames from 'classnames';
34
import { ConfigContext } from '../config-provider';
45
import { cloneElement } from '../_util/reactNode';
@@ -63,10 +64,10 @@ const ScrollNumber: React.FC<ScrollNumberProps> = ({
6364
onAnimated = () => {},
6465
...restProps
6566
}) => {
66-
const [animateStarted, setAnimateStarted] = React.useState(true);
67-
const [count, setCount] = React.useState(customizeCount);
68-
const [prevCount, setPrevCount] = React.useState(customizeCount);
69-
const [lastCount, setLastCount] = React.useState(customizeCount);
67+
const [animateStarted, setAnimateStarted] = useState(true);
68+
const [count, setCount] = useState(customizeCount);
69+
const [prevCount, setPrevCount] = useState(customizeCount);
70+
const [lastCount, setLastCount] = useState(customizeCount);
7071
const { getPrefixCls } = React.useContext(ConfigContext);
7172
const prefixCls = getPrefixCls('scroll-number', customizePrefixCls);
7273

@@ -154,15 +155,12 @@ const ScrollNumber: React.FC<ScrollNumberProps> = ({
154155
);
155156
};
156157

157-
const numberNodeRef = React.useRef<React.ReactNode>(null);
158-
if (show) {
159-
numberNodeRef.current =
160-
count && Number(count) % 1 === 0
161-
? getNumberArray(count)
162-
.map((num, i) => renderCurrentNumber(num, i))
163-
.reverse()
164-
: count;
165-
}
158+
const numberNode =
159+
count && Number(count) % 1 === 0
160+
? getNumberArray(count)
161+
.map((num, i) => renderCurrentNumber(num, i))
162+
.reverse()
163+
: count;
166164

167165
// allow specify the border
168166
// mock border-color by box-shadow for compatible with old usage:
@@ -178,7 +176,7 @@ const ScrollNumber: React.FC<ScrollNumberProps> = ({
178176
className: classNames(`${prefixCls}-custom-component`, oriProps?.className),
179177
}));
180178
}
181-
return React.createElement(component as any, newProps, numberNodeRef.current);
179+
return React.createElement(component as any, newProps, numberNode);
182180
};
183181

184182
export default ScrollNumber;

components/badge/__tests__/__snapshots__/demo.test.js.snap

+18
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,24 @@ exports[`renders ./components/badge/demo/no-wrapper.md correctly 1`] = `
994994
<div
995995
class="ant-space ant-space-horizontal ant-space-align-center"
996996
>
997+
<div
998+
class="ant-space-item"
999+
style="margin-right:8px"
1000+
>
1001+
<button
1002+
aria-checked="true"
1003+
class="ant-switch ant-switch-checked"
1004+
role="switch"
1005+
type="button"
1006+
>
1007+
<div
1008+
class="ant-switch-handle"
1009+
/>
1010+
<span
1011+
class="ant-switch-inner"
1012+
/>
1013+
</button>
1014+
</div>
9971015
<div
9981016
class="ant-space-item"
9991017
style="margin-right:8px"

components/badge/demo/no-wrapper.md

+23-9
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,29 @@ title:
1616
Used in standalone when children is empty.
1717

1818
```jsx
19-
import { Badge, Space } from 'antd';
20-
21-
const Demo = () => (
22-
<Space>
23-
<Badge count={25} />
24-
<Badge count={4} className="site-badge-count-4" />
25-
<Badge className="site-badge-count-109" count={109} style={{ backgroundColor: '#52c41a' }} />
26-
</Space>
27-
);
19+
import { Badge, Space, Switch } from 'antd';
20+
21+
const Demo = () => {
22+
const [show, setShow] = React.useState(true);
23+
24+
return (
25+
<Space>
26+
<Switch
27+
checked={show}
28+
onChange={() => {
29+
setShow(!show);
30+
}}
31+
/>
32+
<Badge count={show ? 25 : 0} />
33+
<Badge count={show ? 4 : 0} className="site-badge-count-4" />
34+
<Badge
35+
className="site-badge-count-109"
36+
count={show ? 109 : 0}
37+
style={{ backgroundColor: '#52c41a' }}
38+
/>
39+
</Space>
40+
);
41+
};
2842

2943
ReactDOM.render(<Demo />, mountNode);
3044
```

components/badge/index.tsx

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from 'react';
2+
import { useMemo, useRef } from 'react';
23
import CSSMotion from 'rc-motion';
34
import classNames from 'classnames';
45
import ScrollNumber from './ScrollNumber';
@@ -68,21 +69,28 @@ const Badge: CompoundedComponent = ({
6869

6970
const showAsDot = (dot && !isZero) || hasStatus;
7071

71-
const displayCount = showAsDot ? '' : numberedDisplayCount;
72+
const mergedCount = showAsDot ? '' : numberedDisplayCount;
7273

73-
const isHidden = React.useMemo(() => {
74-
const isEmpty = displayCount === null || displayCount === undefined || displayCount === '';
74+
const isHidden = useMemo(() => {
75+
const isEmpty = mergedCount === null || mergedCount === undefined || mergedCount === '';
7576
return (isEmpty || (isZero && !showZero)) && !showAsDot;
76-
}, [displayCount, isZero, showZero, showAsDot]);
77+
}, [mergedCount, isZero, showZero, showAsDot]);
78+
79+
// We need cache count since remove motion should not change count display
80+
const displayCountRef = useRef(mergedCount);
81+
if (!isHidden) {
82+
displayCountRef.current = mergedCount;
83+
}
84+
const displayCount = displayCountRef.current;
7785

7886
// We will cache the dot status to avoid shaking on leaved motion
79-
const isDotRef = React.useRef(showAsDot);
87+
const isDotRef = useRef(showAsDot);
8088
if (!isHidden) {
8189
isDotRef.current = showAsDot;
8290
}
8391

8492
// =============================== Styles ===============================
85-
const mergedStyle = React.useMemo<React.CSSProperties>(() => {
93+
const mergedStyle = useMemo<React.CSSProperties>(() => {
8694
if (!offset) {
8795
return { ...style };
8896
}
@@ -173,7 +181,7 @@ const Badge: CompoundedComponent = ({
173181
[`${prefixCls}-count`]: !isDot,
174182
[`${prefixCls}-count-sm`]: size === 'small',
175183
[`${prefixCls}-multiple-words`]:
176-
!isDot && count && count.toString && count.toString().length > 1,
184+
!isDot && displayCount && displayCount?.toString().length > 1,
177185
[`${prefixCls}-status-${status}`]: !!status,
178186
[`${prefixCls}-status-${color}`]: isPresetColor(color),
179187
});

components/badge/style/index.less

+33-3
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,25 @@
124124

125125
&-zoom-appear,
126126
&-zoom-enter {
127-
animation: antZoomBadgeIn 0.3s @ease-out-back;
127+
animation: antZoomBadgeIn @animation-duration-slow @ease-out-back;
128128
animation-fill-mode: both;
129129
}
130130

131131
&-zoom-leave {
132-
animation: antZoomBadgeOut 0.3s @ease-in-back;
132+
animation: antZoomBadgeOut @animation-duration-slow @ease-in-back;
133133
animation-fill-mode: both;
134134
}
135135

136136
&-not-a-wrapper {
137+
.@{badge-prefix-cls}-zoom-appear,
138+
.@{badge-prefix-cls}-zoom-enter {
139+
animation: antNoWrapperZoomBadgeIn @animation-duration-slow @ease-out-back;
140+
}
141+
142+
.@{badge-prefix-cls}-zoom-leave {
143+
animation: antNoWrapperZoomBadgeOut @animation-duration-slow @ease-in-back;
144+
}
145+
137146
&:not(.@{badge-prefix-cls}-status) {
138147
vertical-align: middle;
139148
}
@@ -142,6 +151,7 @@
142151
position: relative;
143152
top: auto;
144153
display: block;
154+
transform-origin: 50% 50%;
145155
}
146156

147157
.@{badge-prefix-cls}-count {
@@ -166,7 +176,7 @@
166176
&-only {
167177
display: inline-block;
168178
height: @badge-height;
169-
transition: all 0.3s @ease-in-out;
179+
transition: all @animation-duration-slow @ease-in-out;
170180
> p.@{number-prefix-cls}-only-unit {
171181
height: @badge-height;
172182
margin: 0;
@@ -198,5 +208,25 @@
198208
}
199209
}
200210

211+
@keyframes antNoWrapperZoomBadgeIn {
212+
0% {
213+
transform: scale(0);
214+
opacity: 0;
215+
}
216+
100% {
217+
transform: scale(1);
218+
}
219+
}
220+
221+
@keyframes antNoWrapperZoomBadgeOut {
222+
0% {
223+
transform: scale(1);
224+
}
225+
100% {
226+
transform: scale(0);
227+
opacity: 0;
228+
}
229+
}
230+
201231
@import './ribbon';
202232
@import './rtl';

0 commit comments

Comments
 (0)