layoutmaterial-uilabelstepper

Material UI - Stepper top and bottom labels with line


I try to make a stepper with Material UI (V5). Here is my code:

import * as React from 'react';
import Box from '@mui/material/Box';
import Stepper from '@mui/material/Stepper';
import Step from '@mui/material/Step';
import Typography from '@mui/material/Typography';
import StepLabel from '@mui/material/StepLabel';

const steps = [
  'Step 1 - Top',
  'Step 2 - Top',
  'Ste^3 - Top',
];

export default function HorizontalLabelPositionBelowStepper() {
  return (
    <Box sx={{ width: '100%' }}>
      <Stepper activeStep={1} alternativeLabel
      >
        {steps.map((label) => (
          <Step key={label}>
            <Typography>Top text</Typography>
            <StepLabel>{label}</StepLabel>
          </Step>
        ))}
      </Stepper>
    </Box>
  );
}

That gives this result:

enter image description here

How to properly position the line and the 'top text' labels?

What about aligning the icons with the line such as: image with icon and line aligned

Do I need to create a separated Grid or Box before the Stepper to create the top labels? Thank you.

thank you for your suggestions.

Marc


Solution

  • Bellow I have the code you need including two solutions.

    Solution 1 is faster and it will work better when the label-text of the steps have similar width between them. If not you have to specify the .MuiStepConnector-root left and right properties for each child if you want to have a better looking result.

    Solution 2 includes a little more code and but will work no matter the width of each label-text. As it used a background color make sure to change it to match your background.

    Here is the codesandbox to play with it and see both working solutions. Please make sure to comment or uncomment the code depending the solution you want to try.

    Code:

    import * as React from "react";
    import Box from "@mui/material/Box";
    import Stepper from "@mui/material/Stepper";
    import Step from "@mui/material/Step";
    import StepLabel from "@mui/material/StepLabel";
    import { Typography } from "@mui/material";
    
    const steps = ["Step 1 - Top", "Step 2 - Top", "Ste^3 - Top"];
    
    // Solution 1
    const StepperSx = {
      "& .MuiStepConnector-root": {
        left: "calc(-50% + 40px)",
        right: "calc(50% + 40px)"
      },
      "& .MuiStepConnector-line": {
        marginTop: "22px"
      }
    };
    
    // Solution 2
    // const StepperSx2 = {
    //   textAlign: "center",
    //   "& .MuiStepConnector-root": {
    //     zIndex: "1",
    //     position: "relative"
    //   }
    // };
    
    // Solution 2
    // const TypographySx = {
    //   zIndex: "2",
    //   background: "#FFF",
    //   display: "inline",
    //   position: "relative",
    //   padding: "0 15px"
    // };
    
    export default function HorizontalLabelPositionBelowStepper() {
      return (
        <Box sx={{ width: "100%" }}>
          <Stepper
            activeStep={1}
            alternativeLabel
            sx={StepperSx} // For solution 1
            // sx={StepperSx2} // For solution 2
          >
            {steps.map((label) => (
              <Step key={label}>
                <Typography
                  align="center"
                  // sx={TypographySx} // For solution 2
                >
                  Top text
                </Typography>
                <StepLabel>{label}</StepLabel>
              </Step>
            ))}
          </Stepper>
        </Box>
      );
    }