Merge pull request #693 from AutoMaker-Org/feature/bug-fix-columns-overflow-title-wrap-t6j1

Fix: Column header overflow and title wrapping in Kanban board
This commit is contained in:
Shirone
2026-01-25 11:29:13 +00:00
committed by GitHub
4 changed files with 51 additions and 34 deletions

View File

@@ -78,7 +78,9 @@ export const KanbanColumn = memo(function KanbanColumn({
)} )}
> >
<div className={cn('w-2.5 h-2.5 rounded-full shrink-0', colorClass)} /> <div className={cn('w-2.5 h-2.5 rounded-full shrink-0', colorClass)} />
<h3 className="font-semibold text-sm text-foreground/90 flex-1 tracking-tight">{title}</h3> <h3 className="font-semibold text-sm text-foreground/90 flex-1 tracking-tight whitespace-nowrap">
{title}
</h3>
{headerAction} {headerAction}
<span className="text-xs font-medium text-muted-foreground/80 bg-muted/50 px-2 py-0.5 rounded-md tabular-nums"> <span className="text-xs font-medium text-muted-foreground/80 bg-muted/50 px-2 py-0.5 rounded-md tabular-nums">
{count} {count}

View File

@@ -132,7 +132,7 @@ const SortableColumnHeader = memo(function SortableColumnHeader({
)} )}
data-testid={`list-header-${column.id}`} data-testid={`list-header-${column.id}`}
> >
<span>{column.label}</span> <span className="whitespace-nowrap truncate">{column.label}</span>
<SortIcon column={column.id} sortConfig={sortConfig} /> <SortIcon column={column.id} sortConfig={sortConfig} />
</div> </div>
); );
@@ -156,7 +156,7 @@ const StaticColumnHeader = memo(function StaticColumnHeader({ column }: { column
)} )}
data-testid={`list-header-${column.id}`} data-testid={`list-header-${column.id}`}
> >
<span>{column.label}</span> <span className="whitespace-nowrap truncate">{column.label}</span>
</div> </div>
); );
}); });

View File

@@ -12,7 +12,8 @@ import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { KanbanColumn, KanbanCard, EmptyStateCard } from './components'; import { KanbanColumn, KanbanCard, EmptyStateCard } from './components';
import { Feature, useAppStore, formatShortcut } from '@/store/app-store'; import { Feature, useAppStore, formatShortcut } from '@/store/app-store';
import { Archive, Settings2, CheckSquare, GripVertical, Plus } from 'lucide-react'; import { Archive, Settings2, CheckSquare, GripVertical, Plus, CheckCircle2 } from 'lucide-react';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { useResponsiveKanban } from '@/hooks/use-responsive-kanban'; import { useResponsiveKanban } from '@/hooks/use-responsive-kanban';
import { getColumnsWithPipeline, type ColumnId } from './constants'; import { getColumnsWithPipeline, type ColumnId } from './constants';
import type { PipelineConfig } from '@automaker/types'; import type { PipelineConfig } from '@automaker/types';
@@ -357,35 +358,49 @@ export function KanbanBoard({
contentClassName="perf-contain" contentClassName="perf-contain"
headerAction={ headerAction={
column.id === 'verified' ? ( column.id === 'verified' ? (
<div className="flex items-center gap-1"> <TooltipProvider>
{columnFeatures.length > 0 && ( <div className="flex items-center gap-1">
<Button {columnFeatures.length > 0 && (
variant="ghost" <Tooltip>
size="sm" <TooltipTrigger asChild>
className="h-6 px-2 text-xs" <Button
onClick={onArchiveAllVerified} variant="ghost"
data-testid="archive-all-verified-button" size="sm"
> className="h-6 w-6 p-0"
<Archive className="w-3 h-3 mr-1" /> onClick={onArchiveAllVerified}
Complete All data-testid="archive-all-verified-button"
</Button> >
)} <CheckCircle2 className="w-3.5 h-3.5" />
<Button </Button>
variant="ghost" </TooltipTrigger>
size="sm" <TooltipContent>
className="h-6 w-6 p-0 relative" <p>Complete All</p>
onClick={onShowCompletedModal} </TooltipContent>
title={`Completed Features (${completedCount})`} </Tooltip>
data-testid="completed-features-button"
>
<Archive className="w-3.5 h-3.5 text-muted-foreground" />
{completedCount > 0 && (
<span className="absolute -top-1 -right-1 bg-brand-500 text-white text-[8px] font-bold rounded-full w-3.5 h-3.5 flex items-center justify-center">
{completedCount > 99 ? '99+' : completedCount}
</span>
)} )}
</Button> <Tooltip>
</div> <TooltipTrigger asChild>
<Button
variant="ghost"
size="sm"
className="h-6 w-6 p-0 relative"
onClick={onShowCompletedModal}
data-testid="completed-features-button"
>
<Archive className="w-3.5 h-3.5 text-muted-foreground" />
{completedCount > 0 && (
<span className="absolute -top-1 -right-1 bg-brand-500 text-white text-[8px] font-bold rounded-full w-3.5 h-3.5 flex items-center justify-center">
{completedCount > 99 ? '99+' : completedCount}
</span>
)}
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Completed Features ({completedCount})</p>
</TooltipContent>
</Tooltip>
</div>
</TooltipProvider>
) : column.id === 'backlog' ? ( ) : column.id === 'backlog' ? (
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<Button <Button

View File

@@ -14,8 +14,8 @@ export interface ResponsiveKanbanConfig {
* Default configuration for responsive Kanban columns * Default configuration for responsive Kanban columns
*/ */
const DEFAULT_CONFIG: ResponsiveKanbanConfig = { const DEFAULT_CONFIG: ResponsiveKanbanConfig = {
columnWidth: 288, // 18rem = 288px (w-72) columnWidth: 320, // Increased from 288px to accommodate longer column titles
columnMinWidth: 280, // Minimum column width - ensures usability columnMinWidth: 320, // Increased from 280px to prevent title overflow
columnMaxWidth: Infinity, // No max width - columns scale evenly to fill viewport columnMaxWidth: Infinity, // No max width - columns scale evenly to fill viewport
gap: 20, // gap-5 = 20px gap: 20, // gap-5 = 20px
padding: 40, // px-5 on both sides = 40px (matches gap between columns) padding: 40, // px-5 on both sides = 40px (matches gap between columns)