Fix: Horizontales Scrollen auf Mobilgeräten endgültig behoben
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- TaskCard: motion.div in overflow-hidden Wrapper gepackt - TaskCard: overscrollBehaviorX auf motion.div gesetzt - TaskCard: Titel und Badge-Zeile mit max-w-full/overflow-hidden abgesichert - TasksWithCalendar: Negative Margins (-mx-4/-mx-6) am Calendar entfernt - TasksWithCalendar: overflow-x-hidden auf Scrollable Task List - index.css: overscroll-behavior-x: none global auf html/body/#root - index.css: max-width: 100% als globale Absicherung gegen Overflow
This commit is contained in:
@@ -295,6 +295,7 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="overflow-hidden">
|
||||||
<motion.div
|
<motion.div
|
||||||
drag="x"
|
drag="x"
|
||||||
dragConstraints={{ left: -50, right: 150 }} // Limit swipe distance
|
dragConstraints={{ left: -50, right: 150 }} // Limit swipe distance
|
||||||
@@ -303,6 +304,7 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
|
|||||||
animate={controls}
|
animate={controls}
|
||||||
whileDrag={{ scale: 1.02, cursor: 'grabbing' }}
|
whileDrag={{ scale: 1.02, cursor: 'grabbing' }}
|
||||||
className="touch-pan-y" // Allow vertical scroll, horizontal swipe
|
className="touch-pan-y" // Allow vertical scroll, horizontal swipe
|
||||||
|
style={{ overscrollBehaviorX: 'none' }}
|
||||||
>
|
>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<ContextMenuTrigger asChild>
|
<ContextMenuTrigger asChild>
|
||||||
@@ -349,12 +351,12 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Parent Task Link rendered in title now */}
|
{/* Parent Task Link rendered in title now */}
|
||||||
<h3 className={`font-medium text-sm leading-tight truncate ${task.status === 'done' ? 'line-through' : ''}`} data-testid={`text-task-title-${task.id}`}>
|
<h3 className={`font-medium text-sm leading-tight truncate max-w-full overflow-hidden ${task.status === 'done' ? 'line-through' : ''}`} data-testid={`text-task-title-${task.id}`}>
|
||||||
{parentTask ? (
|
{parentTask ? (
|
||||||
<span className="flex items-center gap-1 min-w-0">
|
<span className="flex items-center gap-1 min-w-0 max-w-full overflow-hidden">
|
||||||
<span className="text-muted-foreground font-normal truncate shrink">{parentTask.title}</span>
|
<span className="text-muted-foreground font-normal truncate shrink min-w-0">{parentTask.title}</span>
|
||||||
<span className="text-muted-foreground shrink-0">›</span>
|
<span className="text-muted-foreground shrink-0">›</span>
|
||||||
<span className="truncate shrink">{task.title}</span>
|
<span className="truncate shrink min-w-0">{task.title}</span>
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
task.title
|
task.title
|
||||||
@@ -366,7 +368,7 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex items-center gap-2 mt-3 flex-wrap">
|
<div className="flex items-center gap-2 mt-3 flex-wrap max-w-full overflow-hidden">
|
||||||
<Badge
|
<Badge
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className={`text-xs ${getPriorityColor(task.priority)}`}
|
className={`text-xs ${getPriorityColor(task.priority)}`}
|
||||||
@@ -701,5 +703,6 @@ export default function TaskCard({ task, onStartTimer, onStopTimer, onEdit, onDe
|
|||||||
onOpenChange={setIsShareModalOpen}
|
onOpenChange={setIsShareModalOpen}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -355,7 +355,7 @@ export default function TasksWithCalendar({ tasks, onTaskUpdate, onTaskEdit, onT
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Scrollable Task List */}
|
{/* Scrollable Task List */}
|
||||||
<div className="flex-1 overflow-y-auto min-h-0 space-y-3 px-1 pb-4">
|
<div className="flex-1 overflow-y-auto overflow-x-hidden min-h-0 space-y-3 px-1 pb-4">
|
||||||
{unscheduledTasks.length === 0 ? (
|
{unscheduledTasks.length === 0 ? (
|
||||||
<div className="text-center py-8">
|
<div className="text-center py-8">
|
||||||
<p className="text-muted-foreground" data-testid="text-no-tasks">
|
<p className="text-muted-foreground" data-testid="text-no-tasks">
|
||||||
@@ -409,7 +409,7 @@ export default function TasksWithCalendar({ tasks, onTaskUpdate, onTaskEdit, onT
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Calendar Section - Fixed at bottom */}
|
{/* Calendar Section - Fixed at bottom */}
|
||||||
<div className="flex-none -mx-4 md:-mx-6 bg-background/95 backdrop-blur z-30 border-t mt-auto shadow-up-lg">
|
<div className="flex-none bg-background/95 backdrop-blur z-30 border-t mt-auto shadow-up-lg overflow-hidden">
|
||||||
<div className="p-3">
|
<div className="p-3">
|
||||||
{/* Calendar Header */}
|
{/* Calendar Header */}
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
|
|||||||
@@ -6,6 +6,17 @@
|
|||||||
html, body, #root {
|
html, body, #root {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
|
overscroll-behavior-x: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prevent any element from causing horizontal overflow */
|
||||||
|
* {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exceptions for elements that legitimately need wider content */
|
||||||
|
.overflow-x-auto, [style*="grid-template-columns"] {
|
||||||
|
max-width: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LIGHT MODE */
|
/* LIGHT MODE */
|
||||||
|
|||||||
Reference in New Issue
Block a user