A kanban-style board column component with drag-and-drop support, infinite scroll, collapse/expand behavior, and ticket card rendering. ## Key Components ### `BoardColumn` (exported) The primary column container. Renders a collapsible column with a header, divider, and body. Supports visual joining with adjacent columns via `joinLeft`/`joinRight` props and applies tinted background colors for non-system columns. ### `ColumnBody` (internal) Handles the lane-wide drop target, drag auto-scroll, and infinite scroll via `IntersectionObserver`. Each card is a drop target in its own right and is reported ahead of the lane, so the lane only ever answers for the gaps between them — and it answers with the **nearest card and the edge of it the pointer is on**, exactly as that card would have. Reporting a bare lane there sent the ticket to the BOTTOM of the column, which made small moves look like they had not registered and large ones like the only thing that worked. Auto-scroll on the lane is `autoScrollColumn`: vertical-only overflow reach, so a pointer carried below the board scrolls exactly the one lane it is under — a reach that also spread sideways put that pointer inside every lane's region at once and scrolled them all. The page's own scrollers are registered once by the board, not per lane. The lane body reserves a `py-[5px]` sliver so the insertion line is not clipped at the first and last card. ### `SkeletonStack` (internal) Renders a configurable number of `TicketCardSkeleton` placeholders during initial load. ### `EmptyState` (internal) Displays a centered empty state with a tag icon when a column has no tickets — and carries the insertion line when a drop is aimed at the empty lane, since there is no card to hang it off. ## Key Props (`BoardColumnProps`) | Prop | Type | Description | |---|---|---| | `column` | `BoardColumnDef` | Column definition including tickets, color, and state flags | | `collapsed` | `boolean` | Collapses column to `w-14` | | `onToggleCollapse` | `(columnId: string) => void` | Toggle handler — takes the id so one stable handler can serve every lane | | `onLoadMore` | `(columnId: string) => void` | Triggered by intersection sentinel | | `joinLeft` / `joinRight` | `boolean` | Removes borders/radius for adjacent column groups | | `renderAssignSlot` | `(ticket: BoardTicket) => ReactNode` | Custom assignee slot renderer | ## Usage Example ```typescript openNewTicketModal(colId)} getTicketHref={(ticketId) => `/tickets/${ticketId}`} renderAssignSlot={(ticket) => } onApprove={(ticketId) => approveTicket(ticketId)} onLoadMore={(colId) => fetchMoreTickets(colId)} joinLeft /> ```