React Material UI TextField Styles Not Working - reactjs

I'm trying to style the TextField API provided by Material UI (found here), however, for some reason, the styling is not being applied to the component. When I render it on a webpage, it's shown as in its default form. I would greatly appreciate any help on this. Here is my code.
interface CustomEmptyFieldProps {
usernameOrPass: string,
}
const baseMuiOutlineInputSizeAndPosition = {
borderRadius: 8,
width: '328px',
height: '40px',
};
const baseTextFieldSizeAndPosition = () => (
{
"& label:not(.Mui-focused)": { // Label in center of TextInput
marginTop: '-8px',
},
"& label:.Mui-shrink": { // Label in center of TextInput
marginTop:'-8px',
},
width: '328px',
height: '40px'
}
);
const useTextFieldStyles = (isTypedIn: boolean) => (
makeStyles({
"& label.Mui-focused, label:not(.Mui-focused)": { color: TextFieldColours.error.label },
"& .MuiOutlinedInput-root": {
"& fieldset": { borderColor: TextFieldColours.error.border, },
"&:hover fieldset": { borderColor: TextFieldColours.error.border, },
"&.Mui-focused fieldset": { borderColor: TextFieldColours.error.border },
...baseMuiOutlineInputSizeAndPosition,
},
...baseTextFieldSizeAndPosition,
})
);
const EmptyTextField = (props: CustomEmptyFieldProps) => {
const {
usernameOrPass,
} = props;
const inputLabel = "VolunteerHub " + usernameOrPass;
const errorMessage = "Please enter your VolunteerHub " + usernameOrPass;
const textFieldStyles = useTextFieldStyles(false);
return (
<div>
<TextField
classes={{ root: textFieldStyles, }}
placeholder={inputLabel}
id="outlined-error-helper-text"
defaultValue=""
helperText={errorMessage}
variant="outlined"
/>
</div >
);
}

Not sure about the way you declare your useTextFieldStyles. Here is how I would usually do:
const useTextFieldStyles = makeStyles(() => ({
root: {
"& label.Mui-focused, label:not(.Mui-focused)": {
color: TextFieldColours.error.label
},
"& .MuiOutlinedInput-root": {
"& fieldset": { borderColor: TextFieldColours.error.border },
"&:hover fieldset": { borderColor: TextFieldColours.error.border },
"&.Mui-focused fieldset": {
borderColor: TextFieldColours.error.border
},
...baseMuiOutlineInputSizeAndPosition
},
...baseTextFieldSizeAndPosition
}
}));
Working sample: https://codesandbox.io/s/runtime-sky-x14vr?file=/src/App.tsx:647-1173

Related

Passing props to classname using Emotion

My code looks like this:
export const MUISlider = styled(Slider)(({ theme, marks }) => ({
'& .MuiSlider-valueLabel': {
padding: [4, 12],
width: 33,
height: 30,
background: theme.palette.secondary.main,
},
'& .MuiSlider-markLabel': {
color: theme.palette.secondary.light,
'&[data-index="0"]': {
transform: 'none',
},
'&[data-index=`${({ marks }) => marks.length}`]': {
color: 'red',
},
},
'& .MuiSlider-markLabelActive': {
color: theme.palette.secondary.light,
},
}));
I want to pass a prop into the CSS here where it says '&[data-index="${({ marks }) => marks.length}"]': { . How would I format this correctly using #emotion?

I want to change the hover color to red. Wrote a topic for this element does not respond, how to fix it?

I want to change the hover color to red. Wrote a topic for this element does not respond, how to fix it? it turns out it goes dark by default, I want to change it to another color, for example, red, but it doesn't work
MuiOutlinedInput: {
styleOverrides: {
root: {
"& $notchedOutline": {
borderColor: "#ff0000",
},
"&:hover $notchedOutline": {
borderColor: "#ff0000",
},
"&$focused $notchedOutline": {
borderWidth: 0,
},
},
},
},
import OutlinedInput from "#mui/material/OutlinedInput";
const Search = () => {
return (
<>
<OutlinedInput />
</>
);
};
export default Search;
You can do it like this:
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: "#ff0000"
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderColor: "#ff0000"
}
}
}
}
}
});
Working example
$notchedOutline doesn't work for me.

How to customize MUI V5 TextField

I am trying to customise my theme for material v5 and I would like to know how I can disable the black border that appears when I hover over the textfield component. This is what I have so far under my custom theme
MuiTextField: {
styleOverrides: {
root: {},
},
defaultProps: {
inputProps: {
style: {
fontSize: '11.8px',
// height: '.85rem',
},
},
},
},
Checkout the documentation at: https://mui.com/material-ui/react-text-field/#customization
import * as React from 'react';
import { alpha, styled } from '#mui/material/styles';
import TextField from '#mui/material/TextField';
const CssTextField = styled(TextField)({
'& label.Mui-focused': {
color: 'green',
},
'& .MuiInput-underline:after': {
borderBottomColor: 'green',
},
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: 'red',
},
'&:hover fieldset': {
borderColor: 'yellow',
},
'&.Mui-focused fieldset': {
borderColor: 'green',
},
},
});
export default function CustomizedInputs() {
return (
<CssTextField label="Custom CSS" id="custom-css-outlined-input" />
);
}
Change your styleOverrides like this:
MuiTextField: {
styleOverrides: {
root: {
"& .MuiOutlinedInput-root": {
"&:hover fieldset": {
borderColor: "rgba(0, 0, 0, 0.23)",
},
"&.Mui-focused fieldset": {
borderColor: "rgba(0, 0, 0, 0.23)",
},
},
},
},
defaultProps: {
inputProps: {
style: {
fontSize: "11.8px",
// height: '.85rem',
},
},
},
},

How to extends classes in material UI createStyles

import { createStyles, Theme } from '#material-ui/core/styles';
export default (theme: Theme) => {
const { primary } = theme.palette;
return createStyles({
test1: {
fontSize: '30px',
},
test2: {
'& > div': {
color: primary.main,
marginTop: '20px',
},
},
});
};
Here I want to use class test1 in test2. How should I extend it?
You can use the dollar sign to reference the other selector when using JSS:
test1: {
width: 50,
height: 50,
backgroundColor: "pink",
"& $test2": {
backgroundColor: "red"
}
},
test2: {
width: 30,
height: 30
}
Reference
https://cssinjs.org/jss-plugin-nested?v=v10.8.1#use-rulename-to-reference-a-local-rule-within-the-same-style-sheet

React testing library fireEvent not firing / found answer

