diff --git a/apps/web/components/kanban-column.tsx b/apps/web/components/kanban-column.tsx index c5007f1a23..a9e3876921 100644 --- a/apps/web/components/kanban-column.tsx +++ b/apps/web/components/kanban-column.tsx @@ -1,6 +1,7 @@ "use client"; -import { memo, useMemo } from "react"; +import { memo, useCallback, useMemo, type Ref } from "react"; +import { useColumnNaturalHeight } from "@/hooks/domains/kanban/use-column-natural-height"; import { useDroppable } from "@dnd-kit/core"; import { Task, type KanbanPresentation } from "./kanban-card"; import { Badge } from "@kandev/ui/badge"; @@ -26,6 +27,7 @@ export interface WorkflowStep { } interface KanbanColumnProps { + onNaturalHeightChange?: (stepId: string, height: number) => void; step: WorkflowStep; tasks: Task[]; presentation?: KanbanPresentation; @@ -48,7 +50,15 @@ interface KanbanColumnProps { externalLinkAvailability: KanbanExternalLinkAvailability; } -function ColumnHeader({ step, tasks }: { step: WorkflowStep; tasks: Task[] }) { +function ColumnHeader({ + step, + tasks, + headerRef, +}: { + step: WorkflowStep; + tasks: Task[]; + headerRef: Ref; +}) { const { t } = useTranslation(); const admittedTaskCount = countAdmittedTasks(tasks); const overWipLimit = isOverWipLimit(admittedTaskCount, step.wip_limit); @@ -56,7 +66,7 @@ function ColumnHeader({ step, tasks }: { step: WorkflowStep; tasks: Task[] }) { const queuedCount = partitionWipTasks(tasks, step.id).queued.length; return ( -
+

{step.title}

@@ -102,6 +112,7 @@ function externalLinkAvailabilityEqual( function columnCallbacksEqual(previous: KanbanColumnProps, next: KanbanColumnProps): boolean { return ( + previous.onNaturalHeightChange === next.onNaturalHeightChange && previous.onPreviewTask === next.onPreviewTask && previous.onOpenTask === next.onOpenTask && previous.onEditTask === next.onEditTask && @@ -137,6 +148,7 @@ function kanbanColumnPropsEqual(previous: KanbanColumnProps, next: KanbanColumnP } export const KanbanColumn = memo(function KanbanColumn({ + onNaturalHeightChange, step, tasks, presentation = "desktop", @@ -160,6 +172,17 @@ export const KanbanColumn = memo(function KanbanColumn({ const { setNodeRef, isOver } = useDroppable({ id: step.id, }); + const { columnRef, headerRef, onContentHeightChange } = useColumnNaturalHeight( + step.id, + onNaturalHeightChange, + ); + const setColumnRef = useCallback( + (element: HTMLDivElement | null) => { + columnRef.current = element; + setNodeRef(element); + }, + [columnRef, setNodeRef], + ); const activeWorkspaceId = useAppStore((state) => state.workspaces.activeId); // Access repositories from store to pass repository names to cards @@ -176,7 +199,7 @@ export const KanbanColumn = memo(function KanbanColumn({ return (
{/* Column Header */} - {!hideHeader && } + {!hideHeader && } ReactNode; @@ -34,6 +35,7 @@ type PanStart = { }; export function AdaptiveDesktopKanban({ + columnHeight, steps, isDragging = false, renderColumn, @@ -81,7 +83,11 @@ export function AdaptiveDesktopKanban({ }; return ( -
+
))}
- {isDragging && ( -
); } +function DragEndReserve() { + return ( +