From 4e9194495662d4dec611c64ccf1694e17a9e1305 Mon Sep 17 00:00:00 2001 From: Kyle Pope Date: Wed, 11 Mar 2026 03:46:40 +0800 Subject: [PATCH] Fix code review findings: sort dropdown, overlay ref, CalendarPage - C-01: Simplify EntityTable sort dropdown to toggle-based (select column, re-select to flip direction), add aria-label - W-01: Convert CalendarPage mobile overlay to MobileDetailOverlay - W-02: Use ref for onClose in MobileDetailOverlay to prevent listener churn from inline arrow functions Co-Authored-By: Claude Opus 4.6 --- .../src/components/calendar/CalendarPage.tsx | 33 ++++++++----------- .../src/components/shared/EntityTable.tsx | 21 ++++-------- .../components/shared/MobileDetailOverlay.tsx | 10 ++++-- 3 files changed, 26 insertions(+), 38 deletions(-) diff --git a/frontend/src/components/calendar/CalendarPage.tsx b/frontend/src/components/calendar/CalendarPage.tsx index 794c8d8..e9d490c 100644 --- a/frontend/src/components/calendar/CalendarPage.tsx +++ b/frontend/src/components/calendar/CalendarPage.tsx @@ -20,6 +20,7 @@ import { Select } from '@/components/ui/select'; import { Sheet, SheetContent, SheetClose } from '@/components/ui/sheet'; import CalendarSidebar from './CalendarSidebar'; import EventDetailPanel from './EventDetailPanel'; +import MobileDetailOverlay from '@/components/shared/MobileDetailOverlay'; import type { CreateDefaults } from './EventDetailPanel'; type CalendarView = 'dayGridMonth' | 'timeGridWeek' | 'timeGridDay'; @@ -639,26 +640,18 @@ export default function CalendarPage() { {/* Mobile detail panel overlay */} {panelOpen && !isDesktop && ( -
-
e.stopPropagation()} - > - -
-
+ + + )} ); diff --git a/frontend/src/components/shared/EntityTable.tsx b/frontend/src/components/shared/EntityTable.tsx index 6204150..22f5823 100644 --- a/frontend/src/components/shared/EntityTable.tsx +++ b/frontend/src/components/shared/EntityTable.tsx @@ -145,24 +145,15 @@ export function EntityTable({
diff --git a/frontend/src/components/shared/MobileDetailOverlay.tsx b/frontend/src/components/shared/MobileDetailOverlay.tsx index 81cc7a6..93019ff 100644 --- a/frontend/src/components/shared/MobileDetailOverlay.tsx +++ b/frontend/src/components/shared/MobileDetailOverlay.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; import { cn } from '@/lib/utils'; interface MobileDetailOverlayProps { @@ -20,15 +20,19 @@ export default function MobileDetailOverlay({ children, className, }: MobileDetailOverlayProps) { + // Stable ref to avoid re-registering listener on every render + const onCloseRef = useRef(onClose); + onCloseRef.current = onClose; + // Escape key handler useEffect(() => { if (!open) return; const handler = (e: KeyboardEvent) => { - if (e.key === 'Escape') onClose(); + if (e.key === 'Escape') onCloseRef.current(); }; document.addEventListener('keydown', handler); return () => document.removeEventListener('keydown', handler); - }, [open, onClose]); + }, [open]); // Body scroll lock useEffect(() => {