Admin reusable chrome now has a shared home
This story follows the corrected scope: converge reusable presentational primitives toward src/components/shared/, extract the firms active/archived segmented filter, and leave the accepted TanStack table layer untouched.
What moved
The new src/components/shared/ folder contains the admin primitives that are genuinely table-agnostic and reusable across list/detail surfaces.
SegmentedFilter is a controlled presentational component with the same value/onChange/options shape as the app convention. It preserves the firms tab markup, counts, and visual classes.
StatusBadge moved from components/ui to components/shared. It remains the single status and role badge primitive with the same semantic tone mapping.
The generic page header moved out of components/admin as PageHeader. Existing staff, support access, filing type, and matter type surfaces now import it from shared.
What stayed put
src/components/data-table/* and src/hooks/use-data-table.ts are unchanged. That boundary is the accepted pramaan-io/pramaan-spec#1424 divergence: admin's server-paginated TanStack table remains richer than the app table layer and is not part of this convergence.
No app code changed. No functions code changed. No codegen ran. No i18n framework or string catalog was added.
Behavior proof
The firms list still owns scope in firm-table.tsx through shallow useQueryState("scope"). Clicking Archived resets page, clears the status column filter, updates the URL, and rebuilds the generated firms query request client-side.
The existing regression guard in tests/unit/firm-list.test.tsx confirms the scope change calls useAdminListFirms with status: archived and does not call router.push. The header tests still assert tab roles, counts, selection state, and callbacks.
Per pramaan-docs ADR-124, this is presentational component organization only. It adds no business workflow boundary, route, job, backend call, or user-visible state mutation path, so it is instrumentation-exempt.