Better support for table headers
See original GitHub issue- I have searched the issues of this repository and believe that this is not a duplicate.
Summary 💡
Table headers often want styling separately to the rest of the table. This styling needs to easily cascade to all the elements within the table header (such as TableSortLabel
). Ideally it would be possible to configure the table styling is part of the theme so that tables have a consistent look across the whole site.
The current examples on https://material-ui.com/components/tables/#customized-tables are too limited. If you try and add a TableSortLabel
to the current example that has a black header you the label ends up with black text on a black background when it is active.
There is no obvious or simple way to correct the sort label, or any other themed component that is added into the table header. Ideally I should be able to set theme for table headers only, that has a specific background, text colour, primary, secondary, etc and have that theme picked up by all the components within the header.
Examples 🌈
As an example it is very simple to render the entire table on a dark background, such as by setting the palette type to dark.
const theme = createMuiTheme({ palette: { type: 'dark' } })
<ThemeProvider theme={theme}>
<MaterialTable .../>
</ThemeProvider>
However, is it much more difficult to acheive this with only the header, as you have to individually override the various background and foreground colors of every element that is rendered into the table header.
A worked example showing some of the issues is at https://codesandbox.io/s/material-demo-g42ox This shows the original enhanced table that has sorting, and then the enhanced table extended with a custom style. Ideally, we would be able to change the theming for the table header without having to modify the enhanced table.
In the example there are two points to take notice of:
- The currently sorted header is not visible (black on black)
- No good choice from the palette for the background/text colours that components can use to ensure consistency across all table like components.
Motivation 🔦
A very common requirement is to have specific styling on table headers (such as a different background, bold text, etc).
It should be as simple as updating the theme to re-style all table headers on the page, and all elements nested within the header. This shouldn’t involve having to pass large collections of classes down the component tree or extend every element with a custom styled one.
Often you do not even have direct access to the underlying header to style it, as its wrapped in other components such as material-table
or mui-datatable
. This can make it even more challenging to correctly theme the TableSortLabel
.
Despite the material design guide not mentioning table headers, every system I use has some sort of alternate style for headers, even when they’re following a material like design. Even the main material.io site has a very light grey background for all of its tables.
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
What I tried at first was wrapping a
ThemeProvider
around just theTableHead
component but that didn’t work (I wasn’t really expecting it to).The trouble I have with overrides is they override those components no matter where they are in the table (even if they’re in the body). Also I found them very difficult to work with as a lot of the internal details for the styles are not documented and you have to dig them out the source code.
For example I expected this to work to override the sort label, based on the docs at https://material-ui.com/api/table-sort-label/
However, the actual code needed is this
Full example https://codesandbox.io/s/mui-table-override-header-issue-7dr5j?file=/src/App.js
Without digging into the source code for that example I don’t know how you would ever find that out, and that is just a single component. Also I feel that is fragile, any small change to the style in the component and the override could stop working.
The part I find most annoying about this is the original style has perfect place holders for all the values I need to change:
So all I really need is a way to say, in a table header, use this palette for the theme.
Because table headers are so ubiquitous, and often all want to share the same common styling, it just seems like I should be able to configure this alternate palette for table headers as part of the theme, and then any component using
<TableHead>
would pick it up, and any components inside the header would also be themed correctly.That’s where I’m not sure at the moment, need to have a good think. I know something is wrong just not sure how best to solve it.
It’s just that branded / styled headers on tables are so common it feels like something that should be trivial to achieve. Instead, as someone coming to the library for the first time I’m immediately having to play around with overriding styles, or customising styles in 3rd party components which is quite complex.
In things like bootstrap, I would just change the palette options for table headers, and most components inherit their text colour while in material I was finding many components explicitly set their text colour.
This leaves me with several main concepts that I’ve been considering:
I wouldn’t want to restrict this to just table headers if possible, as I could a use in also branding other headers, such as for cards to make them stand out in certain conditions.
Using cascading styles
Within bootstrap, I think the standard approach was mixins that accepted a variable, this would then let you quickly create a new class that applies a theme to all the elements within a container that has that class. In material this seems analogous to a theme or a palette.
The end result is you might end up with like:
Thus then in the html you would have:
The idea here is the main classes used on the individual elements shouldn’t change their name, thus you don’t have
.icon-danger
and need to then use.icon-danger
within a danger section. However, I think in Material UI (correct me if this is wrong), when you change the theme, all the class names are going to change? When really the class names should remain the same, and a new set of styles should be generated, scoped to that theme (which selected by apply a class to the container).As an example, when using multiple themes you end up with:
These are logically the same component, just with different styles so I’d have been expecting both class names to be the same: