gregnb / mui-datatables

Datatables for React using Material-UI
MIT License
2.7k stars 931 forks source link

Sorting columns shifts header #742

Open alexanderwhatley opened 5 years ago

alexanderwhatley commented 5 years ago

The fixedHeader option does not appear to work when you sort the columns of a table, even if you set the width. Shown here is an example: https://codesandbox.io/s/muidatatables-sorting-header-1tkh7. If you sort by the "Name" column, you'll see that the headers all shift, which is not good user experience.

Is there any way to fix the columns even if you are sorting, and truncate the parts of the string that are longer than the column's width? This was possible by default in the Table component in the original Material-UI.

gabrielliwerant commented 5 years ago

Actually, the material-ui table exhibits the same behavior. When there are cells with content that is much greater than the other cells, it will also flip back and forth in widths during sorting and other behaviors that change the content.

You cannot solve this problem without enabling your content to be broken up, otherwise the width will always change to accommodate the content.

You can use:

word-break: break-word;
white-space: pre-wrap;

But you'll also need to fix the width of the select box column. Also, your version of this library is out of date, according to your codesandbox example, so be aware that old versions are not supported.

alexanderwhatley commented 5 years ago

@gabrielliwerant thanks for your reply. I'm in the process of switching from Material UI v0 into v1 right now, and the basic behavior of sorting and column width appears different. I made an example of string truncation in v0 to illustrate the difference I am describing: https://codesandbox.io/s/mui-v0-sorting-header-yzysn. You can see that here, the longer strings are truncated with an ellipsis. Using your CSS, the strings were merely broken into multiple lines, which looks quite ugly to the user.

I tried to replicate the v0 behavior in MUI Datatables using the following CSS:

const theme = createMuiTheme({
  overrides: {
    MUIDataTableToolbar: {
      root: {
        background: grey300
      }
    },
    MUIDataTableHeadCell: {
      root: {
        height: 56,
        fontFamily: "Oxygen",
        fontSize: 10,
        paddingLeft: 24,
        paddingRight: 24,
        overflow: "hidden",
        whiteSpace: 'pre-wrap',
        textOverflow: 'ellipsis',
        position: 'relative'
      }
    },
    MUIDataTableBodyCell: {
      root: {
        height: 48,
        fontFamily: "Oxygen",
        fontSize: 12,
        paddingLeft: 24,
        paddingRight: 24,
        overflow: "hidden",
        whiteSpace: 'pre-wrap',
        textOverflow: 'ellipsis',
        position: 'relative'
      }
    },
    MUIDataTableBody: {
      root: {
        overflow: "hidden",
        whiteSpace: 'pre-wrap',  
        textOverflow: 'clip'
      }
    },
    MUIDataTableColumn: {
      row: {
        height: 48,
        paddingLeft: 24,
        paddingRight: 24,
        overflow: "hidden",
        whiteSpace: 'pre-wrap',
        textOverflow: 'ellipsis',
      }
    },
    MUIDataTablePagination: {
      root: {
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        textAlign: "center"
      },
      caption: {
        fontSize: 12
      }
    }
  }
});

However, this did not work, and the ellipsis and fixed column widths did not appear. Do you know how I can achieve this? Thanks.

gabrielliwerant commented 5 years ago

It may look ugly, but with truncation via ellipsis, the user will not even be able to read the content, so both methods have advantages and disadvantages. Personally, my preference is to allow content to dictate the size of html elements, and to handle extreme cases on a case-by-case basis.

As far as your specific issue, I'm afraid I can't offer much help on versions of the library that are as low as you are using. text-overflow only works when content is overflowing a block container. Table cells use a different means of display. So this is going to be difficult to achieve via pure CSS in modern tables. You may need to dynamically truncate text on your end.

alexanderwhatley commented 5 years ago

I solved the problem using the folloing CSS:

const theme = createMuiTheme({
  overrides: {
    MUIDataTableToolbar: {
      root: {
        background: grey300
      }
    },
    MUIDataTableHeadCell: {
      root: {
        height: 56,
        fontFamily: "Oxygen",
        fontSize: 12,
        overflow: "hidden",
        whiteSpace: "nowrap",
        textOverflow: "ellipsis",
        position: "relative"
      }
    },
    MUIDataTableBodyCell: {
      root: {
        height: 48,
        fontFamily: "Oxygen",
        fontSize: 13,
        overflow: "hidden",
        whiteSpace: "nowrap",
        textOverflow: "ellipsis",
        position: "relative",
        maxWidth: 0
      }
    },
    MUIDataTablePagination: {
      root: {
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        textAlign: "center"
      },
      caption: {
        fontSize: 12
      }
    }
  }
});