refactor(ui): rebuild Tabs primitive on Button tabs and adopt across admin pages#183
Draft
DavidBabinec wants to merge 1 commit into
Draft
refactor(ui): rebuild Tabs primitive on Button tabs and adopt across admin pages#183DavidBabinec wants to merge 1 commit into
DavidBabinec wants to merge 1 commit into
Conversation
…admin pages The Tabs compound component (ARIA automatic-activation, roving tabindex, keyboard nav) shipped with an underline visual style no page used, so it sat dead while AiPage, UsersPage, and AccountPage each hand-rolled the same Button-based tablist — with drift: UsersPage's tabs were missing role="tab"/aria-selected, none had arrow-key navigation, and all three duplicated the same .tabsRow CSS. - Tab now renders the shared Button primitive (primary when active, secondary otherwise, size sm) — the pattern the pages already used. - TabPanel lazy-mounts children by default (matching page behavior); keepMounted opts panels back into staying mounted while hidden. The panel element itself stays in the DOM so aria-controls always resolves. - Tab gains a testId prop so the pages' existing data-testids carry over. - AiPage, UsersPage, AccountPage adopt Tabs/TabList/TabPanel; the three .tabsRow copies are deleted. All three pages gain keyboard navigation, and UsersPage gains the ARIA it was missing. - usersAdmin tests updated: tab queries use role="tab" (a11y improvement the change delivers); new unit tests cover the primitive's contract. Verification: bun test (6009 pass), bun run build, bun run lint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
The
Tabscompound component (src/ui/components/Tabs/) shipped with WAI-ARIA automatic activation, roving tabindex, and arrow-key navigation — but an underline visual style no page used. It sat with zero consumers while AiPage, UsersPage, and AccountPage each hand-rolled the same Button-based tablist, already drifting:role="tab"/aria-selectedthat its two siblings had.tabsRowCSS ruleThis PR redesigns the primitive around the Button pattern the pages actually use, then adopts it in all three:
Tabrenders the sharedButtonprimitive (primarywhen active,secondaryotherwise, sizesm)TabPanellazy-mounts children by default (matching current page behavior);keepMountedopts a panel back into staying mounted while hidden. The panel element itself always stays in the DOM so the active tab'saria-controlsresolvesTabgains atestIdprop so the pages' existingdata-testids carry over unchangedTabList+TabPanels may live in different subtrees of one<Tabs>provider (tab row goes intoAdminPageLayout'stabsslot, panels render as children).tabsRowCSS copies are deleted;docs/reference/ui-primitives.mdupdatedWhy
Health-check audit finding: a dead primitive coexisting with 3 hand-rolled versions of the same UI is the exact drift pattern the
src/uiprimitive rule exists to prevent. Consolidating fixes the UsersPage a11y gap and gives all three pages keyboard navigation for free.Impact
usersAdmintests updated to queryrole="tab"(the a11y improvement this delivers)src/__tests__/ui/tabs.test.tsxcovers the primitive's contract (roles, roving tabindex, lazy vs keepMounted panels, aria wiring, keyboard activation, testId)Verification
🤖 Generated with Claude Code