'Issue in react MUI table in horizontal scroll when i show button in right side of table on hover

My EditDeleteButton button cell that I am showing button based on hover in a row that working fine I make EditDeleteButton to position: "absolute" and table to position: "relative"

    MuiTableBody: {
      styleOverrides: {
        root: {
          position: "relative",
        },
      },
    },

I set position: "relative" to the table because if I am not set it to relative then in vertical scroll when I scroll down then EditDeleteButton dow in next line of hover so because of that I set table body to "relative"

my EditDeleteButton button cell that I am showing button based on hover in a row that working fine but what my issue is if you see an image its working fine but when in a table horizontal scroll will appear then edit and delete button cell will get move under scroll so If I need to edit or delete it I need to scroll it then I am able to do it the table component I am passing that all this outside of the table in my table component I need to make it like that button will visible right side of the table if horizontal scroll appire or not it will not get affected.

  onMouseEnter: (e) => {
      setHoveredRow(column.index);
   },
   onMouseLeave: (e) => {
     setHoveredRow(null);
   },
  const EditDeleteButton = ({ row }) => {
    return (
      <Box
        display="flex"
        alignItems="center"
        sx={{
          position: "absolute",
          right: 0,
          float: "right",
          height: 35,
        }}
      >
        {row.index === hoveredRow && (
          <>
            <IconButton
              onClick={() => {
                setTeamRowData(row.original);
              }}
              aria-label="edit"
            >
              <Edit />
            </IconButton>
            <IconButton
              onClick={() => {
                setTeamRowData(row.original);
                handleClickOpen();
              }}
              aria-label="delete"
            >
              <Delete />
            </IconButton>
          </>
        )}
      </Box>
    );
  };
  const teamColumns = useMemo(
    () => [
      {
        Header: "Team Name",
        accessor: "teamName",
      },
      {
        Header: "Manager",
        accessor: "managerName",
      },
      {
        Header: "Branch",
        accessor: "branch",
      },
      {
        Header: "Product",
        accessor: "product",
      },
      {
        Header: "date",
        accessor: "date",
      },
      {
        Header: "screen 1",
        accessor: "screen1",
      },
      {
        Header: "screen 2",
        accessor: "screen2",
      },
      {
        Header: "screen 3",
        accessor: "screen3",
      },
      {
        Header: "screen 4",
        accessor: "screen4",
      },
      {
        Header: "screen5",
        accessor: "screen5",
      },
      {
        Header: " ",
        accessor: "button",
        disableSortBy: true,
        minWidth: 1,
        maxWidth: 2,
        Cell: EditDeleteButton,
      },
    ],
    [hoveredRow]
  );

without horizontal scroll works fine image 1

when horizontal scroll appire so I need to scroll to see button see image 2



Solution 1:[1]

Here is a working solution which pins the right column. Codesandbox demo and full code below.

Dynamically-generated table:

Edit dreamy-pasteur-qld66m

Static table:

Edit festive-shape-ch4bgv

enter image description here

Want to pin the left column instead?

  1. In StickyTableCell, simply change right: 0 in both head and body to left: 0
  2. Then wrap the first column in <StickyTableCell> instead of wrapping the last

Full code:

import React from "react";
import {
  makeStyles,
  TableContainer,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
  Table,
  withStyles
} from "@material-ui/core";

const useStyles = makeStyles((theme) => ({
  root: {
    width: "100%",
    marginTop: theme.spacing(3)
  },
  head: {
    backgroundColor: "#fff",
    minWidth: "50px"
  },
  tableContainer: {
    maxHeight: "400px"
  },
  cell: {
    minWidth: "100px"
  }
}));

const StickyTableCell = withStyles((theme) => ({
  head: {
    backgroundColor: theme.palette.common.black,
    color: theme.palette.common.white,
    right: 0,
    position: "sticky",
    zIndex: theme.zIndex.appBar + 2
  },
  body: {
    backgroundColor: "#ddd",
    minWidth: "50px",
    right: 0,
    position: "sticky",
    zIndex: theme.zIndex.appBar + 1
  }
}))(TableCell);

