css - Material-ui makeStyles 默认覆盖

标签 css reactjs material-ui

我正在尝试使用 覆盖 Stepper 组件中的伪类makeStyles :

const useStyles = makeStyles((theme) => ({
  active: {
    color: theme.palette.primary.main,
  },
  completed: {
    color: theme.palette.goodyear.status.positive,
  },
  root: {
    color: theme.palette.goodyear.grey.medium,
    fontWeight: 500,
  },
  text: {
    color: theme.palette.text.titles,
  },
  iconContainer: {
    transform: 'scale(1.667)',
  },
  label: {
    fontSize: '1.2rem',
    fontWeight: 500,
  },
}));

const StepLabel = (props) => {
  const classes = useStyles();

  return (
    <MaterialStepLabel
      classes={{
        iconContainer: classes.iconContainer,
        label: classes.label,
      }}
      StepIconProps={{
        classes: {
          active: classes.active,
          completed: classes.completed,
          root: classes.root,
          text: classes.text,
        },
      }}
      {...props}
    />
  );
};
不幸的是,在浏览器中,结果如下所示:
screenshot of app
由 makeStyles 创建的类在那里,但默认情况下会被覆盖,因为它更具体?您还可以看到完成的类也在根类之下,这会很奇怪,因为根是处于一般状态的元素,并且完成的伪应该覆盖该样式。
这里可能有什么问题,我应该如何正确使用这些类?

最佳答案

以下是the default styles for StepIcon的定义:

export const styles = (theme) => ({
  /* Styles applied to the root element. */
  root: {
    display: 'block',
    color: theme.palette.text.disabled,
    '&$completed': {
      color: theme.palette.primary.main,
    },
    '&$active': {
      color: theme.palette.primary.main,
    },
    '&$error': {
      color: theme.palette.error.main,
    },
  },
  /* Styles applied to the SVG text element. */
  text: {
    fill: theme.palette.primary.contrastText,
    fontSize: theme.typography.caption.fontSize,
    fontFamily: theme.typography.fontFamily,
  },
  /* Pseudo-class applied to the root element if `active={true}`. */
  active: {},
  /* Pseudo-class applied to the root element if `completed={true}`. */
  completed: {},
  /* Pseudo-class applied to the root element if `error={true}`. */
  error: {},
});
了解您遇到的问题的关键是更好地了解如何CSS specificity作品。
在上面的样式中,您可以看到除默认之外的所有状态都是通过具有两个 CSS 类名的声明来应用的。 &指回 root然后 $completed$active引用通过completed: {}定义的相应规则和 active: {} .正如您在检查样式时看到的那样,&$completed最终解析为 .MuiStepIcon-root.MuiStepIcon-completed .
带有两个类选择器的 CSS 声明中的样式(例如 .MuiStepIcon-root.MuiStepIcon-completed )将始终胜过带有单个类选择器的 CSS 声明中的样式(就像您的所有样式一样)。当特异性相同时,例如与您的 makeStyles-root-xmakeStyles-completed-x ,那么最后宣布的人将获胜。您声明了您的 root课后你 completed类(并且此相对顺序会传递到为您的 <head> 调用生成的 makeStyles 中的样式表),因此您的 root类(class)获胜。
为了让您的样式覆盖起作用,您应该使用与 Material-UI 中默认样式中使用的相同的特性。我建议定义您的 rootcompleted样式如下:
const useStyles = makeStyles((theme) => ({
  root: {
    color: theme.palette.goodyear.grey.medium,
    fontWeight: 500,
    "&.MuiStepIcon-completed": {
      color: theme.palette.goodyear.status.positive,
    },
  },
}));
使用这种方法,您无需为 completed 指定任何内容。内classes Prop -- 只是 root .
以下是基于 demos 之一的完整工作示例(stepIconRoot 类是最相关的部分):
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Stepper from "@material-ui/core/Stepper";
import Step from "@material-ui/core/Step";
import StepLabel from "@material-ui/core/StepLabel";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";

