diff --git a/frontend/src/components/calendar/CalendarPage.tsx b/frontend/src/components/calendar/CalendarPage.tsx index b4ee310..e547f56 100644 --- a/frontend/src/components/calendar/CalendarPage.tsx +++ b/frontend/src/components/calendar/CalendarPage.tsx @@ -17,7 +17,7 @@ import { useSettings } from '@/hooks/useSettings'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Select } from '@/components/ui/select'; -import { Sheet, SheetContent } from '@/components/ui/sheet'; +import { Sheet, SheetContent, SheetClose } from '@/components/ui/sheet'; import CalendarSidebar from './CalendarSidebar'; import EventDetailPanel from './EventDetailPanel'; import type { CreateDefaults } from './EventDetailPanel'; @@ -165,7 +165,6 @@ export default function CalendarPage() { // Track desktop breakpoint to prevent dual EventDetailPanel mount const isDesktop = useMediaQuery('(min-width: 1024px)'); - const isMobile = useMediaQuery('(max-width: 1023px)'); const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); // Continuously resize calendar during panel open/close CSS transition @@ -484,9 +483,10 @@ export default function CalendarPage() { /> - {isMobile && ( + {!isDesktop && ( + setMobileSidebarOpen(false)} /> { setMobileSidebarOpen(false); handleUseTemplate(tmpl); }} onSharedVisibilityChange={setVisibleSharedIds} width={288} /> @@ -540,12 +540,12 @@ export default function CalendarPage() { ))} -

{calendarTitle}

+

{calendarTitle}

{/* Event search */} -
+
setEventSearch(e.target.value)} onFocus={() => setSearchFocused(true)} onBlur={() => setTimeout(() => setSearchFocused(false), 200)} - className="w-52 h-8 pl-8 text-sm ring-inset" + className="w-32 sm:w-52 h-8 pl-8 text-sm ring-inset" /> {searchFocused && searchResults.length > 0 && (
@@ -644,7 +644,7 @@ export default function CalendarPage() { onClick={handlePanelClose} >
e.stopPropagation()} >
{location.name} - {location.category && {location.category}} + {location.category && {location.category}}
{location.address && (

{location.address}

diff --git a/frontend/src/components/people/PeoplePage.tsx b/frontend/src/components/people/PeoplePage.tsx index d51cc3c..5fa89c8 100644 --- a/frontend/src/components/people/PeoplePage.tsx +++ b/frontend/src/components/people/PeoplePage.tsx @@ -748,7 +748,7 @@ export default function PeoplePage() {
{person.name} - {person.category && {person.category}} + {person.category && {person.category}}
{person.email && {person.email}} diff --git a/frontend/src/components/projects/KanbanBoard.tsx b/frontend/src/components/projects/KanbanBoard.tsx index 6658dbc..91b258c 100644 --- a/frontend/src/components/projects/KanbanBoard.tsx +++ b/frontend/src/components/projects/KanbanBoard.tsx @@ -2,6 +2,7 @@ import { DndContext, closestCorners, PointerSensor, + TouchSensor, useSensor, useSensors, type DragEndEvent, @@ -200,7 +201,7 @@ export default function KanbanBoard({ collisionDetection={closestCorners} onDragEnd={handleDragEnd} > -
+
{tasksByStatus.map(({ column, tasks: colTasks }) => ( -
+
setSearch(e.target.value)} - className="w-52 h-8 pl-8 text-sm" + className="w-32 sm:w-52 h-8 pl-8 text-sm" />
diff --git a/frontend/src/components/reminders/RemindersPage.tsx b/frontend/src/components/reminders/RemindersPage.tsx index 55f892a..e00b61d 100644 --- a/frontend/src/components/reminders/RemindersPage.tsx +++ b/frontend/src/components/reminders/RemindersPage.tsx @@ -135,13 +135,13 @@ export default function RemindersPage() {
-
+
setSearch(e.target.value)} - className="w-52 h-8 pl-8 text-sm ring-inset" + className="w-32 sm:w-52 h-8 pl-8 text-sm ring-inset" />
diff --git a/frontend/src/components/shared/EntityTable.tsx b/frontend/src/components/shared/EntityTable.tsx index e6ccf27..529493d 100644 --- a/frontend/src/components/shared/EntityTable.tsx +++ b/frontend/src/components/shared/EntityTable.tsx @@ -149,7 +149,7 @@ export function EntityTable({ <>

{pinnedLabel}

{pinnedRows.map((item) => ( -
onRowClick(item.id)} className="cursor-pointer"> +
onRowClick(item.id)} className="cursor-pointer" role="button" tabIndex={0} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onRowClick(item.id); } }}> {mobileCardRender(item)}
))} @@ -161,7 +161,7 @@ export function EntityTable({ <>

{group.label}

{group.rows.map((item) => ( -
onRowClick(item.id)} className="cursor-pointer"> +
onRowClick(item.id)} className="cursor-pointer" role="button" tabIndex={0} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onRowClick(item.id); } }}> {mobileCardRender(item)}
))} diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx index 0a9968a..6d826aa 100644 --- a/frontend/src/components/ui/button.tsx +++ b/frontend/src/components/ui/button.tsx @@ -18,7 +18,7 @@ const buttonVariants = cva( default: 'h-10 px-4 py-2', sm: 'h-9 rounded-md px-3', lg: 'h-11 rounded-md px-8', - icon: 'h-11 w-11 md:h-10 md:w-10', + icon: 'h-10 w-10 min-h-[44px] min-w-[44px] md:min-h-0 md:min-w-0', }, }, defaultVariants: { diff --git a/frontend/src/components/ui/date-picker.tsx b/frontend/src/components/ui/date-picker.tsx index f53ca6c..4f9f7bb 100644 --- a/frontend/src/components/ui/date-picker.tsx +++ b/frontend/src/components/ui/date-picker.tsx @@ -326,8 +326,8 @@ const DatePicker = React.forwardRef(
e.stopPropagation()} - style={{ position: 'fixed', top: pos.top, left: pos.left, zIndex: 60 }} - className="w-[280px] rounded-lg border border-input bg-card shadow-lg animate-fade-in" + style={isMobile ? { position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: 60 } : { position: 'fixed', top: pos.top, left: pos.left, zIndex: 60 }} + className={isMobile ? 'w-full rounded-t-lg border border-input bg-card shadow-lg animate-fade-in pb-[env(safe-area-inset-bottom)]' : 'w-[280px] rounded-lg border border-input bg-card shadow-lg animate-fade-in'} > {/* Month/Year nav */}
diff --git a/frontend/src/hooks/useMediaQuery.ts b/frontend/src/hooks/useMediaQuery.ts index b3c4279..6fc4f90 100644 --- a/frontend/src/hooks/useMediaQuery.ts +++ b/frontend/src/hooks/useMediaQuery.ts @@ -1,7 +1,9 @@ import { useState, useEffect } from 'react'; export function useMediaQuery(query: string): boolean { - const [matches, setMatches] = useState(() => window.matchMedia(query).matches); + const [matches, setMatches] = useState(() => + typeof window !== 'undefined' ? window.matchMedia(query).matches : false + ); useEffect(() => { const mql = window.matchMedia(query);