Skip to content

Commit adf0461

Browse files
luo3housevagusX
andauthored
fix: trigger "onMotionEnd" when element is hidden (#161)
* fix: end animation when element is hidden * chore: fix test * chore: add test * Update tests/index.test.tsx Co-authored-by: vagusX <vagusX@users.noreply.github.com>
1 parent 3cc5ac5 commit adf0461

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

src/MotionThumb.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export default function MotionThumb(props: MotionThumbInterface) {
5555
`.${prefixCls}-item`,
5656
)[index];
5757

58-
return ele;
58+
return ele?.offsetParent && ele;
5959
};
6060

6161
const [prevStyle, setPrevStyle] = React.useState<ThumbReact>(null);

tests/index.test.tsx

+47-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import { act, fireEvent, render } from '@testing-library/react';
12
import * as React from 'react';
2-
import { render, act, fireEvent } from '@testing-library/react';
33
import Segmented from '../src';
44

55
jest.mock('rc-motion/lib/util/motion', () => {
@@ -231,6 +231,12 @@ describe('rc-segmented', () => {
231231
});
232232

233233
it('render segmented with controlled mode', () => {
234+
const offsetParentSpy = jest
235+
.spyOn(HTMLElement.prototype, 'offsetParent', 'get')
236+
.mockImplementation(() => {
237+
return container;
238+
});
239+
234240
const Demo = () => {
235241
const options = ['iOS', 'Android', 'Web3'];
236242

@@ -250,6 +256,7 @@ describe('rc-segmented', () => {
250256
);
251257
};
252258
const { container } = render(<Demo />);
259+
253260
fireEvent.click(container.querySelectorAll('.rc-segmented-item-input')[0]);
254261
expect(container.querySelector('.value')?.textContent).toBe('iOS');
255262

@@ -284,10 +291,17 @@ describe('rc-segmented', () => {
284291

285292
// invalid changes: Should not active any item to make sure it's single source of truth
286293
expect(container.querySelector('.rc-segmented-item-selected')).toBeFalsy();
294+
295+
offsetParentSpy.mockRestore();
287296
});
288297

289298
describe('render segmented with CSSMotion', () => {
290299
it('basic', () => {
300+
const offsetParentSpy = jest
301+
.spyOn(HTMLElement.prototype, 'offsetParent', 'get')
302+
.mockImplementation(() => {
303+
return container;
304+
});
291305
const handleValueChange = jest.fn();
292306
const { container, asFragment } = render(
293307
<Segmented
@@ -366,9 +380,16 @@ describe('rc-segmented', () => {
366380

367381
// thumb should disappear
368382
expect(container.querySelector('.rc-segmented-thumb')).toBeFalsy();
383+
384+
offsetParentSpy.mockRestore();
369385
});
370386

371387
it('quick switch', () => {
388+
const offsetParentSpy = jest
389+
.spyOn(HTMLElement.prototype, 'offsetParent', 'get')
390+
.mockImplementation(() => {
391+
return container;
392+
});
372393
const { container } = render(
373394
<Segmented
374395
options={['IOS', 'Android', 'Web3']}
@@ -403,6 +424,31 @@ describe('rc-segmented', () => {
403424
'--thumb-active-left': '0px',
404425
'--thumb-active-width': '62px',
405426
});
427+
428+
offsetParentSpy.mockRestore();
429+
});
430+
431+
it('stop animation early in hidden parent', () => {
432+
const offsetParentSpy = jest
433+
.spyOn(HTMLElement.prototype, 'offsetParent', 'get')
434+
.mockImplementation(() => null);
435+
const Demo = () => {
436+
const [value, setValue] = React.useState<string>('iOS');
437+
React.useEffect(() => setValue('Web3'), []);
438+
return <Segmented options={['iOS', 'Android', 'Web3']} value={value} />;
439+
};
440+
441+
const { container } = render(<Demo />);
442+
443+
// stop animation early and place "selected" class
444+
expect(container.querySelectorAll('.rc-segmented-item')[2]).toHaveClass(
445+
'rc-segmented-item-selected',
446+
);
447+
448+
// thumb should disappear
449+
expect(container.querySelector('.rc-segmented-thumb')).toBeFalsy();
450+
451+
offsetParentSpy.mockRestore();
406452
});
407453
});
408454

0 commit comments

Comments
 (0)