diff --git a/src/components/reply-modal/__tests__/reply-modal.test.tsx b/src/components/reply-modal/__tests__/reply-modal.test.tsx index 7162b7ae..7f3f514b 100644 --- a/src/components/reply-modal/__tests__/reply-modal.test.tsx +++ b/src/components/reply-modal/__tests__/reply-modal.test.tsx @@ -39,6 +39,7 @@ const testState = vi.hoisted(() => ({ setAccountMock: vi.fn(), setPublishReplyOptionsMock: vi.fn(), springStartMock: vi.fn(), + useSpringMock: vi.fn(), communities: { 'music-posting.eth': { address: 'music-posting.eth', @@ -182,7 +183,7 @@ vi.mock('@react-spring/web', async () => { animated: { div: React.forwardRef(({ style, ...props }: any, ref) => React.createElement('div', { ...props, ref, style: normalizeStyle(style) })), }, - useSpring: () => [ + useSpring: testState.useSpringMock.mockImplementation(() => [ { left: { get: () => 120 }, top: { get: () => 80 }, @@ -190,7 +191,7 @@ vi.mock('@react-spring/web', async () => { { start: testState.springStartMock, }, - ], + ]), }; }); @@ -286,6 +287,16 @@ describe('ReplyModal', () => { testState.setAccountMock.mockReset(); testState.setPublishReplyOptionsMock.mockReset(); testState.springStartMock.mockReset(); + testState.useSpringMock.mockReset(); + testState.useSpringMock.mockImplementation(() => [ + { + left: { get: () => 120 }, + top: { get: () => 80 }, + }, + { + start: testState.springStartMock, + }, + ]); testState.communities = { 'music-posting.eth': { address: 'music-posting.eth', @@ -459,4 +470,19 @@ describe('ReplyModal', () => { expect(modal?.style.transform).toBe(''); expect(modal?.style.touchAction).toBe('none'); }); + + it('initializes the drag spring once so typing rerenders do not recenter the modal', async () => { + await renderReplyModal('/mu/thread/post-1'); + + expect(testState.useSpringMock).toHaveBeenCalledWith(expect.any(Function), []); + + const [configFactory, deps] = testState.useSpringMock.mock.calls[0] as [() => Record, unknown[]]; + expect(deps).toEqual([]); + expect(configFactory()).toEqual({ + from: { + left: expect.any(Number), + top: expect.any(Number), + }, + }); + }); }); diff --git a/src/components/reply-modal/reply-modal.tsx b/src/components/reply-modal/reply-modal.tsx index 7b53b982..165f4e2e 100644 --- a/src/components/reply-modal/reply-modal.tsx +++ b/src/components/reply-modal/reply-modal.tsx @@ -111,10 +111,15 @@ const ReplyModal = ({ closeModal, showReplyModal, parentCid, parentNumber, threa const nodeRef = useRef(null); const isMobile = useIsMobile(); - const [{ left, top }, api] = useSpring(() => ({ - left: Math.round(window.innerWidth / 2 - 150), - top: Math.round(window.innerHeight / 2 - 200), - })); + const [{ left, top }, api] = useSpring( + () => ({ + from: { + left: Math.round(window.innerWidth / 2 - 150), + top: Math.round(window.innerHeight / 2 - 200), + }, + }), + [], + ); const bind = useDrag( ({ active, event, offset: [ox, oy] }) => {