- 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)
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
/**
|
|
* EmptyState — shown when a calendar fetch succeeds but returns zero events.
|
|
*
|
|
* UI-SPEC §EmptyState:
|
|
* - Centered in the calendar viewport
|
|
* - Icon: lucide-react CalendarDays (32px, --color-text-muted)
|
|
* - Heading: "Nothing here"
|
|
* - Body: "No events in this period. Try a different date or switch views."
|
|
*
|
|
* Only rendered when fetch succeeded AND zero events in the visible window.
|
|
*/
|
|
|
|
import { CalendarDays } from 'lucide-react'
|
|
|
|
export function EmptyState() {
|
|
return (
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
padding: 'var(--space-12)',
|
|
gap: 'var(--space-4)',
|
|
fontFamily: 'var(--font-family-base)',
|
|
textAlign: 'center',
|
|
flex: 1,
|
|
}}
|
|
>
|
|
<CalendarDays
|
|
size={32}
|
|
style={{ color: 'var(--color-text-muted)' }}
|
|
aria-hidden="true"
|
|
/>
|
|
<div>
|
|
<h2
|
|
style={{
|
|
margin: '0 0 var(--space-2)',
|
|
fontSize: 'var(--text-heading-size)',
|
|
fontWeight: 'var(--text-heading-weight)',
|
|
lineHeight: 'var(--text-heading-line-height)',
|
|
color: 'var(--color-text-primary)',
|
|
}}
|
|
>
|
|
Nothing here
|
|
</h2>
|
|
<p
|
|
style={{
|
|
margin: 0,
|
|
fontSize: 'var(--text-body-size)',
|
|
fontWeight: 'var(--text-body-weight)',
|
|
lineHeight: 'var(--text-body-line-height)',
|
|
color: 'var(--color-text-muted)',
|
|
maxWidth: '280px',
|
|
}}
|
|
>
|
|
No events in this period. Try a different date or switch views.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|