Give the candidate route a dedicated dark workspace layout with overview actions, while keeping the drawer profile flow unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Skeleton loading system: .skeleton shimmer primitives in CSS (theme-
aware via --border) plus a SkeletonRows component, adopted at the
main-content loading states of Jobs, Candidates, Inbox, Interviews,
Offers, Assessments, Tasks, Managers, Notifications. Small card-level
loading states keep their EmptyState text.
- ErrorBoundary around the route outlet, keyed by pathname: a throw in
one lazy screen shows a recoverable error state instead of blanking
the whole app; navigating away resets it.
- auth.css stops hardcoding the Belleza stack twice; both sites use
var(--font-display) so the display face has one definition.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- New ui/PageHeader.jsx emitting the existing .page-head structure;
screens adopt it in the next two passes.
- DataTable: sortable thead extracted as DataTableHead (Candidates can
drop its verbatim copy) and an onRowClick prop with keyboard support.
- Tabs: index-based ids, aria-controls, roving tabindex, arrow-key and
Home/End navigation; TabPanel labels its panel.
- Toast root announces politely to screen readers (was silent).
- Dropdown stamps aria-expanded/aria-haspopup on every trigger.
- primitives: shared PRIORITY_CLASS (Dashboard and Tasks had identical
private copies).
- Shell: skip link to #main-content, sidebar nav labeled Primary,
clickable notification rows are real buttons now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>