DragoJokera
DragoJokera

Reputation: 1035

Change color of active button among multiple buttons in React using material ui

I am trying to change the color only of a button, which is clicked. And by default the first button to be active. The problem that I have is that in Material UI when I use Button there is a span so I cannot use e.target.name ... because there is no name in the span. This span is created when I type some text between the button tags => Some title. As well I intend to have some other actions when the button is clicked, except that it should change its color to show, which one is active. If there is some way around I will appreciate it. Down below is some code, that I tried, but I do not know what to do in clickedButtonHandler and if it's possible to pass any argument on it when the button is clicked... for example the name.

import React, { useState } from "react";
import { Container, Box, Button } from "@material-ui/core";
import { makeStyles, withStyles } from "@material-ui/styles";

const StyledButton = withStyles(() => ({
  root: {
    marginRight: "1rem",
    width: "25%",
    padding: "1rem",
    fontSize: "1.2rem",
    borderRadius: "1rem",
    color: "#000",
    fontWeight: "400",
    textTransform: "capitalize"
  }
}))(Button);

const useStyles = makeStyles(() => ({
  buttonContainerWrapper: {
    display: "flex",
    justifyContent: "center"
  },
  buttonContainer: {
    backgroundColor: "#ccc",
    border: "1px solid #000",
    padding: "1rem",
    display: "flex",
    justifyContent: "space-between"
  },
  lastButtonFilter: {
    marginRight: "0rem"
  },
  activeButton: {
    background: "#fc7303",
    color: "#fff"
  }
}));

export default function Filter() {
  const classes = useStyles();
  const [activeButton, setActiveButton] = useState({
    first: true,
    second: false,
    third: false,
    fourth: false
  });

  const clickedButtonHandler = (e) => {
    console.log(e.target);
    const { name } = e.target;
    setActiveButton(name);
    console.log(activeButton);
  };

  return (
    <Container className={classes.buttonContainerWrapper}>
      <Box className={classes.buttonContainer}>
        <StyledButton
          name="button-one"
          className={activeButton?.first ? `${classes.activeButton}` : ""}
          onClick={clickedButtonHandler}
        >
          Button One
        </StyledButton>
        <StyledButton
          name="button-two"
          className={
            activeButton?.second ? `${classes.activeButton}` : ""
          }
          onClick={clickedButtonHandler}
        >
          Button Two
        </StyledButton>
        <StyledButton
          name="button-three"
          className={activeButton?.third ? `${classes.activeButton}` : ""}
          onClick={clickedButtonHandler}
        >
          Button Three
        </StyledButton>
        <StyledButton
          name="button-four"
          className={
            activeButton?.fourth ? `${classes.activeButton}` : ""
          }
          onClick={clickedButtonHandler}
        >
          Button Four
        </StyledButton>
      </Box>
    </Container>
  );
}

here is the link to codepan: https://codesandbox.io/s/awesome-sinoussi-u3o3s

Upvotes: 0

Views: 5187

Answers (2)

Duderino9000
Duderino9000

Reputation: 2597

It looks like you can also loop through an array for the buttons

export default function Filter() {
  const classes = useStyles();
  const [activeButton, setActiveButton] = useState("button-one");

  const clickedButtonHandler = (name) => {
    setActiveButton(name);
  };


  const buttons = ["button-one", "button-two", "button-three", "button-four"];

  return (
    <Container className={classes.buttonContainerWrapper}>
      <Box className={classes.buttonContainer}>
        {buttons.map((name) => (
          <StyledButton
            name={name}
            className={activeButton === name ? `${classes.activeButton}` : ""}
            onClick={() => clickedButtonHandler(name)}
          >
            {name}
          </StyledButton>
        ))}
      </Box>
    </Container>
  );
}

Upvotes: 2

Rajiv
Rajiv

Reputation: 3772

for targetting the root element use the ButtonBase component.
And also to keep track of active buttons in useState, spread the old state first and then update the new value of the new variable (might differ in different use case or requirement). I've updated that issue.


export default function Filter() {
  const classes = useStyles();
  const [activeButton, setActiveButton] = useState('first');

  const clickedButtonHandler = (e) => {
    console.log(e.target);
    const { name } = e.target;
    setActiveButton(name);
    console.log(activeButton);
  };

  return (
    <Container className={classes.buttonContainerWrapper}>
      <Box className={classes.buttonContainer}>
        <StyledButton
          name="first"
          className={activeButton === "first" ? `${classes.activeButton}` : ""}
          onClick={clickedButtonHandler}
        >
          Button One
        </StyledButton>
        <StyledButton
          name="second"
          className={activeButton === "second" ? `${classes.activeButton}` : ""}
          onClick={clickedButtonHandler}
        >
          Button Two
        </StyledButton>
        <StyledButton
          name="third"
          className={activeButton === "third" ? `${classes.activeButton}` : ""}
          onClick={clickedButtonHandler}
        >
          Button Three
        </StyledButton>
        <StyledButton
          name="fourth"
          className={activeButton === "fourth" ? `${classes.activeButton}` : ""}
          onClick={clickedButtonHandler}
        >
          Button Four
        </StyledButton>
      </Box>
    </Container>
  );
}


Workign demo:-
Edit white-rain-ye62u

Upvotes: 1

Related Questions