Skip to content

Fix Transaction Filter Sidebar: i18n crash, a11y landmarks, label sizing - #1409

Merged
emdevelopa merged 2 commits into
emdevelopa:mainfrom
chinelo002:feat/transaction-filter-sidebar-ux-scott
Aug 28, 2026
Merged

Fix Transaction Filter Sidebar: i18n crash, a11y landmarks, label sizing#1409
emdevelopa merged 2 commits into
emdevelopa:mainfrom
chinelo002:feat/transaction-filter-sidebar-ux-scott

Conversation

@chinelo002

Copy link
Copy Markdown
Contributor

Summary

Investigated the Transaction Filter Sidebar (TransactionFilterSidebar.tsx) for the 4 assigned UX issues and found a genuine, severe rendering bug underlying all of them, plus real a11y and typography gaps.

The core bug (closes #1350 — incorrect state rendering)

The component was migrated to next-intl (useTranslations("transactionFilters")) at some point, but:

  1. The transactionFilters namespace was never added to any of the 3 locale files (messages/en.json, es.json, pt.json).
  2. The component's own test file never wrapped renders in a NextIntlClientProvider.

Since NextIntlClientProvider in layout.tsx loads messages via getMessages() (the full locale file), and that file has no transactionFilters key, every render of this component in the running app throws/falls back to raw message keys — this isn't a test-only issue, it's a production rendering bug. Confirmed via the existing test suite: 0/80 tests passed before this fix (all failed with useTranslations context/missing-message errors), 80/80 pass after.

Fix: added the full transactionFilters message tree (title, search/status/asset/date-range labels, sync-state hints, aria labels, pluralized "Clear all N active filters") to all 3 locale files, and fixed the test file to render through a NextIntlClientProvider wrapping the real English messages — matching how the app actually renders this component.

Accessibility (closes #1348)

  • The mobile drawer's aria-label="Filter sidebar" was hardcoded English, never translated for es/pt locales. Now reads from the same landmarkLabel translation key as the desktop panel.
  • Unified the desktop role="complementary" landmark and mobile role="dialog" to share one purpose-built landmarkLabel ("Transaction filters") distinct from the visible heading ("Filters") — a screen reader user navigating by landmark now gets a more specific label than the generic on-screen heading text.
  • SyncSpinner had a redundant inner sr-only span duplicating the same text already set via the parent's aria-label — screen readers use aria-label once set, so the inner span was dead weight, and it caused the visible "Clearing…" text next to the spinner to be announced twice. Removed the redundant node.
  • Fixed a test helper bug (container.querySelector('#' + hintId)) that silently broke on useId()'s colon-containing ids — switched to getElementById, which needs no escaping.

Typography (closes #1349)

Bumped the 4 primary field-group labels (Search, Status, Asset filter, Date range) from 10px to 11px — the smallest comfortably-readable size for uppercase-tracked label text. Scoped narrowly to this component's primary labels rather than the sub-10px pattern used elsewhere in the codebase (35+ other components share that convention; a codebase-wide type-scale pass is a separate, much larger change and out of scope here).

UI revamp (closes #1351)

The i18n fix above is the substantive UI-facing change: previously the component's actual runtime behavior (crash/fallback) never matched what the polished JSX and test file describe. With working translations, the existing careful UX (optimistic filter state, staggered animations, sync indicators, dual-control-safe pending states) now actually renders as designed.

Test plan

  • npx vitest run src/components/TransactionFilterSidebar.test.tsx — 80/80 passing (was 0/80 before this fix)
  • npx tsc --noEmit — zero new errors (pre-existing unrelated failures in OnboardingProgressTracker.tsx/PortfolioChartWidget.tsx confirmed via git diff upstream/main to predate this change)
  • npx eslint on both touched files — zero errors, only pre-existing warnings unrelated to this diff
  • All 3 locale JSON files validated as parseable with identical key sets

Closes #1348
Closes #1349
Closes #1350
Closes #1351

@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown

@chinelo002 is attempting to deploy a commit to the Emmanuel's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Aug 28, 2026

Copy link
Copy Markdown

@chinelo002 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

The new transactionFilters i18n keys added in the previous commit used
plain ASCII ("Busqueda", "descripcion", "Ate") while the rest of
es.json/pt.json consistently uses accented characters — fixed to match
(búsqueda/descripción, transações/até).

Also removes an unused FilterSyncIndicator import — dead since an
earlier commit (883297a) replaced it with the component's own
SyncSpinner, flagged by eslint's no-unused-vars.
@emdevelopa
emdevelopa merged commit 30b0c1a into emdevelopa:main Aug 28, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants