From b62c8203b717e198f7afe7f3ab964a938cf4535d Mon Sep 17 00:00:00 2001 From: cixzhang Date: Thu, 25 Jun 2026 18:36:17 +0000 Subject: [PATCH 1/5] fix(Pagination): make changeAction interruptible with optimistic page state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pagination's changeAction now runs in a transition and tracks the page optimistically, matching ToggleButton. The controls reflect the page being navigated to while the action is pending, and rapid prev/next clicks advance through pages (interrupting the in-flight transition) instead of being dropped by a re-entry guard. A synchronous handler that suspends also drives the pending state. Button's clickAction keeps its single-fire guard — a re-click there is a duplicate submit, not new intent — and now documents why, with a regression test asserting a fast double-click fires clickAction only once. --- .../pagination-interruptible-button-guard.md | 14 ++ packages/core/src/Button/Button.test.tsx | 40 +++-- packages/core/src/Button/Button.tsx | 8 + .../core/src/Pagination/Pagination.test.tsx | 151 ++++++++++++++++-- packages/core/src/Pagination/Pagination.tsx | 66 ++++---- 5 files changed, 226 insertions(+), 53 deletions(-) create mode 100644 .changeset/pagination-interruptible-button-guard.md diff --git a/.changeset/pagination-interruptible-button-guard.md b/.changeset/pagination-interruptible-button-guard.md new file mode 100644 index 000000000000..eaf1139f58ed --- /dev/null +++ b/.changeset/pagination-interruptible-button-guard.md @@ -0,0 +1,14 @@ +--- +'@astryxdesign/core': patch +--- + +[fix] Make `Pagination`'s `changeAction` interruptible with optimistic state. +Page changes now run inside a transition and track the target page +optimistically, so the controls (indicator, active page, prev/next enablement) +reflect the page being navigated to while the action is pending. Rapid prev/next +clicks now advance through pages instead of being dropped by a re-entry guard, +and a synchronous handler that suspends (e.g. a router navigation) also drives +the pending state — matching `ToggleButton`'s action behavior. `Button`'s +`clickAction` keeps its single-fire guard (a re-click is a duplicate submit, not +new intent) and now documents why. +@cixzhang diff --git a/packages/core/src/Button/Button.test.tsx b/packages/core/src/Button/Button.test.tsx index 98f3d8c960e5..85eb84eb74a5 100644 --- a/packages/core/src/Button/Button.test.tsx +++ b/packages/core/src/Button/Button.test.tsx @@ -10,7 +10,7 @@ */ import {describe, it, expect, vi} from 'vitest'; -import {render, screen} from '@testing-library/react'; +import {render, screen, fireEvent, act} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import {Button} from './Button'; import {Badge} from '../Badge/Badge'; @@ -228,11 +228,7 @@ describe('Button', () => { order.push('clickAction'); }); render( -