How to separate MUI setup to an external js file? - reactjs

I have this MUI codes that are applied to multiple components. I want to separate it into a single file like 'MuiSetup.js' and then import the file to the component that I am using. I've tried with as React component, however, it does not work and I have zero clues how can I do this.
// Styling TextField
const ValidationTextField = withStyles({
root: {
'& input:valid + fieldset': {
borderColor: '#ff9800',
borderWidth: 1,
},
'& .MuiOutlinedInput-root': {
'&:hover fieldset': {
borderColor: '#ff9800',
},
'&.Mui-focused fieldset': {
borderColor: '#ff9800',
},
},
'& input:invalid + fieldset': {
borderColor: '#ff9800',
borderWidth: 1,
backgroundColor: 'black',
},
'& input:valid:focus + fieldset': {
borderColor: '#ff9800',
borderLeftWidth: 5,
padding: '4px !important', // override inline-style
},
},
})(TextField);
//Style MUI
const useStyles = makeStyles((theme) => ({
root: {
height: '100vh',
backgroundColor: 'black',
},
input: {
color: '#ff9800',
},
formBackground: {
background: 'black',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
},
paper: {
margin: theme.spacing(8, 4),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
},
form: {
width: '100hv',
height: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(0),
color: '#ff9800',
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
//Label Style
const useLabelStyles = makeStyles({
root: {
color: '#ff9800',
'&.Mui-focused': {
color: '#ff9800',
},
fontSize: '14px',
},
});
-----------
const App = () => {......}
export default App
How can I take the MUI part to the separated file?

In one of my projects I actually used createMuiTheme() in another file then added my own classes under the overrides. Then the entire app is wrapped in the ThemeProvider which you pass in your custom theme. Then you can just give the component a className.
So my MuiSetup.js equivalent file looks something like this:
import { createMuiTheme } from '#material-ui/core';
// Describe material ui theme
export const customTheme = (isDark = false) => {
return createMuiTheme({
palette: isDark
? {
common: {...},
background: {...},
primary: {...},
secondary: {...},
error: {...},
text: {...},
}
: {// Light theme stuff},
overrides: {
MuiAppBar: {...},
MuiButton: {
// Button example...
root: {
'&.CustomButton': {
margin: 0,
},
'&.OtherCustomButton': {
width: '100%',
minHeight: 'inherit',
},
'&$disabled': {
color: grey[600],
},
},
outlinedSecondary: {
'&$disabled': {
border: `1px solid ${grey[600]}`,
},
},
},
// Other mui components...
},
});
};
You'll need to read the API docs to find your inputs.
Then the ThemeProvider:
import React, { Component } from 'react';
import { ThemeProvider } from '#material-ui/core';
import { customTheme } from './MuiSetup.js';
class App extends Component {
render() {
const currentTheme = customTheme(true);
return (
<ThemeProvider theme={currentTheme}>
<h1>My app</h1>
// Usage
<Button className='CustomButton'/>
</ThemeProvider>
);
}
}
export default App;
Then from any component within the app, you can do: <Button className='CustomButton'/> as I've done above.
Not sure if this is the best way, might be a bit tricky to make multiple updates however you could do something similar in your situation and create a function in another file that returns your custom makeStyles.
HTH

Ciao, to put these customizations in a separated file is just necessary to define them in aseparated file with the key "export const ..." and then, when you want to import them, just write:
import { ValidationTextField } from "./muiCustomizations"; // supposing that you defined your customizations in a file called muiCustomizations.js
and then you can use them:
function MyComponent() {
return (
<div>
<ValidationTextField />
</div>
);
}
Here a codesandbox example.

Related

I cannot change font-color in TextField component from Material UI

I cannot change font-color in TextField Material UI component. I try to do it using createTheme() and when I add class '& .MuiOutlinedInput-input' in code sandbox font-color changes as it should, but when I apply it to the app code it doesn't work.
Will appreciate Your support.
Below is the implementation:
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
backgroundColor: `#EDEDED`,
'& .MuiOutlinedInput-notchedOutline': {
border: 'none',
},
'&.Mui-focused': {
'& .MuiOutlinedInput-notchedOutline': {
border: 'none',
},
},
'& .MuiOutlinedInput-input': {
padding: '10px',
fontSize: '13px',
color: 'red',
},
},
},
},
},
});
<ThemeProvider theme={theme}>
<InputForm
name={'phoneNumber'}
id={'phoneNumber'}
label={phoneNumberLabelTxt}
disabled={isDisabledInputs}
/>
</ThemeProvider>
Your code worked in my local repo. however if its not working for you then try below code which also worked for me.
'&.MuiOutlinedInput-root': { // no space between & and .
padding: '10px',
fontSize: '13px',
color: 'red',
},

Change default hover color of TableRow MUI

I would like to change the default hover color of a MUI TableRow by adding styles to the TableRow.
This question has been asked before, but the solutions are 3-4 years old, and they aren't working for me in my case. The docs also make it seem like there shouldn't be such arduous workarounds to achieve the goal.
The most relevant thread regarding solutions is here. At best, I can change the color of the hover for a cell, but not the whole row.
Below is my code; included you will find all of my attempts commented out:
import React, { Dispatch, SetStateAction, useCallback } from 'react';
import { makeStyles, TableCell, TableRow } from '#material-ui/core';
import EditIcon from '../../assets/common/edit-icon.svg';
import { Link } from 'react-router-dom';
import { COLORS } from '../../constants/theme';
import { format } from 'date-fns';
import { Box } from '#material-ui/core';
const useStyles = makeStyles(theme => ({
tableRow: {
'& .MuiTableCell-root': {
borderRight: `1px solid ${theme.palette.grey[200]}`,
borderBottom: 'none',
padding: 5,
paddingTop: 8,
paddingBottom: 8,
cursor: 'pointer',
minWidth: 25,
//this works but only for cell hover, not the full row
// "&:hover": {
// backgroundColor: `${COLORS.BLUE} !important`,
// },
},
//this doesn't work
// hover: {
// backgroundColor: `${COLORS.BLUE} !important`
// },
//this doesn't work
// '& .MuiTableRow-hover': {
// backgroundColor: `${COLORS.BLUE} !important`
// },
//this doesn't work
// hover: {
// "&:hover": {
// backgroundColor: "green !important",
// },
// },
//this doesn't work
// root: {
// '&:hover': {
// backgroundColor: `${COLORS.BLUE} !important`
// },
// },
//this doesn't work
// '& .MuiTableRow-hover': {
// backgroundColor: `${COLORS.BLUE} !important`
// },
//this doesn't work
// MuiTableRow: {
// root: {
// '&:hover': {
// backgroundColor: `${COLORS.BLUE} !important`,
// }
// }
// },
//this doesn't work
// '& .MuiTableRow-root': {
// hover: { backgroundColor: "green !important" }
// },
// root: {
// '&:hover': {
// backgroundColor: `${COLORS.BLUE} !important`
// },
// },
'& .MuiTableCell-root:first-child': {
border: 'none'
},
},
selectedRow: {
backgroundColor: `${COLORS.BLUE} !important`,
'& .MuiTableCell-root': {
color: COLORS.WHITE
}
},
editIcon: {
backgroundImage: `url(${EditIcon})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
width: 18,
height: 18
}
}));
interface IProps extends Omit<unknown, 'children'> {
children?: React.ReactNode;
isSelected: boolean;
redirectTo: string;
onSelect: Dispatch<SetStateAction<string>>;
cells: Array<string | number | Date | boolean | null | undefined>;
id: string;
}
const TableRowComponent = ({
isSelected,
onSelect,
redirectTo,
cells,
id
}: IProps): JSX.Element => {
const classes = useStyles();
const getCorrectFormat = useCallback(
cell => {
return cell instanceof Date
? format(cell as Date, "MM/dd/yyyy hh:mmaaaaa'm'")
: cell;
},
[cells]
);
return (
<TableRow
className={classes.tableRow}
classes={{ selected: classes.selectedRow }}
selected={isSelected}
onClick={() => onSelect(id)}
hover={true}
>
<TableCell align="center">
{isSelected && (
<Link to={redirectTo}>
<div className={classes.editIcon} />
</Link>
)}
</TableCell>
{cells.map(cell => (
<TableCell key={(id + Math.random()).toString()} align="center">
<Link to={redirectTo}>
<Box>
{cell || cell === 0 ? getCorrectFormat(cell) : 'null'}
</Box>
</Link>
</TableCell>
))
}
</TableRow >
);
};
export default TableRowComponent;
Thanks for your help!
check with below method. tested in MuiV5 and working for me. adjust according to your need. also you dont need to add hover={true} just hover is sufficient.
Option1 : with sx props
<TableRow
...
hover
sx={{
'&.MuiTableRow-root:hover':{
backgroundColor: 'red'
},
}}
>
...
</TableRow>
option 2: with useStyles
const useStyles = makeStyles(theme => ({
tableRow: {
...
'&.MuiTableRow-root:hover':{
backgroundColor: 'red' ,
},
},
}));
Using MUI v5.3.0:
You can change the color with the sx property like this:
<TableRow
sx={{
'&.MuiTableRow-hover': {
'&:hover': {
backgroundColor: 'papayawhip',
},
},
}}
hover
>
...
</TableRow>
haven't tried it but I guess you can use this as well in your useStyles
The solution that worked with useStyles was to add
"&:hover": {
backgroundColor: `${COLORS.BLUE} !important`,
},
into the tableRow. It seems kinda naked...but it works.
Full context in useStyles below
const useStyles = makeStyles(theme => ({
tableRow: {
'& .MuiTableCell-root': {
borderRight: `1px solid ${theme.palette.grey[200]}`,
borderBottom: 'none',
padding: 5,
paddingTop: 8,
paddingBottom: 8,
cursor: 'pointer',
minWidth: 25,
},
//this worked
"&:hover": {
backgroundColor: `${COLORS.BLUE} !important`,
},
'& .MuiTableCell-root:first-child': {
border: 'none'
},
},
selectedRow: {
backgroundColor: `${COLORS.BLUE} !important`,
'& .MuiTableCell-root': {
color: COLORS.WHITE
},
'& ..MuiTableRow-root.Mui-selected': {
hover: { backgroundColor: 'red' }
}
},
editIcon: {
backgroundImage: `url(${EditIcon})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
width: 18,
height: 18
}
}));
I'm not sure why seemingly better/more logical options did not work.

Material UI - Typography fontSize

Recently I upgraded my material UI version from 3.9.4 to 4.11.0, I had to replace these on the theme style override:
to avoid these warnings:
But I require to put that fontSize styles wit !important since that's working on a widget which is rendered on different web pages and if I don't use the !important, then the styles are overritten by the ones of the page, Is there a way to use !important label on the typography fontSize style on the latest versions?
I tried using fontSize: `16 !important`, and fontSize: [[16], ['!important']
without success.
any help would be welcome, Thanks in advice!!!
EDIT:
On the override part it receives the styles even as a string but on the typography part, even using #Ryan Cogswell suggestion, it still throw me the same warning
const Theme = createMuiTheme({
root: {
display: 'flex',
},
palette: {
primary: {
main: '#052d4f',
},
secondary: {
main: '#2376b8',
},
},
typography: {
fontFamily: 'Arial, Helvetica, sans-serif !important',
fontSize: [16, "!important"],
},
overrides: {
MuiTypography: {
body2: {
fontFamily: 'Arial, Helvetica, sans-serif !important',
fontSize: "16px !important",
},
subtitle1: {
fontFamily: 'Arial',
fontSize: "16px !important",
},
},
MuiTablePagination: {
toolbar: {
fontSize: "14px !important",
}
},
MuiAutocomplete: {
root: {
paddingLeft: "15px",
paddingRight: "15px",
},
groupLabel: {
fontWeight: 700,
color: "black",
fontSize: "14px !important",
},
option: {
paddingTop: "0px",
paddingBottom: "0px",
fontSize: "14px !important",
height: "25px"
}
}
},
status: {
danger: 'orange',
},
});
The syntax you want is fontSize: [16, "!important"]. It also works to put the 16 within an array, but you can't put "!important" in an array.
Here's a working example:
import React from "react";
import { ThemeProvider, createMuiTheme } from "#material-ui/core/styles";
import Typography from "#material-ui/core/Typography";
const theme = createMuiTheme({
//v5.0.0
typography: {
body2: {
fontSize: [16, "!important"]
}
},
//older versions
overrides: {
MuiTypography: {
body2: {
fontSize: [16, "!important"]
}
}
}
});
export default function App() {
return (
<ThemeProvider theme={theme}>
<div className="App">
<Typography variant="body2">Hello CodeSandbox</Typography>
</div>
</ThemeProvider>
);
}
JSS Documentation: https://cssinjs.org/jss-syntax?v=v10.4.0#modifier-important

can't pass theme to child components Material-Ui - React?

I am trying to create a global theme with shared styles between component, so i don't need to repeat the same classes in each component, so i have a theme file:
export default {
palette: {
primary: {
light: '#039be5',
main: '#01579b',
dark: '#b22a00',
contrastText: '#fff'
},
secondary: {
main: '#004d40',
contrastText: '#fff'
}
},
typography: {
userNextVariants: true
},
form: {
textAlign: 'center',
},
img: {
maxWidth: 60,
margin: '1.5rem auto 5px'
},
textField: {
margin: 20
},
button: {
marginTop: 16,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
margin: 'auto',
width: 80,
height: 50
},
customError: {
color: 'red',
fontSize: '0.7rem'
},
small: {
display: 'block',
marginTop: '1rem'
},
circularProgress: {
color: '#fff',
position: 'absolute'
}
}
and in App.js
import themeFile from './theme';
import createMuiTheme from '#material-ui/core/styles/createMuiTheme';
import {MuiThemeProvider} from '#material-ui/core/styles';
const theme = createMuiTheme(themeFile);
<MuiThemeProvider theme={theme}>
<Signin />
</MuiThemeProvider>
in Signin page:
import makeStyles from '#material-ui/core/styles/makeStyles';
const useStyles = makeStyles(theme => ({
...theme
}));
const Signin = (props) => {
const classes = useStyles();
return //some form and style elements using classes
}
But i get an error TypeError: color.charAt is not a function, i don't know if i am doing it right, i tried to use withStyles but ii got the same error, what is wrong in my code?
Ciao, the problem is on color in customError. You cannot use 'red' in material ui theme. Try to replace it with #FF0000.
I found a solution for my problem, is by wrapping all properties other than pallette in an object like this
theme.js
export default {
palette: {
primary: {
light: '#039be5',
main: '#01579b',
dark: '#b22a00',
contrastText: '#fff'
},
secondary: {
main: '#004d40',
contrastText: '#fff'
}
},
spread: {
typography: {
userNextVariants: true
},
form: {
textAlign: 'center',
},
img: {
maxWidth: 60,
margin: '1.5rem auto 5px'
},
textField: {
margin: 20
},
button: {
marginTop: 16,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
margin: 'auto',
width: 90,
height: 50
},
customError: {
color: '#FF0000',
fontSize: '0.7rem'
},
small: {
display: 'block',
marginTop: '1rem'
},
circularProgress: {
color: '#fff',
position: 'absolute'
}
}
}
Signin page
const useStyles = makeStyles(theme => ({
...theme.spread
}));

How to make TextField Material UI component start with white text and underline

I'm trying to make my entire material UI TextField tag white. The label and the border, both off focus and on focus.
The on focus is all white, but I can't get the off-focus to be white. I see it in the dev tools as, but it must not be specific enough. I've even tried !important, but that still doesn't take priority over the original color.
I've tried about half a dozen methods and only have been able to get the on focus to work. Not sure what I'm doing wrong here.
import React from 'react';
import { withStyles } from '#material-ui/styles';
import TextField from '#material-ui/core/TextField';
const styles = theme => ({
eventWrap: {
width: '90%',
margin: '0 auto',
'$ eventInput': {
color: 'white',
},
},
eventExplaination: {
fontSize: '25px',
marginBottom: '50px',
},
root: {
color: "white !important",
borderColor: 'white !important',
},
input: {
color: "white !important",
borderColor: 'white !important',
}
});
const CssTextField = withStyles({
root: {
'& label.Mui-focused': {
color: 'white',
},
'& .MuiInput-underline:after': {
borderBottomColor: 'white',
},
},
})(TextField);
class Event extends React.Component {
nextSection = () => {
if(this.props.event !== '') {
this.props.nextSection( 'emotions' )
} else {
alert('you must write in a situation or event')
}
}
render() {
const { classes } = this.props;
return(
<div className={classes.eventWrap}>
<p className={classes.eventExplaination}>Write out an event or situation that made you feel anxious. Keep it factual, leave out all feelings about it.</p>
<CssTextField
id="custom-css-standard-input"
label="Type in Event/Situation"
value={this.props.event}
onChange={(e) => this.props.updateEvent( e.target.value )}
placeholder="Event/Situation"
fullWidth
className={classes.root}
InputProps={{ className: classes.input }}
color="primary"
/>
<button onClick={() => this.nextSection()}>Next</button>
</div>
)
}
}
export default withStyles(styles)(Event);
const WhiteTextField = withStyles({
root: {
'& .MuiInputBase-input': {
color: '#fff', // Text color
},
'& .MuiInput-underline:before': {
borderBottomColor: '#fff8', // Semi-transparent underline
},
'& .MuiInput-underline:hover:before': {
borderBottomColor: '#fff', // Solid underline on hover
},
'& .MuiInput-underline:after': {
borderBottomColor: '#fff', // Solid underline on focus
},
},
})(TextField);

Resources