Change default hover color of TableRow MUI - reactjs

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.

Related

Custom styled MUI IconButton does not work with tooltop

I have styled IconButton so it looks like I need the problem I have right now is that when I use ToolTip it does not appear near to my button but instead in top left corner of the page.
What I do wrong?
import { styled } from '#mui/material/styles';
import IconButton from '#mui/material/IconButton';
import { motion } from "framer-motion"
export const Colors = ['#58b864', '#91d704', '#9ad436', '#fd9828', '#ff7826', '#fc4a41', '#e01f1f', '#4065ac', '#4065ac', '#4065ac', '#4065ac'];
const Button = (props, Component) => {
const { color, greyed, children, className, icon, ...other } = props;
const StyledButton = styled(IconButton)(({ theme }) => ({
borderRadius: '18%',
height: '26px',
width: '26px',
fontSize: '15px',
backgroundColor: greyed ? '#293357' : color,
color: greyed ? (theme.palette.mode === 'dark' ? '#63697d' : '#bebebe') : '#fff' , //? : theme.palette.grey[50]
'& svg': {
fontSize: '16px'
},
'&:hover': {
color: '#fff',
backgroundColor: color,
filter: icon ? 'none' : 'brightness(1.2)',
cursor: icon ? 'default' : 'pointer'
},
'&.Mui-disabled': {
backgroundColor: '#293357',
color: '#666979'
}
}));
return (
<StyledButton
{...other}
component={icon ? null : motion.div}
whileHover={{
scale: 1.1,
transition: { duration: 0.3 }
}}
whileTap={{ scale: 0.9 }}
>
{children}
</StyledButton>
)
}
export default Button;
Update:
I have found out that this work with tooltip:
const properties = ['color', 'greyed', 'icon']
const Button = styled(IconButton, { shouldForwardProp: (prop) => !properties.includes(prop)})
(({ theme, color, greyed, icon }) => ({
borderRadius: '18%',
height: '26px',
width: '26px',
fontSize: '15px',
backgroundColor: greyed ? '#293357' : color,
color: greyed ? (theme.palette.mode === 'dark' ? '#63697d' : '#bebebe') : '#fff' ,
'& svg': {
fontSize: '16px'
},
'&:hover': {
color: '#fff',
backgroundColor: color,
filter: icon ? 'none' : 'brightness(1.2)',
cursor: icon ? 'default' : 'pointer'
},
'&.Mui-disabled': {
backgroundColor: '#293357',
color: '#666979'
}
}));
But then I don't understand how to globally apply animations from motion framer. Please help, what do I miss?
I add position:"relative" try it.
const StyledButton = styled(IconButton)(({ theme }) => ({
position:"relative",
borderRadius: '18%',
height: '26px',
width: '26px',
fontSize: '15px',
backgroundColor: greyed ? '#293357' : color,
color: greyed ? (theme.palette.mode === 'dark' ? '#63697d' : '#bebebe') : '#fff' , //? : theme.palette.grey[50]
'& svg': {
fontSize: '16px'
},
'&:hover': {
color: '#fff',
backgroundColor: color,
filter: icon ? 'none' : 'brightness(1.2)',
cursor: icon ? 'default' : 'pointer'
},
'&.Mui-disabled': {
backgroundColor: '#293357',
color: '#666979'
}
}));

How to separate MUI setup to an external js file?

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.

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);

How to update material-ui button focus style?

material-ui introduces a way of using classname for styling component. I have a button component shown as below. It uses createStyles and withStyles to inject the styles as classes into the component. But I don't know how to set the focus style of the Button.
import Button from '#material-ui/core/Button';
const styles = createStyles({
button: {
minHeight: '3rem',
lineHeight: '3rem',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-around',
fontSize: '0.8rem',
fontFamily: 'Roboto',
color: '#008091',
border: '2px solid #008091',
borderRadius: '0.375rem',
marginRight: '1rem',
marginTop: '2rem',
marginBottom: '2rem',
minWidth: '180px',
textAlign: 'center',
fontWeight: 700,
margin: '1rem 0',
padding: 0
},
selected: {
backgroundColor: '#008091',
color: 'white'
}
});
interface Props {
classes: { [className in keyof typeof styles]: string };
style?: React.CSSProperties;
text: string;
selected?: boolean;
onClick: (event: React.MouseEvent<HTMLElement>) => void;
}
const TextButton = ({ classes, style, text, onClick, selected }: Props) => {
return (
<Button
className={selected ? classNames(classes.button, classes.selected) : classes.button}
style={style}
onClick={onClick}
>
{text}
</Button>
);
};
Psuedo selectors can be added by:
const styles = createStyles({
button: {
// main styles,
"&:focus": {
color: "red"
}
}
});
This should do the trick
overrides: {
MuiButton: {
root: {
'&:focus': {
color: 'rgba(0, 0, 0, 0.87)',
backgroundColor: 'rgba(0, 0, 0, 0.87)',
},
},
},
},

Material-ui Override StepLabel nested property

I want to override the marginTop: 16 property that occurs in this implementation of StepLabel:
label: {
color: theme.palette.text.secondary,
'&$active': {
color: theme.palette.text.primary,
fontWeight: 500,
},
'&$completed': {
color: theme.palette.text.primary,
fontWeight: 500,
},
'&$alternativeLabel': {
textAlign: 'center',
marginTop: 16,
},
'&$error': {
color: theme.palette.error.main,
},
},
So that I get this as the desired outcome:
But I cannot for the life of me figure out how.... here's my implementation:
<StepLabel
classes={{
root: classes.root,
labelContainer: classes.labelContainer,
label: classes.myLabel
}}
>
{this.state.labels[label - 1]}
</StepLabel>
Here's the classes:
const styles = theme => ({
root: {
marginTop: 0,
padding: 0,
"& $alternativeLabel": {
marginTop: 0
}
},
labelContainer: {
backgroundColor: "green",
marginTop: 0,
"& $alternativeLabel": {
marginTop: 0
}
},
myLabel: {
backgroundColor: "red",
marginTop: 0,
"& $alternativeLabel": {
marginTop: 0
}
},
});
The result - the marginTop DOES NOT get overridden. :(
Further information - the property that I want to override:
seems like the way to do it is like this - credit to this answer Material-UI Style Override?
Put an empty alternativeLabel: {} in, so that the property &$alternativeLabel is overridden:
const styles = theme => ({
labelContainer: {
"& $alternativeLabel": {
marginTop: 0
}
},
alternativeLabel: {},
});
and then call it like this in your component:
<StepLabel
classes={{
alternativeLabel: classes.alternativeLabel,
labelContainer: classes.labelContainer
}}
>

Resources