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:
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user