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
Asked
Active
Viewed 134 times
0

Olivier Tassinari
- 8,238
- 4
- 23
- 23

Ishaan Kanwar
- 399
- 1
- 4
- 16
5 Answers
3
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>
);
}

Andrew
- 630
- 1
- 5
- 14
1
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";
};

Tonny Liu
- 101
- 3
-
Doesn't work if you click on a higher number first and then a lower number – Ishaan Kanwar Mar 14 '23 at 13:45
-
ok, now the answer is right – Tonny Liu Mar 14 '23 at 13:51
1
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>
);
}

mahan
- 12,366
- 5
- 48
- 83
0
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

Nirav Jethva
- 116
- 2
0
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";
}
};

fOURP
- 74
- 5