四种不同颜色chips/tags,自定义颜色

Four different colour chips/tags, customizing their colour

现在我的自动完成菜单中包含两个数组,它们 chip/tag 的颜色是主要颜色还是次要颜色,具体取决于所选组件是哪个数组的元素。

我想在菜单中包含所有四个数组(top10Songs、top10Artists、top10Films、top10Shows)。

我的问题是:

  1. 我怎样才能拥有四种独特的颜色而不是两种(主要和次要)
  2. 我如何自定义这些颜色

我是 material UI 的新手,非常感谢您的帮助!

import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import { makeStyles } from "@material-ui/core/styles";
import { Chip } from "@material-ui/core";

const useStyles = makeStyles({
  textField: {
    "& input::placeholder": {
      color: "#a2a1a1",
      fontStyle: "italic",
    },
  },
});

export default function Tags() {
  const [selectedOptions, setSelectedOptions] = React.useState([]);

  const classes = useStyles();

  return (
    <div style={{ width: 500 }}>
      <Autocomplete
        disableClearable="true"
        filterSelectedOptions="true"
        multiple
        id="tags-standard"
        options={final}
        value={selectedOptions}
        onChange={(event, newValue) => {
          setSelectedOptions(newValue);
        }}
        getOptionSelected={(o, v) => o.title === v.title && o.year === v.year}
        getOptionLabel={(o) => o.title + " " + o.year}
        renderTags={(value, getTagProps) => []}
        renderInput={(params) => (
          <TextField
            {...params}
            className={classes.textField}
            variant="standard"
            placeholder="Favorites"
            margin="normal"
            //color="blue"
            fullWidth
          />
        )}
      />

      <div>
        {selectedOptions.map((option, index) => (
          <Chip
            key={index}
            color={option.type === "film" ? "primary" : "secondary"}
            label={`${option.title} ${option.year}`}
            onDelete={() =>
              setSelectedOptions([
                ...selectedOptions.slice(0, index),
                ...selectedOptions.slice(index + 1),
              ])
            }
          />
        ))}
      </div>
    </div>
  );
}

const top10Songs = [
  { title: "A", year: 1 },
  { title: "B", year: 2 },
  { title: "C", year: 3 },
  { title: "D", year: 4 },
  { title: "E", year: 5 },
  { title: "F", year: 6 },
  { title: "G", year: 7 },
  { title: "H", year: 8 },
  { title: "I", year: 9 },
  { title: "J", year: 10 },
  { title: "K", year: 11 },
  { title: "L", year: 12 },
  { title: "M", year: 13 },
  { title: "N", year: 14 },
  { title: "O", year: 15 },
  { title: "P", year: 16 },
];

const top10Artists = [
  { title: "Aa", year: 1 },
  { title: "Bb", year: 2 },
  { title: "Cc", year: 3 },
  { title: "Dd", year: 4 },
  { title: "Ee", year: 5 },
  { title: "Ff", year: 6 },
  { title: "Gg", year: 7 },
  { title: "Hh", year: 8 },
  { title: "Ii", year: 9 },
  { title: "Jj", year: 10 },
  { title: "Kk", year: 11 },
  { title: "Ll", year: 12 },
  { title: "Mm", year: 13 },
  { title: "Nn", year: 14 },
  { title: "Oo", year: 15 },
  { title: "Pp", year: 16 },
];

// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top10Shows = [
  { title: "Once Upon a Time in the West", year: 1968 },
  { title: "American History X", year: 1998 },
  { title: "Interstellar", year: 2014 },
  { title: "Casablanca", year: 1942 },
  { title: "City Lights", year: 1931 },
  { title: "Psycho", year: 1960 },
  { title: "The Green Mile", year: 1999 },
  { title: "The Intouchables", year: 2011 },
  { title: "Modern Times", year: 1936 },
  { title: "Raiders of the Lost Ark", year: 1981 },
];

const top10Films = [
  { title: "Once Upon a Time in the West", year: 1968 },
  { title: "American History X", year: 1998 },
  { title: "Interstellar", year: 2014 },
  { title: "Casablanca", year: 1942 },
  { title: "City Lights", year: 1931 },
  { title: "Psycho", year: 1960 },
  { title: "The Green Mile", year: 1999 },
  { title: "The Intouchables", year: 2011 },
  { title: "Modern Times", year: 1936 },
  { title: "Raiders of the Lost Ark", year: 1981 },
];

const final = [
  ...top10Films.map((f) => Object.assign({}, f, { type: "film" })),
  ...top10Shows.map((s) => Object.assign({}, s, { type: "show" })),
];

下面是一种方法。

首先将另外两种颜色添加到您的主题中:

const theme = createMuiTheme({
  palette: {
    tertiary: lime,
    quaternary: orange
  }
});
// This is a step that Material-UI automatically does for the standard palette colors.
theme.palette.tertiary = theme.palette.augmentColor(theme.palette.tertiary);
theme.palette.quaternary = theme.palette.augmentColor(theme.palette.quaternary);

以下 getCustomChip 函数 returns 自定义 Chip,它会覆盖当 color prop 等于“primary”时使用的颜色。可以找到被覆盖的默认样式 here and here.

const getCustomChip = color =>
  withStyles(theme => ({
    colorPrimary: {
      backgroundColor: theme.palette[color].main,
      color: theme.palette[color].contrastText
    },
    deletableColorPrimary: {
      "&:focus": {
        backgroundColor: emphasize(theme.palette[color].main, 0.2)
      }
    }
  }))(Chip);