const useStyles = makeStyles((theme) => ({
  root: {
    width: "100%"
  },
  button: {
    marginRight: theme.spacing(1)
  },
  instructions: {
    marginTop: theme.spacing(1),
    marginBottom: theme.spacing(1)
  },
  stepIconRoot: {
    color: "orange",
    "&.MuiStepIcon-active": {
      color: "purple"
    },
    "&.MuiStepIcon-completed": {
      color: "green"
    }
  }
}));

function getSteps() {
  return ["Select campaign settings", "Create an ad group", "Create an ad"];
}

function getStepContent(step) {
  switch (step) {
    case 0:
      return "Select campaign settings...";
    case 1:
      return "What is an ad group anyways?";
    case 2:
      return "This is the bit I really care about!";
    default:
      return "Unknown step";
  }
}

export default function HorizontalLinearStepper() {
  const classes = useStyles();
  const [activeStep, setActiveStep] = React.useState(0);
  const [skipped, setSkipped] = React.useState(new Set());
  const steps = getSteps();

  const isStepOptional = (step) => {
    return step === 1;
  };

  const isStepSkipped = (step) => {
    return skipped.has(step);
  };

  const handleNext = () => {
    let newSkipped = skipped;
    if (isStepSkipped(activeStep)) {
      newSkipped = new Set(newSkipped.values());
      newSkipped.delete(activeStep);
    }

    setActiveStep((prevActiveStep) => prevActiveStep + 1);
    setSkipped(newSkipped);
  };

  const handleBack = () => {
    setActiveStep((prevActiveStep) => prevActiveStep - 1);
  };

  const handleSkip = () => {
    if (!isStepOptional(activeStep)) {
      // You probably want to guard against something like this,
      // it should never occur unless someone's actively trying to break something.
      throw new Error("You can't skip a step that isn't optional.");
    }

    setActiveStep((prevActiveStep) => prevActiveStep + 1);
    setSkipped((prevSkipped) => {
      const newSkipped = new Set(prevSkipped.values());
      newSkipped.add(activeStep);
      return newSkipped;
    });
  };

  const handleReset = () => {
    setActiveStep(0);
  };

  return (
    <div className={classes.root}>
      <Stepper activeStep={activeStep}>
        {steps.map((label, index) => {
          const stepProps = {};
          const labelProps = {
            StepIconProps: { classes: { root: classes.stepIconRoot } }
          };
          if (isStepOptional(index)) {
            labelProps.optional = (
              <Typography variant="caption">Optional</Typography>
            );
          }
          if (isStepSkipped(index)) {
            stepProps.completed = false;
          }
          return (
            <Step key={label} {...stepProps}>
              <StepLabel {...labelProps}>{label}</StepLabel>
            </Step>
          );
        })}
      </Stepper>
      <div>
        {activeStep === steps.length ? (
          <div>
            <Typography className={classes.instructions}>
              All steps completed - you&apos;re finished
            </Typography>
            <Button onClick={handleReset} className={classes.button}>
              Reset
            </Button>
          </div>
        ) : (
          <div>
            <Typography className={classes.instructions}>
              {getStepContent(activeStep)}
            </Typography>
            <div>
              <Button
                disabled={activeStep === 0}
                onClick={handleBack}
                className={classes.button}
              >
                Back
              </Button>
              {isStepOptional(activeStep) && (
                <Button
                  variant="contained"
                  color="primary"
                  onClick={handleSkip}
                  className={classes.button}
                >
                  Skip
                </Button>
              )}

              <Button
                variant="contained"
                color="primary"
                onClick={handleNext}
                className={classes.button}
              >
                {activeStep === steps.length - 1 ? "Finish" : "Next"}
              </Button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
Edit StepIcon overrides

关于css - Material-ui makeStyles 默认覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64283026/

相关文章:

html - 强制内部 td 的行为不像 tr

css - select2 css 加载时间太长

jquery - Iscroll5 不会水平滚动,宽度(每张幻灯片)100% 也分配给类(多用途)

javascript - 使用 React 显示图像

javascript - 如何为每个组件实例的元素分配唯一 ID

reactjs - 从 materialui 组件中删除/覆盖默认样式

javascript - 在羽光形态内标记?

javascript - 样式化的组件输入失去对变化的关注

javascript - React 应用程序 - 在 Material UI Table 中加载选定的数组而不进行渲染检查

css - 如何更改事件导航选项卡的背景颜色?