Horizontalen Scroll verhindern: Lange Task-Titel werden überall abgeschnitten
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- Globales overflow-x: hidden auf html/body/#root in index.css - App.tsx: overflow-x-hidden und min-w-0 auf Hauptcontainer - TaskCard: Eltern-Task-Titel mit truncate/min-w-0 im Flex-Layout - KanbanBoard: min-w-0 overflow-hidden auf Spalten-Cards - FiveMinuteStarter: truncate auf Task-Titel - HyperfocusGuard: truncate auf Task-Buttons - TaskBreakdownModal: truncate auf Task- und Subtask-Titel - NotificationsPage: truncate + min-w-0 auf Benachrichtigungs-Titel
This commit is contained in:
+2
-2
@@ -349,7 +349,7 @@ function AppContent() {
|
|||||||
<SidebarProvider>
|
<SidebarProvider>
|
||||||
<AppSidebar user={user} />
|
<AppSidebar user={user} />
|
||||||
<SidebarInset>
|
<SidebarInset>
|
||||||
<div className={`min-h-screen bg-background flex flex-col ${adhdEnabled ? 'adhd-mode' : ''} ${adhdEnabled && adhdSettings.reducedAnimations ? 'reduced-motion' : ''} ${adhdEnabled && adhdSettings.largerTargets ? 'larger-targets' : ''}`}>
|
<div className={`min-h-screen bg-background flex flex-col min-w-0 overflow-x-hidden ${adhdEnabled ? 'adhd-mode' : ''} ${adhdEnabled && adhdSettings.reducedAnimations ? 'reduced-motion' : ''} ${adhdEnabled && adhdSettings.largerTargets ? 'larger-targets' : ''}`}>
|
||||||
{/* Mobile Header with Sidebar Toggle */}
|
{/* Mobile Header with Sidebar Toggle */}
|
||||||
<header className="sticky top-0 z-50 flex items-center gap-3 px-4 py-3 bg-background/80 backdrop-blur-xl border-b border-border/50 md:hidden">
|
<header className="sticky top-0 z-50 flex items-center gap-3 px-4 py-3 bg-background/80 backdrop-blur-xl border-b border-border/50 md:hidden">
|
||||||
<SidebarTrigger className="h-9 w-9" />
|
<SidebarTrigger className="h-9 w-9" />
|
||||||
@@ -360,7 +360,7 @@ function AppContent() {
|
|||||||
<span className="font-bold text-lg">{t('app.title')}</span>
|
<span className="font-bold text-lg">{t('app.title')}</span>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main className="flex-1 p-4 md:p-6 max-w-screen-2xl mx-auto w-full relative">
|
<main className="flex-1 p-4 md:p-6 max-w-screen-2xl mx-auto w-full relative overflow-x-hidden">
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/">
|
<Route path="/">
|
||||||
<FocusMode
|
<FocusMode
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ export default function KanbanBoard({ tasks, onTaskStatusChange, onTaskUpdate, o
|
|||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
key={column.id}
|
key={column.id}
|
||||||
className="p-3 sm:p-4"
|
className="p-3 sm:p-4 min-w-0 overflow-hidden"
|
||||||
onDragOver={handleDragOver}
|
onDragOver={handleDragOver}
|
||||||
onDrop={() => handleDrop(column.status)}
|
onDrop={() => handleDrop(column.status)}
|
||||||
data-testid={`column-${column.id}`}
|
data-testid={`column-${column.id}`}
|
||||||
@@ -494,7 +494,7 @@ export default function KanbanBoard({ tasks, onTaskStatusChange, onTaskUpdate, o
|
|||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
key={column.id}
|
key={column.id}
|
||||||
className="p-3 sm:p-4"
|
className="p-3 sm:p-4 min-w-0 overflow-hidden"
|
||||||
onDragOver={handleDragOver}
|
onDragOver={handleDragOver}
|
||||||
onDrop={() => handleDrop(column.status)}
|
onDrop={() => handleDrop(column.status)}
|
||||||
data-testid={`column-${column.id}`}
|
data-testid={`column-${column.id}`}
|
||||||
@@ -558,7 +558,7 @@ export default function KanbanBoard({ tasks, onTaskStatusChange, onTaskUpdate, o
|
|||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
key={column.id}
|
key={column.id}
|
||||||
className="p-3 sm:p-4"
|
className="p-3 sm:p-4 min-w-0 overflow-hidden"
|
||||||
onDragOver={handleDragOver}
|
onDragOver={handleDragOver}
|
||||||
onDrop={() => handleDrop(column.status)}
|
onDrop={() => handleDrop(column.status)}
|
||||||
data-testid={`column-${column.id}`}
|
data-testid={`column-${column.id}`}
|
||||||
|
|||||||
@@ -351,10 +351,10 @@ 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 ${task.status === 'done' ? 'line-through' : ''}`} data-testid={`text-task-title-${task.id}`}>
|
||||||
{parentTask ? (
|
{parentTask ? (
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1 min-w-0">
|
||||||
<span className="text-muted-foreground font-normal">{parentTask.title}</span>
|
<span className="text-muted-foreground font-normal truncate shrink">{parentTask.title}</span>
|
||||||
<span className="text-muted-foreground">›</span>
|
<span className="text-muted-foreground shrink-0">›</span>
|
||||||
<span>{task.title}</span>
|
<span className="truncate shrink">{task.title}</span>
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
task.title
|
task.title
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ export function TaskBreakdownModal({ task, open, onOpenChange }: TaskBreakdownMo
|
|||||||
|
|
||||||
{/* Task info */}
|
{/* Task info */}
|
||||||
<div className="bg-muted/50 rounded-lg p-4 mb-4">
|
<div className="bg-muted/50 rounded-lg p-4 mb-4">
|
||||||
<h4 className="font-medium mb-1">{task.title}</h4>
|
<h4 className="font-medium mb-1 truncate">{task.title}</h4>
|
||||||
{task.description && (
|
{task.description && (
|
||||||
<p className="text-sm text-muted-foreground">{task.description}</p>
|
<p className="text-sm text-muted-foreground">{task.description}</p>
|
||||||
)}
|
)}
|
||||||
@@ -195,8 +195,8 @@ export function TaskBreakdownModal({ task, open, onOpenChange }: TaskBreakdownMo
|
|||||||
onCheckedChange={() => handleToggleSubtask(index)}
|
onCheckedChange={() => handleToggleSubtask(index)}
|
||||||
className="mt-0.5"
|
className="mt-0.5"
|
||||||
/>
|
/>
|
||||||
<div className="flex-1">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="font-medium text-sm">{subtask.title}</p>
|
<p className="font-medium text-sm truncate">{subtask.title}</p>
|
||||||
<div className="flex items-center gap-1 mt-1 text-xs text-muted-foreground">
|
<div className="flex items-center gap-1 mt-1 text-xs text-muted-foreground">
|
||||||
<Clock className="h-3 w-3" />
|
<Clock className="h-3 w-3" />
|
||||||
<span>~{subtask.estimatedMinutes} min</span>
|
<span>~{subtask.estimatedMinutes} min</span>
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export function FiveMinuteStarter({
|
|||||||
<h3 className="text-xl font-bold mb-2">
|
<h3 className="text-xl font-bold mb-2">
|
||||||
{t('adhd.fiveMin.title')}
|
{t('adhd.fiveMin.title')}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-muted-foreground mb-2">
|
<p className="text-muted-foreground mb-2 truncate max-w-full">
|
||||||
{task.title}
|
{task.title}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-muted-foreground mb-6">
|
<p className="text-sm text-muted-foreground mb-6">
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ export function HyperfocusGuard({ activeTaskId, onTaskStart }: HyperfocusGuardPr
|
|||||||
hover:bg-amber-200 dark:hover:bg-amber-900
|
hover:bg-amber-200 dark:hover:bg-amber-900
|
||||||
transition-colors text-sm
|
transition-colors text-sm
|
||||||
text-amber-900 dark:text-amber-100
|
text-amber-900 dark:text-amber-100
|
||||||
|
truncate
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{task.title}
|
{task.title}
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* Prevent horizontal scroll globally */
|
||||||
|
html, body, #root {
|
||||||
|
overflow-x: hidden;
|
||||||
|
max-width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
/* LIGHT MODE */
|
/* LIGHT MODE */
|
||||||
:root {
|
:root {
|
||||||
--button-outline: rgba(0,0,0, .10);
|
--button-outline: rgba(0,0,0, .10);
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ export default function NotificationsPage() {
|
|||||||
<div className={`p-2 rounded-full shrink-0 ${notif.type === 'overdue' ? 'bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400' : 'bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400'}`}>
|
<div className={`p-2 rounded-full shrink-0 ${notif.type === 'overdue' ? 'bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400' : 'bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400'}`}>
|
||||||
{notif.type === 'overdue' ? <AlertCircle className="h-5 w-5" /> : <Calendar className="h-5 w-5" />}
|
{notif.type === 'overdue' ? <AlertCircle className="h-5 w-5" /> : <Calendar className="h-5 w-5" />}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between gap-2">
|
||||||
<h3 className="font-semibold">{notif.task.title}</h3>
|
<h3 className="font-semibold truncate">{notif.task.title}</h3>
|
||||||
<span className="text-xs text-muted-foreground whitespace-nowrap">
|
<span className="text-xs text-muted-foreground whitespace-nowrap">
|
||||||
{formatDistanceToNow(notif.timestamp, { addSuffix: true, locale: i18n.language === 'de' ? de : enUS })}
|
{formatDistanceToNow(notif.timestamp, { addSuffix: true, locale: i18n.language === 'de' ? de : enUS })}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user