feat(bases): block intra-column drops while sort is active + add hint

This commit is contained in:
Philipinho
2026-05-24 16:17:36 +01:00
parent c91f89a055
commit dba47956b1
4 changed files with 21 additions and 2 deletions
@@ -248,6 +248,11 @@ export function BaseKanban({
))} ))}
</div> </div>
)} )}
{sortsActive && (
<div className={classes.sortHint}>
{t("Sorted — cards within a column can't be reordered.")}
</div>
)}
<div className={classes.board}> <div className={classes.board}>
{columns.map((column) => ( {columns.map((column) => (
<KanbanColumn <KanbanColumn
@@ -259,6 +264,7 @@ export function BaseKanban({
onCardDrop={handleCardDrop} onCardDrop={handleCardDrop}
onColumnReorder={handleColumnReorder} onColumnReorder={handleColumnReorder}
onHide={handleHideColumn} onHide={handleHideColumn}
sortsActive={sortsActive}
/> />
))} ))}
</div> </div>
@@ -14,6 +14,7 @@ type KanbanCardProps = {
primaryProperty: IBaseProperty | undefined; primaryProperty: IBaseProperty | undefined;
onClick: (rowId: string) => void; onClick: (rowId: string) => void;
onDrop: (payload: CardDropPayload) => void; onDrop: (payload: CardDropPayload) => void;
sortsActive: boolean;
}; };
export function KanbanCard({ export function KanbanCard({
@@ -22,12 +23,14 @@ export function KanbanCard({
primaryProperty, primaryProperty,
onClick, onClick,
onDrop, onDrop,
sortsActive,
}: KanbanCardProps) { }: KanbanCardProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { ref, isDragging, closestEdge } = useKanbanCardDrag({ const { ref, isDragging, closestEdge } = useKanbanCardDrag({
cardId: row.id, cardId: row.id,
columnKey, columnKey,
onDrop, onDrop,
sortsActive,
}); });
const titleValue = primaryProperty const titleValue = primaryProperty
@@ -16,6 +16,7 @@ type KanbanColumnProps = {
onCardDrop: (payload: CardDropPayload) => void; onCardDrop: (payload: CardDropPayload) => void;
onColumnReorder: (payload: ColumnReorderPayload) => void; onColumnReorder: (payload: ColumnReorderPayload) => void;
onHide: (columnKey: string) => void; onHide: (columnKey: string) => void;
sortsActive: boolean;
}; };
export function KanbanColumn({ export function KanbanColumn({
@@ -26,6 +27,7 @@ export function KanbanColumn({
onCardDrop, onCardDrop,
onColumnReorder, onColumnReorder,
onHide, onHide,
sortsActive,
}: KanbanColumnProps) { }: KanbanColumnProps) {
const { ref: bodyRef, isOver } = useKanbanColumnDrop({ const { ref: bodyRef, isOver } = useKanbanColumnDrop({
columnKey: column.key, columnKey: column.key,
@@ -56,6 +58,7 @@ export function KanbanColumn({
primaryProperty={primaryProperty} primaryProperty={primaryProperty}
onClick={onCardClick} onClick={onCardClick}
onDrop={onCardDrop} onDrop={onCardDrop}
sortsActive={sortsActive}
/> />
))} ))}
<KanbanAddCardButton onClick={() => onAddCard(column.key)} /> <KanbanAddCardButton onClick={() => onAddCard(column.key)} />
@@ -28,11 +28,13 @@ export function useKanbanCardDrag({
cardId, cardId,
columnKey, columnKey,
onDrop, onDrop,
sortsActive,
disabled, disabled,
}: { }: {
cardId: string; cardId: string;
columnKey: string; columnKey: string;
onDrop: (payload: CardDropPayload) => void; onDrop: (payload: CardDropPayload) => void;
sortsActive: boolean;
disabled?: boolean; disabled?: boolean;
}) { }) {
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
@@ -61,7 +63,12 @@ export function useKanbanCardDrag({
element: el, element: el,
canDrop: ({ source }) => { canDrop: ({ source }) => {
if (source.data.type !== "base-kanban-card") return false; if (source.data.type !== "base-kanban-card") return false;
return source.data.cardId !== cardId; if (source.data.cardId === cardId) return false;
// Block intra-column drops when a sort is active (the slot would
// visibly snap back to the sort's chosen position, confusing the
// user). Cross-column drops still work and change the cell value.
if (sortsActive && source.data.columnKey === columnKey) return false;
return true;
}, },
getData: ({ input, element }) => getData: ({ input, element }) =>
attachClosestEdge( attachClosestEdge(
@@ -85,7 +92,7 @@ export function useKanbanCardDrag({
}, },
}), }),
); );
}, [cardId, columnKey, disabled]); }, [cardId, columnKey, disabled, sortsActive]);
return { ref, isDragging, closestEdge }; return { ref, isDragging, closestEdge };
} }