然后设置选项类型到 Chip 自定义的映射:

const typeToChip = {
  song: Chip,
  artist: getCustomChip("secondary"),
  film: getCustomChip("tertiary"),
  show: getCustomChip("quaternary")
};

然后使用那个映射:

         {selectedOptions.map((option, index) => {
            const ChipForType = typeToChip[option.type];
            return (
              <ChipForType
                key={index}
                color="primary"
                label={`${option.title} ${option.year}`}
                onDelete={() =>
                  setSelectedOptions([
                    ...selectedOptions.slice(0, index),
                    ...selectedOptions.slice(index + 1)
                  ])
                }
              />
            );
          })}

完整代码如下:

import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import {
  makeStyles,
  withStyles,
  ThemeProvider,
  createMuiTheme
} from "@material-ui/core/styles";
import { Chip } from "@material-ui/core";
import { emphasize } from "@material-ui/core/styles/colorManipulator";
import lime from "@material-ui/core/colors/lime";
import orange from "@material-ui/core/colors/orange";

const useStyles = makeStyles({
  textField: {
    "& input::placeholder": {
      color: "#a2a1a1",
      fontStyle: "italic"
    }
  }
});

const theme = createMuiTheme({
  palette: {
    tertiary: lime,
    quaternary: orange
  }
});
// This is a step that Material-UI automatically does for the standard palette colors.
theme.palette.tertiary = theme.palette.augmentColor(theme.palette.tertiary);
theme.palette.quaternary = theme.palette.augmentColor(theme.palette.quaternary);

const getCustomChip = color =>
  withStyles(theme => ({
    colorPrimary: {
      backgroundColor: theme.palette[color].main,
      color: theme.palette[color].contrastText
    },
    deletableColorPrimary: {
      "&:focus": {
        backgroundColor: emphasize(theme.palette[color].main, 0.2)
      }
    }
  }))(Chip);

const typeToChip = {
  song: Chip,
  artist: getCustomChip("secondary"),
  film: getCustomChip("tertiary"),
  show: getCustomChip("quaternary")
};

export default function Tags() {
  const [selectedOptions, setSelectedOptions] = React.useState([]);

  const classes = useStyles();

  return (
    <ThemeProvider theme={theme}>
      <div style={{ width: 500 }}>
        <Autocomplete
          disableClearable="true"
          filterSelectedOptions="true"
          multiple
          id="tags-standard"
          options={final}
          value={selectedOptions}
          onChange={(event, newValue) => {
            setSelectedOptions(newValue);
          }}
          getOptionSelected={(o, v) => o.title === v.title && o.year === v.year}
          getOptionLabel={o => o.title + " " + o.year}
          renderTags={(value, getTagProps) => []}
          renderInput={params => (
            <TextField
              {...params}
              className={classes.textField}
              variant="standard"
              placeholder="Favorites"
              margin="normal"
              //color="blue"
              fullWidth
            />
          )}
        />

        <div>
          {selectedOptions.map((option, index) => {
            const ChipForType = typeToChip[option.type];
            return (
              <ChipForType
                key={index}
                color="primary"
                label={`${option.title} ${option.year}`}
                onDelete={() =>
                  setSelectedOptions([
                    ...selectedOptions.slice(0, index),
                    ...selectedOptions.slice(index + 1)
                  ])
                }
              />
            );
          })}
        </div>
      </div>
    </ThemeProvider>
  );
}

const top10Songs = [
  { title: "A", year: 1 },
  { title: "B", year: 2 },
  { title: "C", year: 3 },
  { title: "D", year: 4 },
  { title: "E", year: 5 },
  { title: "F", year: 6 },
  { title: "G", year: 7 },
  { title: "H", year: 8 },
  { title: "I", year: 9 },
  { title: "J", year: 10 },
  { title: "K", year: 11 },
  { title: "L", year: 12 },
  { title: "M", year: 13 },
  { title: "N", year: 14 },
  { title: "O", year: 15 },
  { title: "P", year: 16 }
];

const top10Artists = [
  { title: "Aa", year: 1 },
  { title: "Bb", year: 2 },
  { title: "Cc", year: 3 },
  { title: "Dd", year: 4 },
  { title: "Ee", year: 5 },
  { title: "Ff", year: 6 },
  { title: "Gg", year: 7 },
  { title: "Hh", year: 8 },
  { title: "Ii", year: 9 },
  { title: "Jj", year: 10 },
  { title: "Kk", year: 11 },
  { title: "Ll", year: 12 },
  { title: "Mm", year: 13 },
  { title: "Nn", year: 14 },
  { title: "Oo", year: 15 },
  { title: "Pp", year: 16 }
];

// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top10Shows = [
  { title: "Psycho", year: 1960 },
  { title: "The Green Mile", year: 1999 },
  { title: "The Intouchables", year: 2011 },
  { title: "Modern Times", year: 1936 },
  { title: "Raiders of the Lost Ark", year: 1981 }
];

const top10Films = [
  { title: "Once Upon a Time in the West", year: 1968 },
  { title: "American History X", year: 1998 },
  { title: "Interstellar", year: 2014 },
  { title: "Casablanca", year: 1942 },
  { title: "City Lights", year: 1931 }
];

const final = [
  ...top10Songs.map(entry => ({ ...entry, type: "song" })),
  ...top10Artists.map(entry => ({ ...entry, type: "artist" })),
  ...top10Films.map(entry => ({ ...entry, type: "film" })),
  ...top10Shows.map(entry => ({ ...entry, type: "show" }))
];

相关回答: