I'm trying to create a pretty specific component that should look like this:
I give it an array with id, date and it should display the event in a timeline manner but in a table manner also since each event must be placed inside the month, with different spacing based on the date. On top of that there should be a radio button under the table align to its event (onClick the event should make the radio button active).
So far I succeeded in doing the timeline and the event but with equal and not in a table.
This is what it looks like:
And this is what the code looks like (using MUI and Minimal template):
import { useState } from 'react';
// mui
import { Box, Stack, Radio, FormControlLabel, FormControl, RadioGroup, Grid, Fab, Tooltip, Divider } from "@mui/material";
// components
import ScanCarousel from "./scan-carousel";
// ----------------------------------------------------------------------
const myObject = [
{
id: 1,
date: "10/10/2021",
label: "normal",
scan: [
'/assets/images/mock/front1.png',
'/assets/images/mock/back1.png',
'/assets/images/mock/lside1.png',
'/assets/images/mock/rside1.png',
],
},
{
id: 2,
date: "11/10/2021",
label: "critical",
scan: [
'/assets/images/mock/front2.png',
'/assets/images/mock/back2.png',
'/assets/images/mock/lside2.png',
'/assets/images/mock/rside2.png',
],
},
{
id: 3,
label: "normal",
date: "12/10/2021",
scan: [
'/assets/images/mock/front3.png',
'/assets/images/mock/back3.png',
'/assets/images/mock/lside3.png',
'/assets/images/mock/rside3.png',
],
},
];
// ----------------------------------------------------------------------
const ScanTimeline = () => {
const [images, setImages] = useState(myObject[0].scan);
const [value, setValue] = useState(myObject[2].date);
const [openTooltips, setOpenTooltips] = useState({});
const handleChange = (event) => {
setValue(event.target.value);
};
const handleClick = (item) => {
setOpenTooltips(prev => ({
...Object.keys(prev).reduce((acc, key) => {
acc[key] = false;
return acc;
}, {}),
[item.id]: !prev[item.id]
})); setImages(item.scan);
setValue(item.date);
};
return (
<>
<Stack direction='row'>
<Box>
<FormControl>
<RadioGroup
row
value={value}
onChange={handleChange}
>
{myObject.map((item) => (
<Stack direction='column' key={item.id} alignItems='flex-start'>
<Stack direction='row' alignItems='center'>
<Fab
onClick={() => handleClick(item)}
aria-label="add"
size="small"
sx={{
color: 'grey',
backgroundColor: 'transparent',
border: `2px solid ${item.label === 'normal' ? '#0BE2CF' : "pink"}`,
boxShadow: 'none',
"&:hover": {
backgroundColor: "transparent"
}
}}>
{item.id}
</Fab>
<Divider sx={{ width: "40px", borderBottomWidth: 2 }} />
</Stack>
<FormControlLabel
labelPlacement="top"
value={item.date}
onClick={() => setImages(item.scan)}
sx={{ mr: 0, ml: "2px" }}
control={
<Tooltip
open={openTooltips[item.id] || false}
onOpen={() => setOpenTooltips(prev => ({ ...prev, [item.id]: true }))}
onClose={() => setOpenTooltips(prev => ({ ...prev, [item.id]: false }))}
title={item.date}
>
<Radio
sx={{
color: item.label === 'normal' ? '#0BE2CF' : "pink",
'&.Mui-checked': {
color: item.label === 'normal' ? '#0BE2CF ' : "pink",
},
}}
/>
</Tooltip>}
/>
</Stack>
))
}
</RadioGroup>
</FormControl>
</Box>
</Stack>
<Grid container>
<ScanCarousel previousScan={images} currentScan={myObject[2].scan} />
</Grid>
</>
);
};
export default ScanTimeline;
The extent of it is that on clicking on and event you also change the content of the carousel/slider under the timeline.
I'm not looking for someone to code the entire thing but more for an idea of how to achieve this tricky component, some directions because so far after long reflexion I don't really know where to start.
Thank you.


Ok so in the end the way to create this was to play with the positioning, here is how I did it based on my own code:
I only need to figure out a algo to determine the exact position of each boutons on the timeline and find a way to make to overflow working (since so far it make the month text disappear..)
And here is the result: