Fix column resizing in Pricing table

Improve resize logic with proper mouse delta calculation
This commit is contained in:
Christian Vidal Wolf
2026-04-21 08:49:02 +02:00
parent b4cb7cbe57
commit 964bb62838
+25 -18
View File
@@ -51,8 +51,15 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
const [filterMode, setFilterMode] = useState<FilterMode>('all_errors');
const [search, setSearch] = useState('');
const [searchMode, setSearchMode] = useState<'all' | 'selected'>('all');
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({
articleNo: 100,
articleName: 220,
line: 100,
classification: 130,
});
const [resizingColumn, setResizingColumn] = useState<string | null>(null);
const [resizeStartX, setResizeStartX] = useState<number | null>(null);
const [resizeStartWidth, setResizeStartWidth] = useState<number | null>(null);
const tableRef = useRef<HTMLTableElement>(null);
const [editingCell, setEditingCell] = useState<EditingCell | null>(null);
const [savingCell, setSavingCell] = useState<{ rowIndex: number; colIndex: number } | null>(null);
@@ -114,36 +121,36 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
setSearchMode('all');
};
const handleResizeStart = (e: React.MouseEvent, colKey: string) => {
const handleResizeStart = (e: React.MouseEvent, colKey: string, currentWidth: number) => {
e.preventDefault();
e.stopPropagation();
setResizingColumn(colKey);
setResizeStartX(e.clientX);
setResizeStartWidth(currentWidth);
};
React.useEffect(() => {
if (!resizingColumn || resizeStartX === null || resizeStartWidth === null) return;
const handleMouseMove = (e: MouseEvent) => {
if (!resizingColumn || !tableRef.current) return;
const th = tableRef.current.querySelector(`th[data-col-key="${resizingColumn}"]`) as HTMLElement;
if (!th) return;
const rect = th.getBoundingClientRect();
const newWidth = e.clientX - rect.left;
if (newWidth >= 50 && newWidth <= 400) {
const delta = e.clientX - resizeStartX;
const newWidth = Math.max(50, Math.min(400, resizeStartWidth + delta));
setColumnWidths(prev => ({ ...prev, [resizingColumn]: newWidth }));
}
};
const handleMouseUp = () => {
setResizingColumn(null);
setResizeStartX(null);
setResizeStartWidth(null);
};
if (resizingColumn) {
document.addEventListener('mousemove', handleMouseMove as any);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
return () => {
document.removeEventListener('mousemove', handleMouseMove as any);
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
}
}, [resizingColumn]);
}, [resizingColumn, resizeStartX, resizeStartWidth]);
// ── Dynamic column detection ──────────────────────────────────────────────
const { uvpIdx, srpCols, containerCols } = useMemo(() => {
@@ -656,7 +663,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
<tr>
<th data-col-key="articleNo" style={{ width: columnWidths.articleNo || 100 }} className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 whitespace-nowrap relative">
Art. No.
<div onMouseDown={(e) => handleResizeStart(e, 'articleNo')} className="absolute right-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-blue-500/30" />
<div onMouseDown={(e) => handleResizeStart(e, 'articleNo', columnWidths.articleNo || 100)} className="absolute right-0 top-0 bottom-0 w-2 cursor-col-resize hover:bg-blue-500/30" />
</th>
<th data-col-key="articleName" style={{ width: columnWidths.articleName || 220 }} className="text-left px-3 py-3 text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-700 group relative">
<div className="flex items-center gap-1"><span>Article Name</span>
@@ -923,9 +930,9 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
<tr
key={dataIndex}
className={cn(
'border-b border-slate-700/50 transition-colors hover:bg-slate-700/20',
'border-b border-slate-700/50 transition-colors',
isValidated
? 'bg-emerald-500/10'
? 'bg-green-400/30 border-l-4 border-l-green-400' // Vibrant high-visibility green
: saveStatus === 'error'
? 'bg-red-400/20 border-l-4 border-l-red-500'
: saveStatus === 'pending'
@@ -1068,7 +1075,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
<td className={cn(
"px-2 py-2.5 sticky right-0 shadow-[-4px_0_8px_rgba(0,0,0,0.1)] transition-colors",
isValidated ? "bg-[#1e2a25]" : "bg-slate-800",
isValidated ? "bg-[#1b4d24]" : "bg-slate-800",
"group-hover:bg-slate-700/40"
)}>
<button