Skip to content

fix(dashboard): UX/a11y/perf/correctness pass#1248

Merged
iammukeshm merged 1 commit into
developfrom
chore/dashboard-ux-a11y-perf-pass
May 27, 2026
Merged

fix(dashboard): UX/a11y/perf/correctness pass#1248
iammukeshm merged 1 commit into
developfrom
chore/dashboard-ux-a11y-perf-pass

Conversation

@iammukeshm
Copy link
Copy Markdown
Member

What

A focused UX / accessibility / performance / correctness pass over the tenant dashboard (clients/dashboard), driven by a four-dimension audit. No backend or src/BuildingBlocks changes.

Why

The dashboard was already mature, so this targets the things lint can't catch: silent realtime bugs, invalid ARIA, contrast gaps, and a few dead-code / footgun spots.

Highlights

Functional bugs

  • 4 hub events subscribed but never wired in realtime-context.tsx (PresenceChanged, ChatMessagePinned, ChatMessageUnpinned, ChatChannelMemberRead) — live presence dots, pin/unpin, and read-receipts silently never updated. The backend broadcasts all four.
  • chat-search highlight: a /g RegExp.test() in a .map() drifted lastIndex and mis-wrapped matches.
  • user-detail: the staged-role reset was keyed on roles = data ?? [], so a background refetch could wipe unsaved edits — re-keyed on userId with a deterministic post-save clear.

Accessibility

  • Combobox: invalid role="option" inside a role="menu" and role="combobox" without aria-expanded/controls → valid menuitemradio; nested interactive clear button lifted to a sibling.
  • Accessible names: reaction chips, quick-react emoji, EntitySearch (every list page), collapsed sidebar items.
  • role="status"/sr-only on skeletons, role="progressbar" on upload bars, DialogTitle on the mobile nav Sheet, anchor-as-menuitem (asChild) for link menu items, h1→h2 heading hierarchy, chat status rows hidden from the role="log" region.
  • Placeholder contrast raised to AA (removed sub-AA alpha multipliers).

UX / correctness

  • Retired hardcoded text-white/bg-white/bg-black via a new theme-independent --color-overlay-foreground / --color-overlay token + semantic foregrounds.
  • Profile form: surfaces load errors, gates inputs while loading, seeds once (no clobber on refetch).
  • Wired the previously no-op "Reduce motion" toggle through the theme provider (persisted + .reduce-motion class + CSS); fixed the notifications "open bell" selector.

Cleanup

  • Removed 3 void X dead-import hacks + a dead effect, swapped a full-page window.location reload for router navigate(), and resolved all 10 exhaustive-deps lint warnings via useMemo.

Deliberately deferred

  • Global token-syntax normalization and products.tsx primitive de-dup (render identically — churn without a defect).
  • Server-side pagination for roles/groups at scale and a batched presence endpoint (need API changes).
  • The 12 remaining lint warnings are all pre-existing react-refresh/only-export-components (dev-only HMR ergonomics).

Verification

  • tsc -b clean
  • eslint 0 errors, 12 warnings (down from 22)
  • vite build succeeds
  • Playwright 121/121 pass (updated 3 identity empty-state heading-level assertions to match the corrected h2)

Note (golden rule #10): the now-working reduce-motion toggle and live-presence fix are user-facing — a changelog entry in the separate docs repo should accompany this before release.

🤖 Generated with Claude Code

Audit-driven fixes across the tenant dashboard. No backend or
BuildingBlocks changes; all verified (tsc clean, eslint 22->12 warnings,
build OK, Playwright 121/121).

Functional bugs:
- realtime-context: wire 4 subscribed-but-unregistered hub events
  (PresenceChanged, ChatMessagePinned/Unpinned, ChatChannelMemberRead) so
  live presence/pin/read-receipt updates actually arrive.
- chat-search: drop a stateful /g RegExp.test() whose lastIndex drifted
  and mis-highlighted matches.
- user-detail: key the staged-roles reset on userId (not the data array)
  so a background refetch can no longer wipe unsaved edits.

Accessibility:
- Combobox: replace invalid role="option" in a menu / role="combobox"
  without aria-expanded with valid menuitemradio; lift the nested
  interactive clear button out to a sibling.
- accessible names for reaction chips, quick-react emoji, EntitySearch,
  collapsed sidebar nav items.
- role="status"/sr-only on skeletons, role="progressbar" on upload bars,
  DialogTitle on the mobile nav Sheet, anchor-as-menuitem for link items,
  h1->h2 heading hierarchy, status rows hidden from the chat log region.
- raise placeholder contrast to AA (drop sub-AA alpha multipliers).

UX/correctness:
- retire hardcoded text-white/bg-white/bg-black via a new
  --color-overlay-foreground/--color-overlay token + semantic foregrounds.
- profile form: surface load errors, gate inputs while loading, seed once.
- wire the previously no-op "Reduce motion" toggle through the theme
  provider; fix the notifications "open bell" selector.

Cleanup:
- remove 3 `void X` dead-import hacks + a dead effect, swap a full-page
  window.location reload for router navigate(), and resolve all 10
  exhaustive-deps lint warnings via useMemo.

Tests: update 3 identity empty-state heading-level assertions to match the
corrected h2 hierarchy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@iammukeshm iammukeshm merged commit c994b14 into develop May 27, 2026
2 checks passed
@iammukeshm iammukeshm deleted the chore/dashboard-ux-a11y-perf-pass branch May 27, 2026 06:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant