React Styling in Props - reactjs

I did some styling for a material ui button and now I want to move the style={{backgroundColor}} part to the top of the function, right before the return.
Does someone know how to do that?
const styles = {
root: {
color: "#FFFFFF",
backgroundColor: "#05164D",
transition: "linear 0.5s",
"&:hover": {
opacity: 0.9,
boxShadow: "0 3px 5px 2px rgba(153, 153, 153, .8)"
}
}
};
const StyledButton = props => {
const { classes } = props;
let customColor = props.customColor || "#05164D";
let backgroundColor = customColor;
return (
<div>
<IconButton
className={classes.root}
{...props}
aria-label="StyledButton"
style={{ backgroundColor }}
/>
</div>
);
};
export default withStyles(styles)(StyledButton);

I think it is important to mention that {backgroundColor} is a shorthand for {backgroundColor: backgroundColor}. So in ES6 you can simply use the variable name, if the value of the property should be the same as the variable name. This variable is initialized within the curly braces, which wrap the property value. That's why it is {{ backgroundColor }}. If you want to initialze the variable above the render you can do it like this.
const StyledButton = props => {
const { classes } = props;
let customColor = props.customColor || "#05164D";
let style = { backgroundColor: customColor };
return (
<div>
<IconButton
className={classes.root}
{...props}
aria-label="StyledButton"
style={style}
/>
</div>
);
};

Related

How to use conditional styles with MUI v5 using emotion styled

I'm migrating from MUI v4 to v5. In v4 I was using clsx with TextField to add conditional styles.
export const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
// ...
},
valid: {
"& fieldset": {
borderColor: theme.palette.success.main,
borderWidth: 2
}
}
})
);
const classes = useStyles();
<TextField
{...props}
className={clsx(classes.root, { [classes.valid]: isValid })}
/>
I'm trying to find a similar approach in MUI v5. Is there any alternative for conditional styles in MUI v5 other than with clsx and makestyles.
Let me know if more information is required.
There are multiple ways to do that:
1. Conditional operator
Use this if you want to conditionally set a property based on a boolean value.
const Box1 = styled(Box, {
shouldForwardProp: (prop) => prop !== "showBorder"
})(({ showBorder }) => ({
border: showBorder ? "solid red 5px" : "none"
}));
<Box1 />
<Box1 showBorder />
2. Dictionary
Use this if you want to conditionally set a property based on multiple values.
import { styled, darken } from "#mui/material/styles";
const colors = {
hauntedForest: "#0b5b38",
redLust: "#b20608",
spaceExplorer: "#1244a1",
default: "#000000"
};
const Box2 = styled(Box, {
shouldForwardProp: (prop) => prop !== "variant"
})(({ variant }) => ({
backgroundColor: colors[variant] ?? colors.default,
border: "5px solid " + darken(colors[variant] ?? colors.default, 0.3)
}));
<Box2 variant="hauntedForest" />
<Box2 variant="redLust" />
<Box2 variant="spaceExplorer" />
<Box2 />
3. Short-circuit evaluation + Spread operator
Use this if you want to conditionally set multiple properties.
const Box3 = styled(Box, {
shouldForwardProp: (prop) => prop !== "isFancy" && prop !== "isFancyBorder"
})(({ theme, isFancy, isFancyBorder }) => ({
...(isFancy && {
borderRadius: theme.shape.borderRadius,
boxShadow: "0 4px 6px gray, 0 1px 3px rgba(0, 0, 0, 0.08)",
backgroundImage: "linear-gradient(90deg, #be5af7, #165b91)"
}),
...(isFancyBorder && {
backgroundColor: "transparent",
border: "5px solid transparent",
borderImage: "linear-gradient(90deg, #be5af7, #165b91)",
borderImageSlice: 1
})
}));
<Box3 isFancy />
<Box3 isFancyBorder />
All of the methods above can also be applied when using sx props since they use JS object to describe the styles.
Live Demo
This seem to work for me
Using sx
sx={{ px: variable ? 8 : null }}
sx with breakpoint
sx={{ px: { md: variable ? 8 : null } }}
prop
<Typography align={variable ? 'center' : 'inherit'}>
Using className
className={ variable ||'class-name'}

Material UI pagination - How Can I use custom style for number of pages?

I'm quite new to material-ui. I'm trying to build this component.
I was able to do the style for the next and previous buttons the same as in the picture.
The normal style shows the number of pages as a numbered group besides each other like this:
Are there any properties that I can pass for the pagination component, in which I can change the style?
Here is the code:
import Pagination from "#material-ui/lab/Pagination";
import useStyles from "./styles";
const ReviewsPagination = () => {
const classes = useStyles();
return (
<div className={classes.root}>
<Pagination count={8} />
</div>
);
};
export default ReviewsPagination;
and the style file:
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
root: {
"& .MuiPagination-ul": {
"& > li:first-child": {
"& button": {
borderRadius: "50%",
border: "1px solid black",
width: "48px",
height: "48px",
},
},
"& > li:last-child": {
"& button": {
borderRadius: "50%",
border: "1px solid black",
width: "48px",
height: "48px",
},
},
},
},
});
export default useStyles;
Thank you!
you can use the usePagination hook to customize the pagination component. Like below:
export default function UsePagination() {
const classes = useStyles();
const { items } = usePagination({
count: 10,
});
return (
<nav>
<ul className={classes.ul}>
{items.map(({ page, type, selected, ...item }, index) => {
let children = null;
if (type === 'next' || type === 'previous') {
children = (
<button type="button" {...item}>
{type}
</button>
);
}else if(selected){
children = <div>{`${page}/10`}</div>
}
return <li key={index}>{children}</li>;
})}
</ul>
</nav>
);
}

Changing the arrow/icon colour material ui select

I'm trying to change my icon to white
Here is my current code but not sure how to change icon colour property:
Link to codesandbox sample
<NativeSelect
disableUnderline
style={{
paddingLeft: 10,
borderRadius: 20,
color: "white",
background: "#121c30",
boxShadow: "0px 5px 8px -3px rgba(99,0,0,0.14)",
}}
defaultValue={"Last 7 days"}
onChange={handleChange}
>
......
</NativeSelect>
The material provides you, one class, for changing the color of that icon.
.MuiNativeSelect-icon {
color: red
}
const MyIcon = (props)=> {
const { style, ...otherProps } = props;
const colorStyle = {
color: 'white',
};
const styles = { ...style, ...colorStyle };
return <ArrowDropDownIcon {...otherProps} style={styles} />
}
<NativeSelect
IconComponent={MyIcon}
...
/>
I would recommend not to use inline styles, as you cannot apply them in classes property, in your case this should work for you
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
iconSelect: {
color: "white"
},
});
...
export default function App() {
const classes = useStyles();
...
<NativeSelect
disableUnderline
classes={{icon: classes.iconSelect}}
...
>
https://codesandbox.io/s/table-forked-7w6nw
Create .css, where is your choice.
there. instead of writing: color:white; you can write color:white !important;

How to change the progress bar background color dynamically in react material ui?

//Component Style:
const BorderLinearProgress = withStyles(theme => ({
bar: {
borderRadius: 8,
backgroundColor: "red"
}
}))(LinearProgress);
//Component use:
<BorderLinearProgress variant="determinate" value={50} />
I am new to react and material-ui.
In the above code I need to pass or change bar:backgroundColor dynamically.
Please let me know what are the options to do.
Thanks in advance
You can pass your color with the theme variable.
// Passing theme
const useStyles = makeStyles((theme) => ({
bar: props => ({
borderRadius: 8,
backgroundColor: props.color
})
}))
//Using style in component
...
const [progressColor, setProgressColor] = React.useState({ color: 'red' })
const classes = useStyles(progressColor);
// Update color based on your requirements i.e. setProgressColor({color: 'green'}) in some useEffect() when progress crosses some threshold
return (
<LinearProgress color={classes.bar} />
)
...
You can find an example in official docs: https://material-ui.com/styles/basics/#adapting-based-on-props
Below code works fine with dynamic values and colors
const LinearProgressBar: React.FC<ILinearProps> = ({ value, color }) => {
const useStyles = makeStyles({
root: {
height: 10,
borderRadius: 5
},
colorPrimary: {
backgroundColor: '#E9E9E9'
},
bar: {
borderRadius: 5,
backgroundColor: color
}
});
const classes = useStyles();
return (
<LinearProgress
variant="determinate"
value={value}
classes={{
root: classes.root,
colorPrimary: classes.colorPrimary,
bar: classes.bar
}}
/>
);
};
export default LinearProgressBar;
You can do it in two ways:
1). just Write
<LinearProgress style={{backgroundColor: "red"}} variant="determinate" value={50} />
2).
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
const styles = {
LinerProgressColor: {
backgroundColor: 'red',
},
};
function BorderLinearProgress (props) {
return <LinearProgress className={LinerProgressColor} variant="determinate" value={50} />;
}
export default withStyles(styles)(BorderLinearProgress);

