@@ -27,6 +27,7 @@ import type { TypeDefinition } from '../../types/typeConfig';
2727import { KanbanCard } from './KanbanCard' ;
2828import { GripIcon } from '../ui/Icons' ;
2929import { hexToRgba } from '../../lib/utils' ;
30+ import { useKanbanColumnWidths , KANBAN_BASE_WIDTH , type WidthMultiplier } from '../../hooks/useKanbanColumnWidths' ;
3031
3132// Only virtualize columns with many items (avoids height estimation issues for small lists)
3233const VIRTUALIZATION_THRESHOLD = 15 ;
@@ -40,6 +41,7 @@ interface KanbanBoardProps {
4041
4142export function KanbanBoard ( { itemsByType, types, onItemClick, onTypesReorder } : KanbanBoardProps ) {
4243 const totalItems = Object . values ( itemsByType ) . reduce ( ( sum , items ) => sum + items . length , 0 ) ;
44+ const { getMultiplier, getWidth, toggleWidth } = useKanbanColumnWidths ( ) ;
4345
4446 // Filter types to only show columns with items
4547 const visibleTypes = useMemo ( ( ) => {
@@ -94,6 +96,9 @@ export function KanbanBoard({ itemsByType, types, onItemClick, onTypesReorder }:
9496 type = { type }
9597 items = { itemsByType [ type . id ] || [ ] }
9698 onItemClick = { onItemClick }
99+ width = { getWidth ( type . id ) }
100+ multiplier = { getMultiplier ( type . id ) }
101+ onToggleWidth = { ( ) => toggleWidth ( type . id ) }
97102 />
98103 ) ) }
99104 </ div >
@@ -111,8 +116,11 @@ interface SortableKanbanColumnProps {
111116 type : TypeDefinition ;
112117 items : BacklogItem [ ] ;
113118 onItemClick : ( item : BacklogItem ) => void ;
119+ width : number ;
120+ multiplier : WidthMultiplier ;
121+ onToggleWidth : ( ) => void ;
114122}
115- function SortableKanbanColumnWithStyles ( { type, items, onItemClick } : SortableKanbanColumnProps ) {
123+ function SortableKanbanColumnWithStyles ( { type, items, onItemClick, width , multiplier , onToggleWidth } : SortableKanbanColumnProps ) {
116124 const {
117125 attributes,
118126 listeners,
@@ -145,15 +153,19 @@ function SortableKanbanColumnWithStyles({ type, items, onItemClick }: SortableKa
145153 const borderColor = hexToRgba ( type . color , 0.3 ) ;
146154 const headerBgColor = hexToRgba ( type . color , 0.15 ) ;
147155
156+ const isDouble = multiplier === 2 ;
157+
148158 return (
149159 < div
150160 ref = { setNodeRef }
151161 style = { {
152162 ...style ,
153163 backgroundColor : bgColor ,
154164 borderColor : borderColor ,
165+ width : `${ width } px` ,
166+ minWidth : `${ KANBAN_BASE_WIDTH } px` ,
155167 } }
156- className = "flex flex-col w-full sm:w-72 md:w-80 rounded-lg border max-h-[calc(100vh-200px)]"
168+ className = "flex flex-col rounded-lg border max-h-[calc(100vh-200px)] transition-all duration-200 "
157169 >
158170 { /* Header - Draggable */ }
159171 < div
@@ -167,7 +179,27 @@ function SortableKanbanColumnWithStyles({ type, items, onItemClick }: SortableKa
167179 < GripIcon className = "w-4 h-4 opacity-50" />
168180 < h3 className = "font-semibold" style = { { color : type . color } } > { type . label } </ h3 >
169181 </ div >
170- < span className = "text-sm" style = { { color : type . color , opacity : 0.75 } } > { items . length } </ span >
182+ < div className = "flex items-center gap-2" >
183+ < button
184+ onClick = { ( e ) => {
185+ e . stopPropagation ( ) ;
186+ onToggleWidth ( ) ;
187+ } }
188+ onMouseDown = { ( e ) => e . stopPropagation ( ) }
189+ className = { `
190+ px-1.5 py-0.5 text-[10px] font-medium rounded
191+ transition-all duration-150 ease-out
192+ ${ isDouble
193+ ? 'bg-blue-100 text-blue-700 hover:bg-blue-200'
194+ : 'bg-white/50 text-gray-600 hover:bg-white/80'
195+ }
196+ ` }
197+ title = { isDouble ? 'Réduire (1 carte)' : 'Élargir (2 cartes)' }
198+ >
199+ { isDouble ? '2x' : '1x' }
200+ </ button >
201+ < span className = "text-sm" style = { { color : type . color , opacity : 0.75 } } > { items . length } </ span >
202+ </ div >
171203 </ div >
172204 </ div >
173205
@@ -178,7 +210,7 @@ function SortableKanbanColumnWithStyles({ type, items, onItemClick }: SortableKa
178210 Aucun item
179211 </ div >
180212 ) : shouldVirtualize ? (
181- // Virtualized rendering for large lists
213+ // Virtualized rendering for large lists (single column only for now)
182214 < div
183215 style = { {
184216 height : `${ virtualizer . getTotalSize ( ) } px` ,
@@ -209,8 +241,8 @@ function SortableKanbanColumnWithStyles({ type, items, onItemClick }: SortableKa
209241 } ) }
210242 </ div >
211243 ) : (
212- // Classic rendering for small lists (avoids height estimation issues)
213- < div className = " space-y-3" >
244+ // Classic rendering - grid for 2x mode, single column for 1x
245+ < div className = { isDouble ? 'grid grid-cols-2 gap-3' : ' space-y-3' } >
214246 { items . map ( item => (
215247 < KanbanCard
216248 key = { item . id }
0 commit comments