Answer every budget control in the same frame - #28
Conversation
Filtering, sorting, paging the period or clicking a chart rewrote the URL and refetched, and `keepPreviousData` held the old answer on screen, so a click looked like nothing happened until the round trip landed. Now the pressed control changes at once and the data it affects dims (`StaleRegion`: aria-busy immediately, opacity after 100 ms, so a fast answer never flickers) under one screen-reader status line. The direction tab, sort toggle, period arrows and range toggle prefetch their target after an 80 ms pointer rest, so the click swaps from cache. The search box owns its draft, so a keystroke re-renders the input alone. Recharts series paint their final state instead of tweening 1500 ms, and `getTransactions` runs its three database calls concurrently. A failure nothing on screen observes no longer toasts: a prefetch has no observer, and its Retry would invalidate a query no component reads.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Verification log, for anyone who wants the numbers rather than the claim. Run against the OrbStack dev stack, 144 seeded transactions over June–September 2026, CDP Same-frame feedback. Picking a category chip: the chip and the URL change in the next sampled frame while the previous 8 rows stay; Prefetch.
Search. Typing Chart motion. The pie's Prefetch failures stay silent, observed failures do not. With CDP Server. Gates. |
Summary
Every control on the Budget pages now answers in the same frame: the pressed control changes at once and the data it affects dims until the fresh answer replaces it (
StaleRegion—aria-busyimmediately, opacity after 100 ms, so a fast answer never flickers). Look first at the newapps/web/src/lib/budget/budget-queries.ts, which owns the transactions query options, the prefetchers andisStaleView, then at howtransactions.tsxthreads them. The direction tab, sort toggle, period arrows and range toggle prefetch their target after an 80 ms pointer rest, so the click swaps from cache. Server-side filtering is unchanged.Motivation
placeholderData: keepPreviousDataheld the previous answer on screen, so a filter, sort or period click looked like nothing happened for the whole round trip.getTransactionsawaited its three database calls in sequence when none depends on another.Drawbacks
onFocuswould fetch every control's target as focus passes through.QueryCache.onErrornow skips queries with no observer, so a failure whose component already unmounted is silent too.oxlint-disable-next-line sort-keysinbudget-queries.ts: alphabetical order putsgetNextPageParambeforequeryFn, and itslastPagethen infers asunknown.Prior art
<Link>targets on intent; these are search-param navigations, which it does not cover, henceuseHoverIntent.RandomSpinner) but not content about to be replaced; a spinner there was rejected, since spinners stay reserved for pressed controls./budget/recurringdoes) and rejected it: the list pages 50 rows at a time and the totals cover the whole filtered range.Notes
isAnimationActive={true}makes them differ);getTransactionstotals equal a direct SQL aggregate. Evidence in a comment below.apps/fumadocs: no page changes — no screen, route, environment variable, API shape or vocabulary moves.getTransactionskeeps its response shape, sointegrations/procedures.mdxstays as it is.changes_requestedon the first pass (prefetch failures toasted, the empty list escaped the dim,useSettledText.settledwent dead), all three fixed, re-judgedapprovedwith no findings.getTransactionssetsnextCursorto the extra row it popped and re-queries withskip: 1, so that row is never shown. It predates this branch and deserves its own change with a regression test.