Search code examples
reactjsmaterial-uitimeline

Is there a way to implement horizontal timeline using Material UI in React?


I'm trying to implement a horizontal timeline using Material UI in React. In their documentation I could find only vertical timeline demos and I couldn't find any prop that can directly change the alignment. Is there a way to solve this?

I would want to implement something like the below image, but horizontal.

enter image description here


Solution

  • You can override the timeline styles and do something like this:

    const useStyles = makeStyles({
      timeline: {
        transform: "rotate(90deg)"
      },
      timelineContentContainer: {
        textAlign: "left"
      },
      timelineContent: {
        display: "inline-block",
        transform: "rotate(-90deg)",
        textAlign: "center",
        minWidth: 50
      },
      timelineIcon: {
        transform: "rotate(-90deg)"
      }
    });
    
    function App() {
      const classes = useStyles();
    
      return (
        <Timeline className={classes.timeline} align="alternate">
          <TimelineItem>
            <TimelineSeparator>
              <CheckCircleOutlineIcon
                color="primary"
                className={classes.timelineIcon}
              />
              <TimelineConnector />
            </TimelineSeparator>
            <TimelineContent className={classes.timelineContentContainer}>
              <Paper className={classes.timelineContent}>
                <Typography>Eat</Typography>
              </Paper>
            </TimelineContent>
          </TimelineItem>
          <TimelineItem>
            <TimelineSeparator>
              <PauseCircleFilledIcon
                color="primary"
                className={classes.timelineIcon}
              />
              <TimelineConnector />
            </TimelineSeparator>
            <TimelineContent className={classes.timelineContentContainer}>
              <Paper className={classes.timelineContent}>
                <Typography>Code</Typography>
              </Paper>
            </TimelineContent>
          </TimelineItem>
          <TimelineItem>
            <TimelineSeparator>
              <CachedIcon color="primary" className={classes.timelineIcon} />
              <TimelineConnector />
            </TimelineSeparator>
            <TimelineContent className={classes.timelineContentContainer}>
              <Paper className={classes.timelineContent}>
                <Typography>Sleep</Typography>
              </Paper>
            </TimelineContent>
          </TimelineItem>
          <TimelineItem>
            <TimelineSeparator>
              <CachedIcon color="primary" className={classes.timelineIcon} />
              <TimelineConnector />
            </TimelineSeparator>
            <TimelineContent className={classes.timelineContentContainer}>
              <Paper className={classes.timelineContent}>
                <Typography>Repeat</Typography>
              </Paper>
            </TimelineContent>
          </TimelineItem>
          <TimelineItem>
            <TimelineSeparator>
              <ErrorIcon color="primary" className={classes.timelineIcon} />
            </TimelineSeparator>
            <TimelineContent className={classes.timelineContentContainer}>
              <Paper className={classes.timelineContent}>
                <Typography>Sleep</Typography>
              </Paper>
            </TimelineContent>
          </TimelineItem>
        </Timeline>
      );
    }
    

    If the labels aren't on the same elevation, adjust minWidth.


    The result looks like this:

    timeline

    One thing that will feel weird using this approach is that the visually left most element is the last element in the timeline, because of the rotation.