From ec8f5a9b4e93ecaa380a9bb0d300814fad18753e Mon Sep 17 00:00:00 2001 From: Kyle Pope Date: Sat, 7 Mar 2026 18:02:42 +0800 Subject: [PATCH] Fix mobile density issues from S24 Ultra testing - Page titles: text-xl on mobile, text-2xl on desktop (7 pages) - Stat cards: reduce padding/gap on mobile, hide icons below sm (3 pages) - TodoItem: two-line layout on mobile (title row + metadata row) - ReminderItem: same two-line treatment - FullCalendar: smaller event font/padding on mobile via CSS media query Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/admin/AdminPortal.tsx | 2 +- .../components/locations/LocationsPage.tsx | 2 +- frontend/src/components/people/PeoplePage.tsx | 2 +- .../src/components/projects/ProjectDetail.tsx | 4 +- .../src/components/projects/ProjectsPage.tsx | 28 +-- .../src/components/reminders/ReminderItem.tsx | 132 +++++++------ .../components/reminders/RemindersPage.tsx | 28 +-- frontend/src/components/todos/TodoItem.tsx | 178 +++++++++--------- frontend/src/components/todos/TodosPage.tsx | 28 +-- frontend/src/index.css | 35 ++++ 10 files changed, 244 insertions(+), 195 deletions(-) diff --git a/frontend/src/components/admin/AdminPortal.tsx b/frontend/src/components/admin/AdminPortal.tsx index 3776dd7..76c2d4e 100644 --- a/frontend/src/components/admin/AdminPortal.tsx +++ b/frontend/src/components/admin/AdminPortal.tsx @@ -23,7 +23,7 @@ export default function AdminPortal() {
-

Admin Portal

+

Admin Portal

{/* Horizontal tab navigation */} diff --git a/frontend/src/components/locations/LocationsPage.tsx b/frontend/src/components/locations/LocationsPage.tsx index 9a21eb6..00bee6a 100644 --- a/frontend/src/components/locations/LocationsPage.tsx +++ b/frontend/src/components/locations/LocationsPage.tsx @@ -286,7 +286,7 @@ export default function LocationsPage() {
{/* Header */}
-

Locations

+

Locations

{/* Header */}
-

People

+

People

navigate('/projects')}> -

Loading...

+

Loading...

@@ -379,7 +379,7 @@ export default function ProjectDetail() { -

+

{project.name}

diff --git a/frontend/src/components/projects/ProjectsPage.tsx b/frontend/src/components/projects/ProjectsPage.tsx index 1b6b37c..823d397 100644 --- a/frontend/src/components/projects/ProjectsPage.tsx +++ b/frontend/src/components/projects/ProjectsPage.tsx @@ -72,7 +72,7 @@ export default function ProjectsPage() {
{/* Header */}
-

Projects

+

Projects

{/* Summary stats */} {!isLoading && reminders.length > 0 && ( -
+
- -
+ +
-

+

Active

-

{activeCount}

+

{activeCount}

- -
+ +
-

+

Overdue

-

{overdueCount}

+

{overdueCount}

- -
+ +
-

+

Dismissed

-

{dismissedCount}

+

{dismissedCount}

diff --git a/frontend/src/components/todos/TodoItem.tsx b/frontend/src/components/todos/TodoItem.tsx index cea548b..2036d07 100644 --- a/frontend/src/components/todos/TodoItem.tsx +++ b/frontend/src/components/todos/TodoItem.tsx @@ -52,7 +52,6 @@ export default function TodoItem({ todo, onEdit }: TodoItemProps) { await api.delete(`/todos/${todo.id}`); }, onMutate: async () => { - // Optimistic removal await queryClient.cancelQueries({ queryKey: ['todos'] }); const previous = queryClient.getQueryData(['todos']); queryClient.setQueryData(['todos'], (old) => @@ -65,7 +64,6 @@ export default function TodoItem({ todo, onEdit }: TodoItemProps) { toast.success('Todo deleted'); }, onError: (_err, _vars, context) => { - // Rollback on failure if (context?.previous) { queryClient.setQueryData(['todos'], context.previous); } @@ -87,7 +85,7 @@ export default function TodoItem({ todo, onEdit }: TodoItemProps) { return (
toggleMutation.mutate()} disabled={toggleMutation.isPending} + className="mt-0.5 md:mt-0" /> - onEdit(todo)} - > - {todo.title} - - - {/* Inline pills */} - - {todo.priority} - - - {todo.category && ( - - {todo.category} + {/* Content wrapper — stacks on mobile, inline on desktop */} +
+ {/* Title row — always takes full width on mobile */} + onEdit(todo)} + > + {todo.title} - )} - {todo.recurrence_rule && ( - - {recurrenceLabels[todo.recurrence_rule] || todo.recurrence_rule} - - )} - - {/* Date / time / reset info — right-aligned cluster */} - {showResetInfo ? ( -
- - - Resets {format(resetDate, 'EEE dd/MM')} - {nextDueDate && ( - <> · Due {format(nextDueDate, 'dd/MM')}{todo.due_time ? ` ${todo.due_time.slice(0, 5)}` : ''} + {/* Metadata row — wraps on second line on mobile */} +
+ + {todo.priority} -
- ) : ( - <> - {dueDate && ( - + {todo.category} + + )} + + {todo.recurrence_rule && ( + + {recurrenceLabels[todo.recurrence_rule] || todo.recurrence_rule} + + )} + + {showResetInfo ? ( +
+ + + Resets {format(resetDate, 'EEE dd/MM')} + {nextDueDate && ( + <>{' \u00b7 '}Due {format(nextDueDate, 'dd/MM')}{todo.due_time ? ` ${todo.due_time.slice(0, 5)}` : ''} + )} + +
+ ) : ( + <> + {dueDate && ( + + {isOverdue ? : } + {isOverdue ? 'Overdue \u00b7 ' : isDueToday ? 'Today \u00b7 ' : ''} + {format(dueDate, 'MMM d')} + )} - > - {isOverdue ? : } - {isOverdue ? 'Overdue · ' : isDueToday ? 'Today · ' : ''} - {format(dueDate, 'MMM d')} -
+ {todo.due_time && ( + + + {todo.due_time.slice(0, 5)} + + )} + )} - {todo.due_time && ( - - - {todo.due_time.slice(0, 5)} - - )} - - )} +
+
{/* Actions */} - - {confirmingDelete ? ( - - ) : ( - - )} + {confirmingDelete ? ( + + ) : ( + + )} +
); } diff --git a/frontend/src/components/todos/TodosPage.tsx b/frontend/src/components/todos/TodosPage.tsx index 57356ac..36ed396 100644 --- a/frontend/src/components/todos/TodosPage.tsx +++ b/frontend/src/components/todos/TodosPage.tsx @@ -130,7 +130,7 @@ export default function TodosPage() {
{/* Header */}
-

Todos

+

Todos

{/* Priority filter */}