UI: Add resizable columns to Matrix View. Users can now adjust column widths by dragging, improving data visibility in the All Data view.

This commit is contained in:
Christian Vidal Wolf
2026-04-22 17:09:46 +02:00
parent f01b720c05
commit bf98e4e4ba
+33 -4
View File
@@ -66,6 +66,8 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
return filteredData.slice(start, start + pageSize);
}, [filteredData, page, pageSize]);
const [columnWidths, setColumnWidths] = useState<Record<number, number>>({});
const handleSort = (col: number) => {
if (sortCol === col) {
setSortDesc(!sortDesc);
@@ -75,6 +77,25 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
}
};
const handleResize = (colIndex: number, e: React.MouseEvent) => {
e.preventDefault();
const startX = e.pageX;
const startWidth = columnWidths[colIndex] || 150;
const onMouseMove = (moveEvent: MouseEvent) => {
const newWidth = Math.max(60, startWidth + (moveEvent.pageX - startX));
setColumnWidths(prev => ({ ...prev, [colIndex]: newWidth }));
};
const onMouseUp = () => {
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);
};
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
};
const getUniqueValues = (col: number) => {
const values = data.map(r => String(r[col] || ''));
return Array.from(new Set(values)).sort();
@@ -197,17 +218,18 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
</div>
<div className="overflow-auto flex-1">
<table className="w-full text-left text-sm whitespace-nowrap">
<table className="w-full text-left text-sm whitespace-nowrap" style={{ tableLayout: 'fixed' }}>
<thead className="bg-slate-900/50 text-slate-400 sticky top-0 z-10">
<tr>
{headers.map((header, index) => (
<th
key={index}
className="px-4 py-3 font-medium border-b border-slate-700 transition-colors select-none group relative"
className="px-4 py-3 font-medium border-b border-slate-700 transition-colors select-none group relative border-r border-slate-700/30"
style={{ width: columnWidths[index] || 150, minWidth: columnWidths[index] || 150 }}
>
<div className="flex items-center overflow-hidden">
<span
className="flex items-center gap-1 cursor-pointer hover:text-white"
className="flex items-center gap-1 cursor-pointer hover:text-white truncate"
onClick={() => handleSort(index)}
>
{header}
@@ -229,6 +251,12 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
</button>
</div>
{/* Resizer handle */}
<div
onMouseDown={(e) => handleResize(index, e)}
className="absolute right-0 top-0 bottom-0 w-1 cursor-col-resize hover:bg-blue-500/50 group-hover:bg-slate-700/50 transition-colors z-20"
/>
{openFilterCol === index && (
<ColumnFilterPopover
uniqueValues={getUniqueValues(index)}
@@ -259,7 +287,8 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
return (
<td
key={colIndex}
className="px-4 py-3 text-slate-300 max-w-[200px] truncate"
className="px-4 py-3 text-slate-300 truncate border-r border-slate-700/30"
style={{ width: columnWidths[colIndex] || 150, minWidth: columnWidths[colIndex] || 150 }}
title={String(row[colIndex] || '')}
>
{formattedValue}