Repository navigation
v0.329.0 — UI review release D: shared async states + clipped-header fix
Container
ghcr.io/budgets-au/budgets:0.329.0
ghcr.io/budgets-au/budgets:latest
Last of four UI-consistency releases — shared async states — plus the fix for the clipped table header reported against 0.328.
Fixed
- Report table headers were clipped by the filter bar. On
/reportstwo filter bars now stack (the date-range + report picker row, then the active report's own toggle bar), so real vertical chrome above a table is ~200px where--table-chromereserved 180. The page scrolled by the difference, sliding the table'ssticky top-0header up underneath the sticky filter bar — and because both sat atz-10, the bar won and cut the month labels in half. Thez-30corner cell escaped, which is why "Category" stayed readable while "Jan '26" didn't./reportsdeclares its own--table-chrome: 15rem, which is what the token was added for. The page no longer scrolls, so the overlap doesn't arise.- The z-ladder is re-cut so it degrades gracefully if a page ever does scroll: header corner
z-40, rest of thetheadz-20(clear of the bar'sz-10), sticky first-column body cellsz-10. Documented as an explicit contract inui/table-scroller.tsxso the next table to adopt it doesn't rediscover this. accounts-cashflow-report's header cells were also semi-transparent — now opaque, same reason the frozen column needed it in 0.328.
- Failed report fetches no longer masquerade as an empty ledger. Cashflow and Category checked
!databut nevererror, so a failed GET fell through to "No data for this period." — telling you your ledger is empty when the request had actually failed. Both now checkerrorfirst and offer a retry.
Added
ui/state-message.tsx—LoadingState,EmptyState,ErrorState.LoadingStatereplaces 24 hand-writtenLoading…paragraphs across 23 files, which had drifted across nine padding combinations and two type sizes. Carriesaria-live="polite"/aria-busyso screen readers announce the transition rather than sitting on a silently stale region.EmptyStatestandardises the container and typography but not the copy. "No transactions in this category" and "No accounts yet" answer different questions — one says your filter matched nothing, the other says you haven't created anything. An optionalactionslot covers the second case.ErrorStateis new behaviour, not a consolidation: read failures were silent almost everywhere. Toasts remain the pattern for write failures (99 call sites, user-initiated). A read failure needs a persistent marker in the region that failed, with a retry.- Deliberately not skeletons — these sit above tables and charts whose height isn't known until the fetch lands, so a shimmer block of the wrong size reads worse than a line of text.
Verify
- tsc clean,
pnpm buildclean, 733/743 unit. - 42 e2e: pages-smoke 12/12, reports-tabs 15/15, monkey-goals 15/15.
Upgrade
Pull ghcr.io/budgets-au/budgets:0.329.0 and roll. No migrations. The visible change is that report table headers stay fully readable while you scroll, and a failed report fetch now says so instead of claiming you have no data.