stack qtion
stack qtion

Reputation: 201

show percentage number in reactjs material ui progress bar

I use Linear Determinate and i want to display how much progress is completed in number. like below image.

enter image description here

Upvotes: 9

Views: 13854

Answers (5)

Audrey JW
Audrey JW

Reputation: 41

I hope you have found your answer but if that helps anyone with the same issue, I managed to achieve this by using React.createPortal. ;)

Here are the steps to implement this:

  • Add a ref to your progress bar (the ref can't be used with useRef if you want your label to be initialized on mount, instead create an element local state (useState<HtmlElement | undefined>())
  • Add this to your progress bar component:
ref={(el: HTMLElement) => setElement(el)}
  • Create a component which will have your label, in it make sure to pass down the element from your local state (IMPORTANT pass the child element from your node, not the parent -> el={element.firstElementChild}).
  • Do a createPortal to "move" this component as a child of element.firstElementChild, aka: the progress bar. Here is my code for that:
// in my case I made sure my HTML code for my label has an position absolute so I can move it to the far right of my progress bar.
const MyLabel: FC<{ el: Element; extraLabel: string }> = ({ el, extraLabel }) => {
  return (
    <>
      {createPortal(
        <>..your HTML code for your label..</>, 
        el,
      )}
    </>
  );
};

Here is my final output:

enter image description here

Hope it helps <3

For more information on how to use React.createPortal and understand its magic, here is the documentation : https://reactjs.org/docs/portals.html

From a senior FullStack dev, Audrey.

Upvotes: 1

Harley Lang
Harley Lang

Reputation: 2333

Here are a few different material-ui custom styles mixed together to create the desired component:

import React from "react";

import { withStyles } from "@material-ui/styles";
import { lighten, Box, LinearProgress, Typography } from "@material-ui/core";

interface Props {
  color?: "primary" | "secondary";
  hex?: string;
  value?: number;
}

/**
 * ProgressBar -- atom
 * A material-ui progress bar.
 * @param {'primary' | 'secondary'} color Choose to render the primary or secondary colors.
 * @param {string} hex Override the selected color with a hex value.
 * @param {number} value The value for the progress bar, between 0-100.
 * @return {JSX} React component
 */
const ProgressBar = ({ color, hex, value }: Props) => {
  let internalColor: string;

  if (typeof hex === "undefined") {
    internalColor = "#3f51b5";
  } else if (typeof hex !== "undefined" && /^#[0-9A-F]{6}$/i.test(hex)) {
    internalColor = hex;
  } else {
    throw new Error("Invalid hex prop -- please use a hex string.");
  }

  if (typeof value === "undefined") {
    value = 0;
  } else if (typeof value === "number" && value < 0) {
    throw new Error(
      "Invalid value prop -- please use a number more than or equal to 0."
    );
  } else if (typeof value === "number" && value > 100) {
    throw new Error(
      "Invalid value prop -- please use a number less than or equal to 100."
    );
  }

  // from: https://bit.dev/mui-org/material-ui/linear-progress
  const BorderLinearProgress = withStyles({
    root: {
      height: 20,
      width: "100%",
      backgroundColor: hex ? lighten(internalColor, 0.5) : undefined,
      borderRadius: "10px"
    },
    bar: {
      borderRadius: 20,
      backgroundColor: hex ? internalColor : undefined
    }
  })(LinearProgress);

  // from: https://stackoverflow.com/a/60609045/14198287
  const WhiteTextTypography = withStyles({
    root: {
      color: "#FFFFFF"
    }
  })(Typography);

  return (
    <Box position="relative" display="inline-flex" style={{ width: "100%" }}>
      <BorderLinearProgress
        color={hex ? undefined : color}
        variant="determinate"
        value={value}
      />
      <Box
        top={0}
        left={0}
        bottom={0}
        right={0}
        position="absolute"
        display="flex"
        alignItems="center"
        justifyContent="center"
      >
        <WhiteTextTypography variant="body2">{`${value}%`}</WhiteTextTypography>
      </Box>
    </Box>
  );
};

export default ProgressBar;

For a working example, see: https://codesandbox.io/s/stack-51254333-progressbar-x7j5m?file=/src/App.tsx:0-2390

Upvotes: 0

erhanasikoglu
erhanasikoglu

Reputation: 1735

Materiaui supports progressbar implementation please have a look at sample in codesandbox

Upvotes: 3

enbermudas
enbermudas

Reputation: 1615

You could display this.state.completed which shows the percentage value of the progress and the just add some style to it. Of course, you'll have to concatenate a % at the end if you want to be more explicit because it is nothing but a number.

Upvotes: 0

Harsh Makadia
Harsh Makadia

Reputation: 3443

I don't think Material UI provides progress bar as shown in your image above.

However, you can make use of React Bootstrap package and get things done.

Here is the link - https://react-bootstrap.github.io/components/progress/

Upvotes: 2

Related Questions