feat(02-05): EventDetailPopover read-only popover, XSS-safe, wired into CalendarShell
- EventDetailPopover: reads openEventId from Zustand, resolves occurrence from TanStack Query cache - Dual-mode: standalone (Zustand-driven) + customComponents.eventModal (Schedule-X) - Plain-text JSX children for all event fields (T-02e-01 XSS guard) - Focus trap, Escape to close, backdrop-click to close, aria-label=Close (44px target) - Phone: bottom sheet layout; tablet/desktop: centered popover (max-width 360px) - Phase-3 footer action area reserved with comment - CalendarShell: passes customComponents.eventModal=EventDetailPopover to ScheduleXCalendar - test-setup.ts: import @testing-library/jest-dom for toHaveTextContent matcher - All 36 tests pass, tsc clean
This commit is contained in:
@@ -31,6 +31,7 @@ import { fetchMe, fetchEvents } from '../api/client.js'
|
||||
import { hydrateEvents } from '../lib/hydrateEvents.js'
|
||||
import { buildCalendarConfig, SX_FIRST_DAY_OF_WEEK } from '../lib/calendarConfig.js'
|
||||
import { useCalendarStore } from '../store/calendarStore.js'
|
||||
import { EventDetailPopover } from './EventDetailPopover.js'
|
||||
|
||||
// ── Helpers ────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -177,8 +178,14 @@ export function CalendarShell() {
|
||||
|
||||
{/* Schedule-X calendar fills available space */}
|
||||
<div style={{ flex: 1, minHeight: 0 }}>
|
||||
<ScheduleXCalendar calendarApp={calendar} />
|
||||
<ScheduleXCalendar
|
||||
calendarApp={calendar}
|
||||
customComponents={{ eventModal: EventDetailPopover }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* EventDetailPopover — standalone mode driven by Zustand openEventId */}
|
||||
<EventDetailPopover />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user