diff --git a/frontend/src/features/triage/TasksView.tsx b/frontend/src/features/triage/TasksView.tsx index 45c8ed3..2af2451 100644 --- a/frontend/src/features/triage/TasksView.tsx +++ b/frontend/src/features/triage/TasksView.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef, useMemo, useCallback } from 'react'; +import React, { useEffect, useLayoutEffect, useState, useRef, useMemo, useCallback } from 'react'; import { AnimatePresence, motion } from 'framer-motion'; import { Check, @@ -605,17 +605,33 @@ export const TasksView: React.FC = ({ const multi = tops.size > 1; setKanbanMultiRow(multi); setKanbanPerRow(colTops.filter((t) => t === Math.min(...colTops)).length); - if (multi) return; - // One row: take back what still overflows (paddings), so the page does not scroll - const over = area ? area.scrollHeight - area.clientHeight : document.documentElement.scrollHeight - window.innerHeight; - if (over > 0) setKanbanColHeight((h) => (h ? Math.max(KANBAN_MIN_COL_HEIGHT, h - over) : h)); }); }; fit(); + // The board's width animates when it is stretched to full width or back: measure again at the end + const board = kanbanBoardRef.current; + const onTransitionEnd = (e: TransitionEvent) => { + if (e.target === board) fit(); + }; window.addEventListener('resize', fit); - return () => window.removeEventListener('resize', fit); + board?.addEventListener('transitionend', onTransitionEnd); + return () => { + window.removeEventListener('resize', fit); + board?.removeEventListener('transitionend', onTransitionEnd); + }; }, [isKanban, isKanbanWide, boardColumns.length, selectedListId, loading]); + // One row on the desktop: take back what still overflows (paddings), so the page does not scroll. Measured + // only once the new height is on the page; measured right away, the old layout (e.g. two tall rows before + // stretching the board to full width) counted as overflow and squeezed the columns to their minimum. + useLayoutEffect(() => { + if (!kanbanColHeight || kanbanMultiRow || kanbanPhoneSnap) return; + const area = kanbanBoardRef.current?.closest('[data-app-scroll]'); + if (!area) return; + const over = area.scrollHeight - area.clientHeight; + if (over > 0) setKanbanColHeight((h) => (h ? Math.max(KANBAN_MIN_COL_HEIGHT, h - over) : h)); + }, [kanbanColHeight, kanbanMultiRow, kanbanPhoneSnap]); + // Several rows: one wheel step moves to the next row (or back up to the previous row / the page top), // smoothly. The browser's own snapping goes back to the nearest point, so a wheel step shorter than a row // never got past the first one. A column whose cards can still scroll that way scrolls first; Ctrl +