MUI: BottomNavigationAction override label styles - reactjs

I'm implementing a BottomNavigation bar for mobile. I want the label texts to be UPPERCASE and add 5px to spacing to icon above.
<BottomNavigation
value={selectedTab}
onChange={this.handleTabChange}
className={classes.bottomNav}>
<BottomNavigationAction
label="Details"
value={0}
icon={<DescriptionIcon />}
className={classes.bottomNavLabel}
/>
<BottomNavigationAction
label="Card"
value={1}
icon={<CreditCardIcon />}
disabled={!navEnabled}
className={classes.bottomNavLabel}
/>
</BottomNavigation>
My styles look like this:
export default ({ spacing, breakpoints }: Theme) =>
createStyles({
bottomNav: {
position: 'fixed',
bottom: 0,
width: '100%',
},
bottomNavLabel: {
textTransform: 'uppercase',
marginTop: 5,
},
})
I tried styling in bottomNavLabel class but it's hitting the whole button element. I only want to hit the <span> element with the label inside.
According to docs i can override classes.label but I can't get it to work. I suspect this means I create a wrapper component around BottomNavigationAction but I would prefer not to do this, as I'm not using this elsewhere and it feels kind of "bloated" to do.
How do I do that?

I figured it out. <BottomNavigationAction> takes a prop classes where I define the label styling. Like this:
<BottomNavigation
value={selectedTab}
onChange={this.handleTabChange}
className={classes.bottomNav}>
<BottomNavigationAction
label={<span className="bottomNavLabel">Details</span>}
value={0}
icon={<DescriptionIcon />}
classes={{label: classes.label}}
/>
<BottomNavigationAction
label={<span className="bottomNavLabel">Card</span>}
value={1}
icon={<CreditCardIcon />}
disabled={!navEnabled}
classes={{label: classes.label}}
/>
</BottomNavigation>
And styling:
export default ({ spacing, breakpoints }: Theme) =>
createStyles({
bottomNav: {
position: 'fixed',
bottom: 0,
width: '100%',
},
label: {
textTransform: 'uppercase',
marginTop: 5,
},
})

Related

How to add backgrounds to mui outlined textfield

I tried creating a custom MUI Text field with the following code:
const CustomTextField = styled(TextField)(() => ({
height: '56px',
width: '505px',
'& input + fieldset': {
borderRadius: '12px',
borderColor: 'white',
color: 'black'
}
}));
export function SearchTextField(props: TextFieldProps): JSX.Element {
return (
<CustomTextField
style={{ width: '505px' }}
InputProps={{
style: {
height: '56px'
},
startAdornment: (
<InputAdornment position="start">
<SearchOutlined fontSize="medium" color="info" />
</InputAdornment>
)
}}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
/>
);
}
When I add a background to the same, the input and the icon I have added is disappearing. I can still type and the input is still being taken but I can't see them.
It's supposed to look like this
But looks like this
Any kind of help is appreciated

React Material UI custom tooltip AND speed dial style

I'm trying to customize the tooltip appearance and the position of the speed dial but get an error when doing both.
const useStyles = makeStyles((theme) => ({
root: {
height: 380,
transform: "translateZ(0px)",
flexGrow: 1,
},
speedDial: {
position: "absolute",
bottom: theme.spacing(2),
right: theme.spacing(0),
},
tooltip: {
backgroundColor: "#37517e",
fontSize: "1.1em",
},
}));
<SpeedDial
ariaLabel="Tutor SpeedDial"
className={classes.speedDial}
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
onClose={handleClose}
onOpen={handleOpen}
open={open}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
TooltipClasses={classes}
onClick={handleClose}
/>
))}
</SpeedDial>
The code actually compiles and works but I get a console error
index.js:1 Material-UI: The key speedDial provided to the classes prop is not implemented in ForwardRef(Tooltip).
You can only override one of the following: popper,popperInteractive,popperArrow,tooltip,tooltipArrow,arrow,touch,tooltipPlacementLeft,tooltipPlacementRight,tooltipPlacementTop,tooltipPlacementBottom.
It's pretty clear that the issue is because ToolTipClasses cannot override the speedDial class but I'm not sure how else to do it.
Any guidance will be much appreciated
Thanks
I came up with solution by by creating a StyledSpeedDial instead so that I could remove the speeddial onbject from the classes style
const StyledSpeedDial = styled(SpeedDial)(({ theme }) => ({
position: "absolute",
"&.MuiSpeedDial-directionUp, &.MuiSpeedDial-directionLeft": {
bottom: theme.spacing(2),
right: theme.spacing(0),
},
}));
<StyledSpeedDial
ariaLabel="Tutor SpeedDial"
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
onClose={handleClose}
onOpen={handleOpen}
open={open}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
TooltipClasses={classes}
onClick={handleClose}
/>
))}
</StyledSpeedDial>

Material UI remove Menu padding

Is there any way to remove top and bottom padding from Menu component?
Tried to set padding to 0 in PaperProps and also in makeStyles but when I inspect the element on browser it still shows 8px default padding on top and bottom.
Here's the code if it helps:
<Menu
className={classes.menuSearchContainer}
PaperProps={{
style: {
backgroundColor: "#fff",
width: "270px",
paddingTop: '0px',
},
}}
>
<Input
className={classes.menuSearchInput}
type="text"
/>
target the list class from Menu classes prop.
<Menu
{...other props}
classes={{list:classes.list}}
>
{...meuItem}
</Menu>
and useStlyes will be:
const useStyles = makeStyles(() =>
createStyles({
list:{
padding:'0'
}
}),
);
Checkout a Codesandbox demo
use MenuListProps:
<Menu
className={classes.menuSearchContainer}
PaperProps={{
style: {
backgroundColor: "#fff",
width: "270px",
},
}}
MenuListProps={{ sx: { py: 0 } }}
>
<Input
className={classes.menuSearchInput}
type="text"
/>
Try this
<MenuItem dense=true />
From Materiul-UI dense : If true, compact vertical padding designed for keyboard and mouse input will be used.
This might be the issue.

How to reduce gap between Stars in material UI

I am trying to reduce gap between stars but no luck.
Code below for your ref
<MuiThemeProvider >
<Rating
onChange={() => console.log('onChange')}
value={4}
max={5}
iconFilled={<ToggleStar color={colors.green500} />}
iconHovered={<ToggleStarBorder color={colors.green500} />}
iconNormal ={<ToggleStarBorder color={colors.black300}/>}
className={classes.Rating}
spacing ={0}
onChange={(value) => console.log(`Rated with value ${value}`)}
/>
</MuiThemeProvider >
How can I resolve this?
Use the itemStyle and itemIconStyle props:
const smallDistanceStyle = {
width: 30,
height: 30,
padding: 5
}
const iconStyle = {
width: ...,
height: ...
}
<Rating
itemStyle={smallDistanceStyle}
itemIconStyle={iconStyle}
...
/>
I know this question was asked a while ago, but I found that
<Rating
value={5}
readOnly
sx={{
fontSize: "5rem",
"& .MuiRating-icon": {
width: '4.5rem'
}
}}
icon={<StarRateIcon fontSize="5rem" sx={{ color: "black" }} />}
/>
worked for me. It was able to bring the stars a little closer together.

Is there a way I can overwrite the colour the Material UI Icons npm package provides in React?

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.

Resources