Reputation: 43491
I have
import CaretDownIcon from 'src/../public/images/svg/caret-down.svg';
<Select
className={selectClassName}
data-testid={testId}
// IconComponent={<SvgIcon>{CaretDownIcon}</SvgIcon>}
// IconComponent={CaretDownIcon}
inputProps={{
name,
id: labelId,
}}
{...rest}
>
I tried both of those commented lines, but no dice. What's the right way?
Upvotes: 4
Views: 5655
Reputation: 80986
You need to create a component for your custom svg icon. Copy the path from the svg file to make a component as shown below:
function CustomSvgIcon(props) {
return (
<SvgIcon {...props}>
<path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
</SvgIcon>
);
}
then you can use that with IconComponent={CustomSvgIcon}
.
Here's a full working example:
import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import SvgIcon from "@material-ui/core/SvgIcon";
const styles = (theme) => ({
root: {
display: "flex",
flexWrap: "wrap"
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing.unit * 2
}
});
function CustomSvgIcon(props) {
return (
<SvgIcon {...props}>
<path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
</SvgIcon>
);
}
class SimpleSelect extends React.Component {
state = {
age: "",
name: "hai"
};
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const { classes } = this.props;
return (
<form className={classes.root} autoComplete="off">
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple">Age</InputLabel>
<Select
value={this.state.age}
onChange={this.handleChange}
inputProps={{
name: "age",
id: "age-simple"
}}
IconComponent={CustomSvgIcon}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</form>
);
}
}
SimpleSelect.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(SimpleSelect);
It is also possible to create a React component from an imported SVG file, but this is dependent on your build configuration. If you are using create-react-app
then this will work (see this article for details).
Below is an example using the import approach. This uses import { ReactComponent as TestSvgAsComponent } from "./test.svg";
to get a React component from the SVG file. The other step necessary is to add in the styles that would be applied by SvgIcon (classes.icon
from useIconStyles
in the example).
import React from "react";
import PropTypes from "prop-types";
import { withStyles, makeStyles } from "@material-ui/core/styles";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import { ReactComponent as TestSvgAsComponent } from "./test.svg";
import clsx from "clsx";
const styles = (theme) => ({
root: {
display: "flex",
flexWrap: "wrap"
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing.unit * 2
}
});
const useIconStyles = makeStyles({
// This is a copy of the styles from https://github.com/mui-org/material-ui/blob/v4.12.3/packages/material-ui/src/SvgIcon/SvgIcon.js#L10
icon: {
fill: "currentColor",
width: "1em",
height: "1em",
display: "inline-block",
fontSize: "1.5rem",
transition: "fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms",
flexShrink: 0,
userSelect: "none"
}
});
function CustomSvgIcon({ className, ...other }) {
const classes = useIconStyles();
return (
<TestSvgAsComponent className={clsx(classes.icon, className)} {...other} />
);
}
class SimpleSelect extends React.Component {
state = {
age: "",
name: "hai"
};
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const { classes } = this.props;
return (
<form className={classes.root} autoComplete="off">
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple">Age</InputLabel>
<Select
value={this.state.age}
onChange={this.handleChange}
inputProps={{
name: "age",
id: "age-simple"
}}
IconComponent={CustomSvgIcon}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</form>
);
}
}
SimpleSelect.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(SimpleSelect);
Related documentation:
Related answer:
Upvotes: 2