fixed table formatting and added a scroll bar

This commit is contained in:
Carter 2026-03-13 14:57:42 -06:00
parent 9e3ce3c00d
commit e732cab837

View file

@ -15,11 +15,10 @@ const useStyles = makeStyles((theme: Theme) => {
border: "none" border: "none"
}, },
tableContainer: { tableContainer: {
// margin: theme.spacing(1), width: "100%",
// [theme.breakpoints.up("sm")]: { maxWidth: "100%",
// margin: theme.spacing(2) overflow: "hidden",
// }, minWidth: 0,
// width: "auto"
}, },
title: { title: {
padding: theme.spacing(1), padding: theme.spacing(1),
@ -75,6 +74,53 @@ export interface Column<T> {
disableSort?: boolean; disableSort?: boolean;
} }
function ResizableHeaderTitle<T>(props: {
column: Column<T>;
index: number;
columnsLength: number;
resizeable: boolean;
onColumnClick: (column: Column<T>) => void;
showOrderIcon: (column: Column<T>) => React.ReactNode;
}) {
const { column, index, columnsLength, resizeable, onColumnClick, showOrderIcon } = props;
const titleRef = useRef<HTMLDivElement>(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 (
<Grid2
ref={titleRef}
alignItems="center"
display="flex"
onClick={() => !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%)",
}
: {}),
}}
>
<Box component="span" sx={{ whiteSpace: "nowrap" }}>
{column.title} {showOrderIcon(column)}
</Box>
</Grid2>
);
}
interface Props<T> { interface Props<T> {
rows: T[], rows: T[],
columns?: Column<T>[] | (() => Column<T>[]), columns?: Column<T>[] | (() => Column<T>[]),
@ -483,11 +529,15 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
if (!dragStart) return if (!dragStart) return
let newWidths: number[] = [...rowWidths] 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) => { newWidths.every((width, j) => {
if (j <= index || width === 0) return true if (j <= index || width === 0) return true
else if (newWidths[j] !== undefined) { else if (newWidths[j] !== undefined) {
newWidths[j] = newWidths[j] + (dragStart - e.clientX) newWidths[j] = newWidths[j] + actualDelta
return false return false
} }
}) })
@ -495,8 +545,11 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
} }
const MIN_COLUMN_WIDTH = 24;
return ( return (
<Box className={classes.tableContainer} component={Paper}> <Box className={classes.tableContainer} component={Paper}>
<TableContainer sx={{ overflowX: "auto" }}>
<Table> <Table>
<TableHead className={stickyHeader ? classes.stickyHeader : undefined}> <TableHead className={stickyHeader ? classes.stickyHeader : undefined}>
<TableRow sx={ !title && !setSearchText ? { display: "none" } : undefined}> <TableRow sx={ !title && !setSearchText ? { display: "none" } : undefined}>
@ -552,18 +605,23 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
) )
return ( return (
<TableCell key={"header-cell-"+index} width={rowWidths[index] ? rowWidths[index] : undefined}> <TableCell key={"header-cell-"+index} width={rowWidths[index] ? rowWidths[index] : undefined}>
<Grid2 container spacing={1} justifyContent={"space-between"}>
<Grid2 <Grid2
alignItems="center" container
display="flex" spacing={1}
onClick={() => !column.disableSort && columnClick(column)} justifyContent={"space-between"}
sx={{ cursor: column.disableSort ? "default" : "pointer" }} flexWrap="nowrap"
> >
{column.title} {showOrderIcon(column)} <ResizableHeaderTitle
</Grid2> column={column}
index={index}
columnsLength={columns.length}
resizeable={!!resizeable}
onColumnClick={columnClick}
showOrderIcon={showOrderIcon}
/>
{index < columns.length-1 && resizeable && {index < columns.length-1 && resizeable &&
<Grid2 <Grid2
sx={{ cursor: "col-resize", userSelect: "none" }} sx={{ cursor: "col-resize", userSelect: "none", flexShrink: 0 }}
onMouseDown={event => resizeClick(event, index)} onMouseDown={event => resizeClick(event, index)}
> >
| |
@ -672,6 +730,7 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
} }
</TableBody> </TableBody>
</Table> </Table>
</TableContainer>
{!hidePagination && {!hidePagination &&
<TablePagination <TablePagination
rowsPerPageOptions={rowsPerPageOptions ? rowsPerPageOptions : [5, 10, 20]} rowsPerPageOptions={rowsPerPageOptions ? rowsPerPageOptions : [5, 10, 20]}