Fix ColumnFilterPopover single-click and drag-selection interaction

This commit is contained in:
Christian Vidal Wolf
2026-04-20 16:42:07 +02:00
parent 1d9e77038a
commit 23074ed42f
+13 -3
View File
@@ -44,6 +44,7 @@ export function ColumnFilterPopover({
const selectedValuesRef = React.useRef<string[]>(selectedValues); const selectedValuesRef = React.useRef<string[]>(selectedValues);
const onSelectAllRef = React.useRef(onSelectAll); const onSelectAllRef = React.useRef(onSelectAll);
const filteredValuesRef = React.useRef(filteredValues); const filteredValuesRef = React.useRef(filteredValues);
const didDragRef = React.useRef(false);
selectedValuesRef.current = selectedValues; selectedValuesRef.current = selectedValues;
onSelectAllRef.current = onSelectAll; onSelectAllRef.current = onSelectAll;
@@ -53,6 +54,7 @@ export function ColumnFilterPopover({
isDraggingRef.current = true; isDraggingRef.current = true;
dragStartRef.current = index; dragStartRef.current = index;
hoveredIndexRef.current = index; hoveredIndexRef.current = index;
didDragRef.current = false;
setIsDragging(true); setIsDragging(true);
setDragStart(index); setDragStart(index);
setHoveredIndex(index); setHoveredIndex(index);
@@ -70,14 +72,21 @@ export function ColumnFilterPopover({
if (isDraggingRef.current) { if (isDraggingRef.current) {
const start = dragStartRef.current; const start = dragStartRef.current;
const end = hoveredIndexRef.current; const end = hoveredIndexRef.current;
if (start !== null && end !== null) {
// Only trigger special drag-select if it covered more than one item
if (start !== null && end !== null && start !== end) {
const s = Math.min(start, end); const s = Math.min(start, end);
const e = Math.max(start, end); const e = Math.max(start, end);
const itemsToSelect = filteredValuesRef.current.slice(s, e + 1).map(v => v); const itemsToSelect = filteredValuesRef.current.slice(s, e + 1);
const newSelected = new Set([...selectedValuesRef.current]); const newSelected = new Set([...selectedValuesRef.current]);
itemsToSelect.forEach(v => newSelected.add(v)); itemsToSelect.forEach(v => newSelected.add(v));
onSelectAllRef.current(Array.from(newSelected)); onSelectAllRef.current(Array.from(newSelected));
// Set flag to prevent subsequent click event from toggling the end item
didDragRef.current = true;
setTimeout(() => { didDragRef.current = false; }, 100);
} }
isDraggingRef.current = false; isDraggingRef.current = false;
dragStartRef.current = null; dragStartRef.current = null;
hoveredIndexRef.current = null; hoveredIndexRef.current = null;
@@ -136,7 +145,8 @@ export function ColumnFilterPopover({
onMouseDown={(e) => { e.preventDefault(); handleMouseDown(idx); }} onMouseDown={(e) => { e.preventDefault(); handleMouseDown(idx); }}
onMouseEnter={() => handleMouseEnter(idx)} onMouseEnter={() => handleMouseEnter(idx)}
onClick={(e) => { onClick={(e) => {
if (isDragging) return; // If a drag operation just happened, ignore the click to avoid double-selection issues
if (didDragRef.current) return;
if (e.shiftKey && lastClickedIndex !== null) { if (e.shiftKey && lastClickedIndex !== null) {
const start = Math.min(lastClickedIndex, idx); const start = Math.min(lastClickedIndex, idx);