skip to Main Content

enter image description here

I want to achieve something like this, when I click on 20 numbered block, everything before that changes to light orange.
I have this attached sandbox code, if anyone can guide what to add in the handleClick function would be grateful
https://codesandbox.io/s/adoring-cherry-by6u9b?file=/demo.tsx

5

Answers


  1. You can manage one state to store the selected block. Now, we can pass props to block based on this state.

    Check out the working demo here:
    https://codesandbox.io/s/floral-leaf-neuuku?file=/demo.tsx

    Login or Signup to reply.
  2. Made some changes in your playground: codesandbox.io

    Basic idea is that you need to save the current clicked index and then to pass the custom backgroundColor property to your styled component if the element’s index is smaller than the clicked index.

    const Item = styled(Paper)(({ theme, customBackground }) => ({
      backgroundColor: customBackground
        ? customBackground
        : theme.palette.mode === "dark"
        ? "#1A2027"
        : "#fff",
      ...theme.typography.body2,
      padding: theme.spacing(2),
      textAlign: "center",
      color: theme.palette.text.secondary
    }));
    
    export default function ResponsiveGrid() {
      const [selectedIndex, setSelectedIndex] = React.useState(null);
    
      const handleClick = React.useCallback((e, index) => {
        setSelectedIndex(index);
      }, []);
    
      return (
        <Box sx={{ flexGrow: 1 }}>
          <Grid container spacing={{ xs: 0.5 }} columns={{ xs: 8 }}>
            {Array.from(Array(102)).map((_, index) => (
              <Grid xs={2} key={index}>
                <Item
                  customBackground={
                    index < selectedIndex
                      ? "orange"
                      : index === selectedIndex
                      ? "darkorange"
                      : "white"
                  }
                  onClick={(e) => handleClick(e, index)}
                >
                  {index + 1}
                </Item>
              </Grid>
            ))}
          </Grid>
        </Box>
      );
    }
    
    Login or Signup to reply.
  3. You can also do it like that although i am not sure if it’s very efficient.

    const handleClick = (e, index) => {
      const arr = document.getElementsByClassName("MuiPaper-root"); //some class
    
      for (i=0; i < index; i++) {
        arr[i].style.backgroundColor = "orange";
      }
    };
    
    Login or Signup to reply.
  4. change demo.tsx:

    import * as React from "react";
    import { experimentalStyled as styled } from "@mui/material/styles";
    import Box from "@mui/material/Box";
    import Paper from "@mui/material/Paper";
    import Grid from "@mui/material/Unstable_Grid2";
    
    const Item = styled(Paper)(({ theme }) => ({
      backgroundColor: theme.palette.mode === "dark" ? "#1A2027" : "#fff",
      ...theme.typography.body2,
      padding: theme.spacing(2),
      textAlign: "center",
      color: theme.palette.text.secondary
    }));
    
    const handleClick = (e, index) => {
      const gridItems = document.querySelectorAll(".grid-item");
      for (let i = 0; i < gridItems.length; i++) {
        const element = gridItems[i];
        if (element.dataset.index > index) {
          element.style.backgroundColor = "#fff"; //
        }
        if (element.dataset.index < index) {
          element.style.backgroundColor = "#ffa50036"; // light orange
        }
      }
      e.target.style.backgroundColor = "orange";
    };
    
    export default function ResponsiveGrid() {
      return (
        <Box sx={{ flexGrow: 1 }}>
          <Grid container spacing={{ xs: 0.5 }} columns={{ xs: 8 }}>
            {Array.from(Array(102)).map((_, index) => (
              <Grid xs={2} key={index}>
                <Item
                  className="grid-item"
                  data-index={index + 1}
                  onClick={(e) => handleClick(e, index + 1)}
                >
                  {index + 1}
                </Item>
              </Grid>
            ))}
          </Grid>
        </Box>
      );
    }
    

    Here is the two key points:

    <Item
                  className="grid-item"
                  data-index={index + 1}
                  onClick={(e) => handleClick(e, index + 1)}
                >
                  {index + 1}
                </Item>
    

    and,

    const handleClick = (e, index) => {
      const gridItems = document.querySelectorAll(".grid-item");
      for (let i = 0; i < gridItems.length; i++) {
        const element = gridItems[i];
        if (element.dataset.index > index) {
          element.style.backgroundColor = "#fff"; //
        }
        if (element.dataset.index < index) {
          element.style.backgroundColor = "#ffa50036"; // light orange
        }
      }
      e.target.style.backgroundColor = "orange";
    };
    
    Login or Signup to reply.
  5. This answer use the same theme as you have used and does not break any style.

    Store the index of the item clicked. And based on it, update the background color.

    const Item = styled(Paper)(({ theme, backgroundColor }) => ({
      backgroundColor:
        backgroundColor !== null
          ? backgroundColor
          : theme.palette.mode === "dark"
          ? "#1A2027"
          : "#fff",
    
      ...theme.typography.body2,
      padding: theme.spacing(2),
      textAlign: "center",
      color: theme.palette.text.secondary,
    }));
    
    export const GridItem = ({ selectedIndex, index, onClick }) => {
      const backgroundColor =
        index === selectedIndex
          ? "orange"
          : index < selectedIndex
          ? "#ffecd8"
          : null;
      return (
        <Grid xs={2}>
          <Item backgroundColor={backgroundColor} onClick={onClick}>
            {index + 1}
          </Item>
        </Grid>
      );
    };
    
    export default function ResponsiveGrid() {
      const [selectedIndex, setSelectedIndex] = React.useState(null);
    
      return (
        <Box sx={{ flexGrow: 1 }}>
          <Grid container spacing={{ xs: 0.5 }} columns={{ xs: 8 }}>
            {Array.from(Array(102)).map((_, index) => (
              <GridItem
                key={index}
                onClick={() => setSelectedIndex(index)}
                index={index}
                selectedIndex={selectedIndex}
              />
            ))}
          </Grid>
        </Box>
      );
    }
    
    
    

    https://codesandbox.io/s/happy-leaf-348miz?file=/demo.tsx

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search