question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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.

image

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.

image

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
chilversccommented, Apr 8, 2020

What I tried at first was wrapping a ThemeProvider around just the TableHead 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/

createMuiTheme({
  overrides: {
    MuiTableSortLabel: {
      root: {
        color: "white"
      },
      active: {
        color: "white"
      },
      icon: {
        color: "white"
      }
    }
  }
});

However, the actual code needed is this

createMuiTheme({
  overrides: {
    MuiTableSortLabel: {
      root: {
        color: "white",
        "&:focus": {
          color: "#ccc"
        },
        "&:hover": {
          color: "#ccc"
        },
        "&$active": {
          color: "white",
          "&& $icon": {
            color: "white"
          }
        }
      }
    }
  }
});

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:

    '&$active': {
      color: theme.palette.text.primary,
      '&& $icon': {
        opacity: 1,
        color: theme.palette.text.secondary,
      },
    },

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.

0reactions
chilversccommented, Apr 9, 2020

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:

  1. Should palettes include extra options for table headers?
  • This needs a way to cascade to components used within the header.
  1. Make more use of cascading styles.
  • Inherit text, border, background colours from the container.
  • Fewer elements should explicitly set their text/background/border colours.
  • This needs to include components such as the table sort icon.
  • Ideally this would mean any simple component would even render correctly inside an alert.
  1. Some how the palette for text, background, borders, primary, secondary, accent, etc. needs to be linked to the background colour.
  • This seems a lot like switching theme/palette.
  • Does this have an parallels with the concept that tables can be dense?

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.

NOTE: I’m not sure how well this will translate to the current material design where the components seem to be attempting their best to isolate themselves from cascading styles.

The end result is you might end up with like:

p { color: black }
.icon { color: #333 }

.danger p { color: red }
.danger .icon { color: #300 }

Thus then in the html you would have:

<table>
  <thead class="danger">
     ...
  </thead>
  ...
</table>

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:

// inside light theme (main)
<div>
  <span class="MuiCheckbox-colorSecondary">
</div>

// inside dark theme (nested)
<div>
  <span class="MuiCheckbox-colorSecondary-308">
</div>

These are logically the same component, just with different styles so I’d have been expecting both class names to be the same:

// Same as before since this is the main style
<div>
  // Where possible we shouldn't create component specific styles
  // this would allow one common style that defines the secondary colours
  <span class="MuiCheckbox colorSecondary">
</div>

// switch to the dark theme within this div
<div class="theme-308">
  <span class="MuiCheckbox colorSecondary">
</div>

.colorSecondary {
    color: #f50057
    background: ...
    border-color: ...
    // etc
}

.theme-308 .colorSecondary {
    color: #f50057
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Better support for table headers · Issue #20460 - GitHub
Summary. Table headers often want styling separately to the rest of the table. This styling needs to easily cascade to all the elements ......
Read more >
Column Headers and Browser Support - Adrian Roselli
Changing Column Headers Mid-Table #anchor. There are <th> es in the first row, and then more <th> es in the middle of the ......
Read more >
PowerPoint: Use table headers - Microsoft Support
Table headers make content readable and much more accessible to screen reader users as they provide navigation information to assistive technologies.
Read more >
<th>: The Table Header element - HTML - MDN Web Docs
The HTML element defines a cell as header of a group of table cells. The exact nature of this group is defined by...
Read more >
Add support for tables with two headers in views ... - Drupal
Recently #1831162: Tables generated by Views need better semantics. added the scope="col" for column header elements, but did not add any ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found