const StyledTableCell = withStyles((theme) => ({
  head: {
    backgroundColor: theme.palette.common.black,
    color: theme.palette.common.white
  },
  body: {
    fontSize: 14
  }
}))(TableCell);

const StyledTableRow = withStyles((theme) => ({
  root: {
    "&:nth-of-type(odd)": {
      backgroundColor: theme.palette.action.hover
    }
  }
}))(TableRow);

const App = () => {
  let id = 0;
  function createData(name, calories, fat, carbs, protein) {
    id += 1;
    return { id, name, calories, fat, carbs, protein };
  }

  const data = [
    createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
    createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
    createData("Eclair", 262, 16.0, 24, 6.0),
    createData("Cupcake", 305, 3.7, 67, 4.3),
    createData("Gingerbread", 356, 16.0, 49, 3.9),
    createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
    createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
    createData("Eclair", 262, 16.0, 24, 6.0),
    createData("Cupcake", 305, 3.7, 67, 4.3),
    createData("Gingerbread", 356, 16.0, 49, 3.9),
    createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
    createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
    createData("Eclair", 262, 16.0, 24, 6.0),
    createData("Cupcake", 305, 3.7, 67, 4.3),
    createData("Gingerbread", 356, 16.0, 49, 3.9),
    createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
    createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
    createData("Eclair", 262, 16.0, 24, 6.0),
    createData("Cupcake", 305, 3.7, 67, 4.3),
    createData("Gingerbread", 356, 16.0, 49, 3.9)
  ];

  const classes = useStyles();

  return (
    <div>
      <TableContainer className={classes.tableContainer}>
        <Table stickyHeader aria-label="sticky table">
          <TableHead>
            <TableRow>
              <StyledTableCell className={classes.head} numeric>
                Dessert (100g serving)
              </StyledTableCell>

              <StyledTableCell className={classes.head} numeric>
                Calories
              </StyledTableCell>

              <StyledTableCell className={classes.head} numeric>
                Fat (g)
              </StyledTableCell>

              <StyledTableCell className={classes.head} numeric>
                Carbs (g)
              </StyledTableCell>

              <StyledTableCell className={classes.head} numeric>
                Protein (g)
              </StyledTableCell>

              <StyledTableCell className={classes.head} numeric>
                Protein (g)
              </StyledTableCell>

              {/** Sticky */}
              <StickyTableCell className={classes.head}>
                <StyledTableCell className={classes.head} numeric>
                  Protein (g)
                </StyledTableCell>
              </StickyTableCell>

            </TableRow>
          </TableHead>
          <TableBody>
            {data.map((n) => {
              return (
                <StyledTableRow key={n.id}>
                  <StyledTableCell
                    numeric
                    align="right"
                    className={classes.cell}
                  >
                    {n.name}
                  </StyledTableCell>

                  <StyledTableCell
                    numeric
                    align="center"
                    className={classes.cell}
                  >
                    {n.fat}
                  </StyledTableCell>

                  <StyledTableCell
                    numeric
                    align="center"
                    className={classes.cell}
                  >
                    {n.carbs}
                  </StyledTableCell>

                  <StyledTableCell
                    numeric
                    align="center"
                    className={classes.cell}
                  >
                    {n.protein}
                  </StyledTableCell>

                  <StyledTableCell
                    numeric
                    align="center"
                    className={classes.cell}
                  >
                    {n.calories}
                  </StyledTableCell>

                  <StyledTableCell
                    numeric
                    align="center"
                    className={classes.cell}
                  >
                    {n.fat}
                  </StyledTableCell>

                  {/** Sticky */}
                  <StickyTableCell>
                    <StyledTableCell
                      numeric
                      align="center"
                      className={classes.cell}
                    >
                      {n.carbs}
                    </StyledTableCell>
                  </StickyTableCell>
                </StyledTableRow>
              );
            })}
          </TableBody>
        </Table>
      </TableContainer>
    </div>
  );
};

export default App;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1