I created a reusable component that wraps the IconButton and pass as one of the props icons from react-icons.
I get the following error:
Warning: Function components cannot be given refs. Attempts to access
this ref will fail. Did you mean to use React.forwardRef()?`
Here's my component wrapper:
export function SidebarMenu({ icon, isActive, handleMenuClick, name }) {
return (
<IconButton
className={isActive ? 'active' : ''}
aria-label={name + ' menu'}
isActive={isActive}
bg="transparent"
px="0"
as={icon}
_hover={{
cursor: 'pointer',
backgroundColor: 'transparent',
}}
_active={{
backgroundColor: 'transparent',
}}
onClick={() => handleMenuClick(name)}
/>
Here's how i use the wrapper component
<SidebarMenu
icon={VscCode}
name="folders"
handleMenuClick={handleMenuClick}
isActive={menuList.folders}
/>
But if i change the content IconButton to a instead use a Icon wrapped in a Button the error disappears.
export function SidebarMenu({ icon, isActive, handleMenuClick, name }) {
return (
<Button
className={isActive ? 'active' : ''}
aria-label={name + ' menu'}
isActive={isActive}
bg="transparent"
px="0"
// as={icon}
_hover={{
cursor: 'pointer',
backgroundColor: 'transparent',
}}
_active={{
backgroundColor: 'transparent',
}}
onClick={() => handleMenuClick(name)}
>
<Icon as={icon} w={7} h={7} />
</Button>
);
}
Edit:
For anyone who may stumble on the same problem.
There are couple of things i did wrong here.
I was using as instead of icon prop in IconButton
Second, i was passing a reference instead of the component
Instead of doing <IconButton icon={<VsColorMode />} />, i was doing this <IconButton icon={VsCodeMode} />.
According to the doc, IconButton has its own prop icon, so instead of using as, in this case, use icon with Icon
function SidebarMenu({ icon }) {
return (
<IconButton
bg="transparent"
px="0"
icon={<Icon as={icon} w={7} h={7} />}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_hover={{
cursor: "pointer",
backgroundColor: "transparent"
}}
_active={{
backgroundColor: "transparent"
}}
/>
);
}
Codesandbox demo
I want to change the font size of the label in material ui badge.
I am using style={{ fontSize: "15" }} but that only affect its child, which is an icon.
Code:
<Badge badgeContent={props.cartCount} color="secondary" style={{ fontSize: "15" }}>
<ShoppingCart className={classes.mediumIcon} />
</Badge>
Ideal way would be use classes badge as mentioned in documentation
import { Badge } from "#material-ui/core";
import { makeStyles } from "#material-ui/core/styles";
import "./styles.css";
const useStyles = makeStyles((theme) => ({
badge: {
fontSize: 30
}
}));
export default function App() {
const classes = useStyles();
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Badge
badgeContent={"h"}
color="secondary"
classes={{ badge: classes.badge }}
/>
</div>
);
}
If you use mui system then this can change badge font size
<Badge
badgeContent={9}
color="error"
overlap="circular"
sx={{ "& .MuiBadge-badge": { fontSize: 9, height: 15, minWidth: 15 } }}
>
<IconButton sx={{ p: 0, color: "primary.main" }}>
<Notifications />
</IconButton>
</Badge>
You can modify the font-size as below.
create styles of different font-size in useStyles
const useStyles = makeStyles((theme) => ({
font1: {
fontSize: "1rem"
},
)}
And then assign it as below to the Badge component
<Badge
classes={{
badge: classes.font1
}}
badgeContent={99}
{...defaultProps}
/>
Sandbox
You can use the componentProps attribute as follows (this example changes the color of the text in the badge but the same principle will work for fontSize).
<Badge badgeContent={comments} componentsProps={{ root: {style: {color: 'white'}} }}>
<CommentIcon />
</Badge>
Is there a way to use the outline variant for the fab button in material ui
<Fab variant="here i see rounded || extended" color="primary" size="small" aria-label="scroll back to top">
<KeyboardArrowUp />
</Fab>
is there a way i could use the outline version and still inherit material ui ripple effect and other styles
As far as I know you cannot have outline version for that. But you can always write CSS for that. I had a simple demo for this
Edit: here are the code
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
"& > *": {
margin: theme.spacing(1)
}
},
fabStyle: {
backgroundColor: "white",
color: theme.palette.primary.light,
borderColor: theme.palette.primary.light,
"&:hover": {
backgroundColor: theme.palette.primary.light,
color: "white"
}
}
})
);
export default function FloatingActionButtons() {
const classes = useStyles();
return (
<div className={classes.root}>
<Fab color="primary" aria-label="add" className={classes.fabStyle}>
<AddIcon />
</Fab>
</div>
);
}
You should be able to inject classes into the Fab component. You can refer to this link for more information Customizing Components
<Fab
classes={{
root: classes.root, // class name, e.g. `classes-nesting-root-x`
label: classes.label, // class name, e.g. `classes-nesting-label-x`
}}
variant="here i see rounded || extended" color="primary" size="small" aria-label="scroll back to top">
<KeyboardArrowUp />
</Fab>
I have created a dropdown for the icon where when the icon is clicked, it will show the dropdown. Once we hover on Card then the three dots icon will appear. But my objective is even after showing dropdown the icon should appear. but here is my code, it is disappearing. Can anyone help me with this query?
Here is the code:
<Card>
<CardHeader
className={classes.header}
avatar={<Avatar aria-label="recipe">R</Avatar>}
action={
<div>
<IconButton
id="simple-menu"
className={classes.showIcon}
aria-label="settings"
aria-controls="simple-menu"
onClick={this.handleClick}
>
<MoreVertIcon />
</IconButton>
<Menu
style={{ marginTop: "35px" }}
id="simple-menu"
keepMounted
anchorEl={this.state.menu}
open={Boolean(this.state.menu)}
onClose={this.handleClose}
>
<MenuItem onClick={this.handleClose}>Profile</MenuItem>
<MenuItem onClick={this.handleClose}>change password</MenuItem>
<MenuItem onClick={this.handleClose}>Logout</MenuItem>
</Menu>
</div>
}
title="Shrimp and Chorizo Paella"
subheader="September 14, 2016"
/>
</Card>
Here is the sample code
Create a style className which sets the icon visibility to visible. Conditionally assign the class to the parent div only when the menu is open i.e. check for this.state.menu && classes.menu.
Style
const styles = theme => ({
header: {
background: "grey",
"&:hover": {
background: "yellow",
"& $showIcon": {
visibility: "visible"
}
}
},
showIcon: {
visibility: "hidden"
},
menu: {
"& $showIcon": {
visibility: "visible"
}
}
});
JSX
<Card>
<CardHeader
className={classes.header}
avatar={<Avatar aria-label="recipe">R</Avatar>}
action={
<div className={this.state.menu && classes.menu}>
<IconButton
id="simple-menu"
className={classes.showIcon}
aria-label="settings"
aria-controls="simple-menu"
onClick={this.handleClick}
>
<MoreVertIcon />
</IconButton>
...
Working copy of your code is here
I am new to React and am using the npm package Material UI icons (https://www.npmjs.com/package/#material-ui/icons) and displaying icons within a React component as such:
Importing:
import KeyboardArrowRightIcon from 'material-ui/svg-icons/hardware/keyboard-arrow-right';
and rendering:
readMoreLink={<a href={someUrl} >Read more <KeyboardArrowRightIcon /></a>}
However, since KeyboardArrowRightIcon is an SVG provided by the npm package, it comes with it's own fill colour:
Eg: <svg viewBox="0 0 24 24" style="display: inline-block; color: rgba(0, 0, 0, 0.54);...
I know I can override this colour by having a style attribute within the element, eg:
<KeyboardArrowRightIcon style={{ fill: '#0072ea' }} />
But is there anyway to make this a SCSS variable (style={{ fill: $link-color }})?
I worry if the link colour changes in the style sheet someone will have to hunt down all these hard coded instances later.
Change Icon Color
<HomeIcon />
<HomeIcon color="primary" />
<HomeIcon color="secondary" />
<HomeIcon color="action" />
<HomeIcon color="disabled" />
<HomeIcon style={{ color: green[500] }} />
<HomeIcon style={{ color: 'red' }} />
Change Icon Size
<HomeIcon fontSize="small" />
<HomeIcon />
<HomeIcon fontSize="large" />
<HomeIcon style={{ fontSize: 40 }} />
MDI using Icon component
<Icon>add_circle</Icon>
<Icon color="primary">add_circle</Icon>
<Icon color="secondary">add_circle</Icon>
<Icon style={{ color: green[500] }}>add_circle</Icon>
<Icon fontSize="small">add_circle</Icon>
<Icon style={{ fontSize: 30 }}>add_circle</Icon>
For the Font
<Icon className="fa fa-plus-circle" />
<Icon className="fa fa-plus-circle" color="primary" />
<Icon className="fa fa-plus-circle" color="secondary" />
<Icon className="fa fa-plus-circle" style={{ color: green[500] }} />
<Icon className="fa fa-plus-circle" fontSize="small" />
<Icon className="fa fa-plus-circle" style={{ fontSize: 30 }} />
Resouces to learn more abo it, Icons
Just add a style fill: "green"
Example: <Star style={{fill: "green"}}/>
The simplest way to specify/override the color of an Icon in Material-UI is to use a custom CSS class name.
Suppose that you want to show a green checkbox rather than a red triangle, depending on the outcome of some process.
You create a function somewhere inside your code, for example like this:
function iconStyles() {
return {
successIcon: {
color: 'green',
},
errorIcon: {
color: 'red',
},
}
}
You then apply makeStyles to that function, and run the result.
import { makeStyles } from '#material-ui/core/styles';
...
const classes = makeStyles(iconStyles)();
Inside your render function, you can now use the object classes:
const chosenIcon = outcome
? <CheckCircleIcon className={classes.successIcon} />
: <ReportProblemIcon className={classes.errorIcon} />;
The function I mentioned first in this answer actually accepts a theme as input and allows you to modify/enrich that theme: this ensures that your custom classes aren't seen as exceptions, but rather as integrations inside a more comprehensive visual solution (for example, icon colors in a theme are best seen as encodings).
Material-UI is very rich and I'd encourage you to explore also other existing customisation mechanisms.
Update: 2022 July MUI5
There are multiple ways to change icon color
<HomeIcon sx={{color: "#FC0"}} />
<HomeIcon htmlColor="red" />
<HomeIcon color="primary" />
<HomeIcon color="success" />
<HomeIcon color="action" />
<HomeIcon color="disabled" />
<HomeIcon color="error" />
<HomeIcon sx={{ color: pink[500] }} />
Using sx prop you can specify any hex/rgb color code or colors from your theme palette
Example :
import { red } from '#mui/material/colors';
<HomeIcon sx={{ color: red[800] }} />
This is what I do
I use MUI v4.5.1. Use the color prop API with value inherit and add a div or span wrapper around and add your color there.
From the API docs
color default value:inherit. The color of the component. It supports those theme colors that make sense for this component.
Add star icon
import React from 'react';
import Star from '#material-ui/icons/StarRounded';
import './styles.css';
export function FavStar() {
return (
<div className="star-container">
<Star size="2em" fontSize="inherit" />
</div>
);
}
In style.css
.star-container {
color: red;
font-size: 30px;
}
You can do like this: <PlusOne htmlColor="#ffaaee" />
The simplest way I found is using the following.
import { styled } from '#material-ui/styles';
import { Visibility } from '#material-ui/icons';
const MyVisibility = styled(Visibility)({
color: 'white',
});
You can set a default color for all icons by creating a custom theme with createMuiTheme():
createMuiTheme({
props: {
MuiSvgIcon: {
htmlColor: '#aa0011',
}
}
})
This will set the default value of the htmlColor prop for every icon like <KeyboardArrowRightIcon/>. Here's a list of other props you can set.
Overwriting the material UI Icon color like below
in js
const [activeStar, setActiveStar] = useState(false);
<IconButton onClick={() => setActiveStar(!activeStar)}>
{activeStar ? (
<StarOutlined className="starBorderOutlined" />
) : (
<StarBorderOutlined />
)}
</IconButton>
in Css
.starBorderOutlined {
color: #f4b400 !important;
}
Surprised that no one has suggested a site-wide solution yet.
You can override the colors that are assigned for the "colors" option here https://material-ui.com/api/icon/#props
by adding an override to your theme (you'll have to define a custom theme if you aren't already) https://material-ui.com/customization/theming/#createmuitheme-options-args-theme
After defining a theme though, it's as simple as
const theme = createMuiTheme({
"overrides": {
MuiSvgIcon: {
colorPrimary: {
color: ["#625b5b", "!important"],
},
colorSecondary: {
color: ["#d5d7d8", "!important"],
},
},
...
});
Only correct solution that covers two tone (TwoTone) icons is to pass it htmColor property:
React.createElement(Icon, {htmlColor: "#00688b"})
To change color of your MUI Icons your have three ways: (Source)
//using a hex value
<BathroomIconOutlined style={{ color: "#ffee66" }} />
//using a standard css colour
<BathroomTwoToneIcon style={{ color: "blue" }} />
//import a material ui colour, and use that
import { purple } from "#mui/material/colors";
<BathroomIcon style={{ color: purple[500] }} />
Or use directly the MUI properties: (Source)
import SearchOutlined from '#mui/icons-material/SearchOutlined';
<SearchOutlined style={{ color: 'primary', fontSize: "small" }} />
<SearchOutlined style={{ color: 'secondary', fontSize: "medium" }} />
<SearchOutlined style={{ color: 'action', fontSize: "large" }} />
<SearchOutlined style={{ color: 'error', fontSize: 16 }} />
<SearchOutlined style={{ color: 'disabled', fontSize: 16 }} />
You can use SvgIcon, from the documentation:
The SvgIcon component takes an SVG path element as its child and
converts it to a React component that displays the path, and allows
the icon to be styled and respond to mouse events. SVG elements should
be scaled for a 24x24px viewport.
You must use the devTools to extract the path of the KeyboardArrowRightIcon icon:
Then use it with your custom color like this:
<SvgIcon
component={svgProps => {
return (
<svg {...svgProps}>
{React.cloneElement(svgProps.children[0], {
fill: myColorVariable
})}
</svg>
);
}}
>
<path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"></path>
</SvgIcon>
I had the same problem, me solution was:
import React from 'react';
import pure from 'recompose/pure';
import {SvgIcon} from '#material-ui/core';
let smile = (props) => (
<SvgIcon {...props}
component={props => {
return (
<svg {...props}>
{React.cloneElement(props.children[0], {
fill: "#4caf50"
})}
</svg>
);
}}
>
<path d="M256,32C132.281,32,32,132.281,32,256s100.281,224,224,224s224-100.281,224-224S379.719,32,256,32z M256,448
c-105.875,0-192-86.125-192-192S150.125,64,256,64s192,86.125,192,192S361.875,448,256,448z M160,192c0-26.5,14.313-48,32-48
s32,21.5,32,48c0,26.531-14.313,48-32,48S160,218.531,160,192z M288,192c0-26.5,14.313-48,32-48s32,21.5,32,48
c0,26.531-14.313,48-32,48S288,218.531,288,192z M384,288c-16.594,56.875-68.75,96-128,96c-59.266,0-111.406-39.125-128-96"></path>
</SvgIcon>
);
smile = pure(smile);
smile.displayName = 'smile';
smile.muiName = 'SvgIcon';
export default smile;
Solution that works the best for myself:
const EditableIcon = ({ icon, color, sx }: PropsWithChildren<EditableIconProps>) => {
const c = useIconStyles()
return React.cloneElement(icon, {
...(color && { color }),
...(sx && { sx }),
classes: {
colorPrimary: c.colorPrimary,
colorSecondary: c.colorSecondary,
colorAction: c.colorAction
}
})
}
If color is set, your classes would override default values.