feat(02-05): ColorLegend, AppNav, ViewToolbar, SkeletonCalendar, EmptyState; retire EventProof

- ColorLegend: per-member color swatches (12px circle, label) + always-visible Family row
- AppNav: phone 48px top bar (avatar with aria-label/title) + tablet/desktop 240px sidebar with ColorLegend
- ViewToolbar: Today/prev/next + Day/Week/Month/Agenda view switcher; 44px min-height; active state uses surface tint not accent
- SkeletonCalendar: shimmer month (6x7 grid) and agenda (4 date-group blocks) variants; aria-busy=true
- EmptyState: CalendarDays icon + 'Nothing here' heading + body copy per UI-SPEC
- CalendarShell: full phone/desktop layout with AppNav + ViewToolbar + ColorLegend chrome
- CalendarShell: state branches — loading→SkeletonCalendar, empty→EmptyState, error→'Couldn't load events' + Retry button (refetchQueries)
- EventProof.tsx deleted; legacy types removed from client.ts
- CalendarShell.test.tsx: updated to waitFor ScheduleXCalendar after data loads
- All 36 tests pass, tsc clean, vite build clean (490kB)
This commit is contained in:
Lucas Berger
2026-06-05 10:58:06 -04:00
parent 3eebfbff42
commit 216ddcedf4
9 changed files with 840 additions and 230 deletions
@@ -152,9 +152,10 @@ describe('CalendarShell — CAL-03 render smoke', () => {
expect(() => renderWithClient(<CalendarShell />)).not.toThrow()
})
it('mounts the ScheduleXCalendar with a non-null calendarApp', () => {
it('mounts the ScheduleXCalendar with a non-null calendarApp after data loads', async () => {
renderWithClient(<CalendarShell />)
const calEl = screen.getByTestId('schedule-x-calendar')
// CalendarShell shows SkeletonCalendar during loading; wait for data to resolve
const calEl = await screen.findByTestId('schedule-x-calendar')
expect(calEl).toBeDefined()
expect(calEl.getAttribute('data-has-app')).toBe('true')
})