I have an issue with using react testing library and its fireEvent function.
I want to test my component and its style after hovering.
Here it is my component written in tsx:
import React from 'react'
import { makeStyles } from '#material-ui/core'
import Paper, { PaperProps } from '#material-ui/core/Paper'
import Box from '#material-ui/core/Box'
import posed from 'react-pose'
import grey from '#material-ui/core/colors/grey'
import green from '#material-ui/core/colors/green'
import lightBlue from '#material-ui/core/colors/lightBlue'
import teal from '#material-ui/core/colors/teal'
function styleProducer(variant: BigTileProps['variant'] = 'default', color: BigTileProps['color'] = 'default'): Function {
type colrMapType = {
[k: string]: { tile: { [pr: string]: string } }
}
const colorMap: colrMapType = {
default: { tile: {} },
grey: {
tile: { background: grey[700], color: 'white' }
},
green: {
tile: { background: green[300] }
},
teal: {
tile: { background: teal[400], color: 'white' }
},
blue: {
tile: { background: lightBlue[200] }
},
}
interface variantsKeys {
small: (theme: any) => object
default: (theme: any) => object
big: (theme: any) => object
large: (theme: any) => object
}
type variantsType = {
[k in keyof variantsKeys]: variantsKeys[k]
}
const variants: variantsType = {
small: (theme: any) => ({
tile: Object.assign({
minWidth: theme.spacing(10),
height: theme.spacing(10),
background: grey[500],
position: 'relative',
'&:hover': {
cursor: 'pointer'
}
}, colorMap[color].tile),
content: {
fontSize: '2rem',
fontWeight: 'bold'
},
title: {
textTransform: 'uppercase'
},
icon: {
position: 'absolute',
top: 0,
left: 0
}
}),
default: (theme: any) => ({
tile: Object.assign({
minWidth: theme.spacing(15),
height: theme.spacing(15),
position: 'relative',
'&:hover': {
cursor: 'pointer'
}
}, colorMap[color].tile),
content: {
fontSize: '2rem',
fontWeight: 'bold'
},
title: {
textTransform: 'uppercase'
},
icon: {
position: 'absolute',
top: 0,
left: 0
}
}),
big: (theme: any) => ({
tile: Object.assign({
minWidth: theme.spacing(20),
height: theme.spacing(20),
position: 'relative',
'&:hover': {
cursor: 'pointer'
}
}, colorMap[color].tile),
content: {
fontSize: '2rem',
fontWeight: 'bold'
},
title: {
textTransform: 'uppercase'
},
icon: {
position: 'absolute',
top: 0,
left: 0
}
}),
large: (theme: any) => ({
tile: Object.assign({
minWidth: theme.spacing(25),
height: theme.spacing(25),
position: 'relative',
'&:hover': {
cursor: 'pointer'
}
}, colorMap[color].tile),
content: {
fontSize: '2rem',
fontWeight: 'bold'
},
title: {
textTransform: 'uppercase'
},
icon: {
position: 'absolute',
top: 0,
left: 0
}
})
}
return makeStyles(variants[variant])
}
type BigTileProps = {
color?: 'default' | 'grey' | 'green' | 'blue' | 'teal',
variant?: 'small' | 'default' | 'big' | 'large',
width?: string, // 15px , 10rem etc
height?: string, // 15px , 10rem etc
title?: string,
content?: string
icon?: React.FC | React.ReactElement
}
const PosedPaper = posed(Paper)({
onHover: {
scale: 1.05
},
none: {
scale: 1
}
})
const BigTile: React.FC<BigTileProps> = ({
variant = 'default',
color = 'default',
width,
height,
children,
title,
content,
icon,
...props
}) => {
const [hover, setHover] = React.useState(false)
const useStyles = styleProducer(variant, color)
const classes = useStyles()
const onHoverHandle = (bool: boolean) => () => {
setHover(bool)
}
const style = {height, width}
if (!height) delete style['height']
if (!width) delete style['width']
return (
<PosedPaper className={classes.tile} style={{ height, width }} pose={hover ? 'onHover' : 'none'} onMouseEnter={onHoverHandle(true)} onMouseLeave={onHoverHandle(false)}>
<Box className={classes.icon} p={1}>
{icon}
</Box>
<Box height="100%" width="100%" display="flex" justifyContent="center" alignItems="center" flexDirection="column">
<Box mb={1} className={classes.content}>{children ? children : content}</Box>
<div className={classes.title}>{title}</div>
</Box>
</PosedPaper>
)
}
export default BigTile
And here is my test :
it('BigTile hover check', ()=>{
const { container } = render(<BigTile />)
const elem = container.querySelector<HTMLElement>('.MuiPaper-root')
if (!elem) fail("Element is null.")
fireEvent.mouseOver(elem);
const elemAfterHover = container.querySelector<HTMLElement>('.MuiPaper-root')
if (!elemAfterHover) fail("Element after hover is null.")
console.log(elemAfterHover.style)
})
Here i cant see changed style after mouseover event. Console log shows me only transform:none
when it should be something like transform: scale(1.05).
Please help me with firing this event properly and if you have some advise to the code itself it would be great to take some advices.
//Answer
The event was firing every time i started the test.
To check it i just put some console.log(..) inside onHoverHandle which is firing after moseenter/leave.
Of course i didn't need to find element once again after fireEvent, becouse i had this element before. Main idea is that i needed to wait for event to end before checking for style change. So waitFor is good for that.
I read somewhere than using userEvent from '#testing-library/user-event' is better than fireEvent , so i did.
Final solution :
it('BigTile hover check.', async ()=>{
const { container } = render(<BigTile />)
const elem = container.firstChild as HTMLElement
if (!elem) fail("Element is null.")
userEvent.hover(elem);
await waitFor(() => {
expect(elem.style.transform).toEqual("scale(1.05) translateZ(0)")
})
})

Resources