improvement(org): move the People page onto the new design system
Merged
WA
2d ago+4045+4045+0123456789012345678901234567890123456789-2687-2687-0123456789012345678901234567890123456789
Summary
- Rebuild People on the embedded design system (same mount as Home, Links, Integrations): org chart, directory, profile, directory sync, connect, import
- Org chart matches the Paper prototype: person cards, focused state, reporting bus, breadcrumb, zoom and fit controls, four reports per page on desktop, one branch with a compact manager on mobile
- Find a person is a real search field with two-line results (title and department) and keyboard hints
- Directory sync is now a page at the existing
?panel=syncURL, with a summary for each state: connected, first sync, syncing, publishing, waiting to retry, failed, paused - First use for an admin offers Okta, Entra and SCIM plus Import profiles; a member gets a neutral state pointing at the directory
- Profile is two columns with Copy profile link; invalid or inaccessible links get a neutral recovery state
- Page gate moves to
canBrowsePeople, so a member withheld the directory gets a 404 from a saved link, matching the sidebar - Sync actions share one org-wide in-flight guard, since the page and the connect dialog each hold actions now
- Initial sync status reads no longer invalidate every People query
- Move the parsers and sheet reader to
lib/people, matching #9687 - Delete the legacy People views and the
ResourceLoadErrorthey orphaned;LinksSurfacebecomes a sharedRedesignPageSurface
Design-system additions, each with a People consumer: SearchCombobox, Avatar row/card/hero, DataTable primary and rowChevron, SearchableSelect variant='text', users and minus glyphs. EmptyState now lays out its own action row instead of restyling any div it is given.
Where the prototype and the #9687 contract disagree, this follows the contract:
- No row dividers in the directory or profile lists (lines are reserved for surface boundaries)
- Single-initial avatars
- Dialogs use the shared
Modalchrome - Disconnect is the solid destructive button
- Directory load-more is automatic through the table owner, not a button
Deliberate departures from the prototype:
- Header keeps Import beside Directory sync once a chart exists, so admins don't lose it
- Mobile keeps the breadcrumb, so top-level teams stay reachable
- Profile rows center the avatar as Paper draws them instead of using
ActivityRow, whose leading slot can't hold it (the contract asks for first-line alignment) - Underline tabs are local to People, as Paper draws them (the contract points horizontal destinations at
ControlRow)
Heads up for #9687: its branch has its own people/ tree at many of the same paths, so that rebase needs to pick this implementation.
Type of Change
- Improvement
Testing
test-people-e2e.tsagainst a running app and real Postgres in hosted mode: 20/20, browser journey updated for the new UI and extended to the header entry pointstest-org-redesign-e2e.tsPeople phase updated; runs in CI, not run locallybun run --cwd apps/sim test lib/peopleand the organization layout test: 56 passedtype-check,lint,check:platform-css,check:source-conventions,check:comment-hygiene,check:file-names,check:utils,check:client-boundary,check:explicit-any,check:boundaries,check:test-patterns, block registry- Full
check:auditsand rootbun run testleft to CI - Rendered every state against the Paper artboards: light and dark on the chart, 1440, 1024 and 390 wide. Sync states used a mocked status response
- Not exercised against a real Okta or Entra tenant
Checklist
- Code follows project style guidelines
- Self-reviewed my changes
- Tests added/updated and passing (new tests pass the
test-auditauthoring gate) - No new warnings introduced
- I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)