How to add Backdrop that overlays single component such as Paper rather than entire screen

Viewed 6143

The standard Backdrop implementation overlays the entire screen with a loading indicator.

I have a table within a Paper component that I'm doing server-side pagination/loading and I want to display an overlay just over the Paper or even just the TableBody while loading.

Does anyone know how this could be achieved?

Thanks!

1 Answers

Below are the default styles for Backdrop:

export const styles = {
  /* Styles applied to the root element. */
  root: {
    // Improve scrollable dialog support.
    zIndex: -1,
    position: 'fixed',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    right: 0,
    bottom: 0,
    top: 0,
    left: 0,
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
    WebkitTapHighlightColor: 'transparent',
  },
  /* Styles applied to the root element if `invisible={true}`. */
  invisible: {
    backgroundColor: 'transparent',
  },
};

You can see that the approach it uses for covering the whole screen is to use right, bottom, top, and left of zero along with a position of fixed. By changing the position to absolute, it will instead cover its closest positioned ancestor. This means that you will want to change the containing Paper to have a position of relative (unless it already had a position of absolute). You also need to adjust the z-index of the backdrop, since it defaults to -1 which will put it behind other things in the current stacking context (such as the Paper it is contained within).

Below is a working example:

import React from "react";
import CssBaseline from "@material-ui/core/CssBaseline";
import Paper from "@material-ui/core/Paper";
import { withStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Backdrop from "@material-ui/core/Backdrop";
import Button from "@material-ui/core/Button";

const StyledPaper = withStyles({
  root: {
    height: 200,
    position: "relative"
  }
})(Paper);
const LimitedBackdrop = withStyles({
  root: {
    position: "absolute",
    zIndex: 1
  }
})(Backdrop);
export default function App() {
  const [showBackdrop, setShowBackdrop] = React.useState(false);
  return (
    <div>
      <CssBaseline />
      <Grid container spacing={2}>
        <Grid item xs={6}>
          <StyledPaper>
            <LimitedBackdrop open={showBackdrop}>
              <Button onClick={e => setShowBackdrop(!showBackdrop)}>
                Hide Backdrop
              </Button>
            </LimitedBackdrop>
            <div>
              Paper 1<br />
              {!showBackdrop && (
                <Button onClick={e => setShowBackdrop(!showBackdrop)}>
                  Show Backdrop
                </Button>
              )}
            </div>
          </StyledPaper>
        </Grid>
        <Grid item xs={6}>
          <StyledPaper>Paper 2</StyledPaper>
        </Grid>
      </Grid>
    </div>
  );
}

Edit Backdrop within parent

Related