From e732cab837e3b7cbec501cf5858e291cfe6f1de2 Mon Sep 17 00:00:00 2001 From: Carter Date: Fri, 13 Mar 2026 14:57:42 -0600 Subject: [PATCH] fixed table formatting and added a scroll bar --- src/common/ResponsiveTable.tsx | 93 +++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/src/common/ResponsiveTable.tsx b/src/common/ResponsiveTable.tsx index ef99665..b229475 100644 --- a/src/common/ResponsiveTable.tsx +++ b/src/common/ResponsiveTable.tsx @@ -15,11 +15,10 @@ const useStyles = makeStyles((theme: Theme) => { border: "none" }, tableContainer: { - // margin: theme.spacing(1), - // [theme.breakpoints.up("sm")]: { - // margin: theme.spacing(2) - // }, - // width: "auto" + width: "100%", + maxWidth: "100%", + overflow: "hidden", + minWidth: 0, }, title: { padding: theme.spacing(1), @@ -75,6 +74,53 @@ export interface Column { disableSort?: boolean; } +function ResizableHeaderTitle(props: { + column: Column; + index: number; + columnsLength: number; + resizeable: boolean; + onColumnClick: (column: Column) => void; + showOrderIcon: (column: Column) => React.ReactNode; +}) { + const { column, index, columnsLength, resizeable, onColumnClick, showOrderIcon } = props; + const titleRef = useRef(null); + const [isOverflowing, setIsOverflowing] = useState(false); + + useEffect(() => { + const el = titleRef.current; + if (!el) return; + const checkOverflow = () => setIsOverflowing(el.scrollWidth > el.clientWidth); + checkOverflow(); + const ro = new ResizeObserver(checkOverflow); + ro.observe(el); + return () => ro.disconnect(); + }, []); + + return ( + !column.disableSort && onColumnClick(column)} + sx={{ + cursor: column.disableSort ? "default" : "pointer", + minWidth: 0, + overflow: "hidden", + ...(isOverflowing && resizeable && index < columnsLength - 1 + ? { + maskImage: "linear-gradient(to right, black 75%, transparent 100%)", + WebkitMaskImage: "linear-gradient(to right, black 75%, transparent 100%)", + } + : {}), + }} + > + + {column.title} {showOrderIcon(column)} + + + ); +} + interface Props { rows: T[], columns?: Column[] | (() => Column[]), @@ -483,11 +529,15 @@ export default function ResponsiveTable(props: Props) { if (!dragStart) return let newWidths: number[] = [...rowWidths] - newWidths[index] = newWidths[index] - (dragStart - e.clientX) + const delta = dragStart - e.clientX + const newWidthForIndex = newWidths[index] - delta + const clampedWidth = Math.max(MIN_COLUMN_WIDTH, newWidthForIndex) + const actualDelta = newWidths[index] - clampedWidth + newWidths[index] = clampedWidth newWidths.every((width, j) => { if (j <= index || width === 0) return true else if (newWidths[j] !== undefined) { - newWidths[j] = newWidths[j] + (dragStart - e.clientX) + newWidths[j] = newWidths[j] + actualDelta return false } }) @@ -495,8 +545,11 @@ export default function ResponsiveTable(props: Props) { } + const MIN_COLUMN_WIDTH = 24; + return ( + @@ -552,18 +605,23 @@ export default function ResponsiveTable(props: Props) { ) return ( - - !column.disableSort && columnClick(column)} - sx={{ cursor: column.disableSort ? "default" : "pointer" }} - > - {column.title} {showOrderIcon(column)} - + + {index < columns.length-1 && resizeable && resizeClick(event, index)} > | @@ -672,6 +730,7 @@ export default function ResponsiveTable(props: Props) { }
+
{!hidePagination &&