In React, how to pass a dynamic variable to a const CSS Style list?

I'm using react-dropzone to allow a user to upload a profile photo.
I define the custom CSS like so:
const dropzoneStyle = {
width: `200px`,
height: `200px`,
backgroundColor: `#1DA1F2`,
};
Inside the method to render the DropZone input, I can detect if their is a file preview which is populated after a user selects an image to be uploaded..
What I want to do is, if the file.preview exists, send the file.preview the the dropzoneStyle so a background-image is added to the CSS.
const renderDropzoneInput = (field) => {
const files = field.input.value;
let dropzoneRef;
if (files[0]) {
console.log(files[0].preview)
}
return (
<div>
<Dropzone
name={field.name}
ref={(node) => { dropzoneRef = node; }}
accept="image/jpeg, image/png"
style={dropzoneStyle}
>
How can I pass files[0].preview to the style dropzoneStyle with React?
I usually just define the style as an arrow function that returns the style object, and pass in whatever parameters are needed for the style. There is a shorthand notation for returning an object literal from an arrow function that works nicely for this.
const style = () => ({});
Just remember to only use ternary operators if using the shorthand, otherwise you would just need to explicitly return an object.
So, for your style:
const dropzoneStyle = (isPreview) => ({
width: `200px`,
height: `200px`,
backgroundColor: `#1DA1F2`,
backgroundImage: (isPreview) ? 'url(/path/to/image.jpg)' : 'none',
});
This adds the image is isPreview is true, but keeps it blank if not.
Then in your component, call the function where the style goes:
return (
<div>
<Dropzone
{...otherProps}
style={ dropzoneStyle(isPreview) }
>
</div>
);
Assuming files[0].preview returns a file (image) URL, you should be able to set a new style and pass it to the Dropzone component.
Something along these lines:
const renderDropzoneInput = (field) => {
const files = field.input.value;
let dropzoneRef;
render() {
let dropzoneStyle = {
width: `200px`,
height: `200px`,
backgroundColor: `#1DA1F2`,
};
if (files[0]) {
dropzoneStyle = {
width: `200px`,
height: `200px`,
backgroundColor: `#1DA1F2`,
backgroundImage: `url(${files[0].preview})`,
// or to use a fixed background image
// backgroundImage: `url(/path/to/static/preview.png)`,
backgroundPosition: `center center`,
backgroundRepeat: `no-repeat`
};
}
return (
<Dropzone
name={field.name}
ref={(node) => { dropzoneRef = node; }}
accept="image/jpeg, image/png"
style={dropzoneStyle}
/>
)
}
}
a spread operator could be used to DRY this code a bit, with:
let dropzoneStyle = {
width: `200px`,
height: `200px`,
backgroundColor: `#1DA1F2`,
};
if (files[0]) {
dropzoneStyle = {
...dropzoneStyle,
backgroundImage: `url(/path/to/static/preview.png)`,
backgroundPosition: `center center`,
backgroundRepeat: `no-repeat`
};
}

Resources