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'
}
}));
Related
So I want to migrate from styled-components to MUI v5xxx, I have some styling work on styled-components but after I convert the code to the MUI some of them don't work properly, for example, I have a container supposed to be hovering an infostyle but nothing happen
Hover Script
const StyledInfo = styled("div")(({ theme }) => ({
opacity: 0,
width: "100%",
height: "100%",
position: "absolute",
backgroundColor: "rgba(0, 0, 0, 0.1)",
top: 0,
left: 0,
zIndex: 3,
display: "flex",
alignItems: "center",
justifyContent: "center",
transition: "all 0.5s ease",
}));
const StyledContainer = styled("div")(({ theme }) => ({
flex: 1,
minWidth: "320px",
height: "400px",
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#F7BB62",
backgroundImage: `url("https://www.transparenttextures.com/patterns/crissxcross.png")`,
color: "#ffffff",
position: "relative",
cursor: "pointer",
"&:hover ${StyledInfo}": {
opacity: 1,
},
}));
as you can see on this "&:hover ${StyledInfo}": {....} doesn't work
Another example, when adding props
const Arrow= styled("img")(({ theme,props }) => ({
left: ${(props) => props.direction === "left" && "10px"},
right: ${(props) => props.direction === "right" && "10px"},
}));
on this case ${(props) => props.direction === "left" && "10px"} doesn't work
What I've tried
Using backtick
I have no clue how to fix this
Are you using emotion? If you are using emotion (highly recommended over styled-components), you can simply use import { styled } from '#mui/material/styles, and it works identically.
If you use emotion, you need to follow https://mui.com/system/styled/#how-to-use-components-selector-api to add the babel plugin, in order to use Child selector
babel config
module.exports = {
...
plugins: [
[
"#emotion",
{
importMap: {
"#mui/system": {
styled: {
canonicalImport: ["#emotion/styled", "default"],
styledBaseImport: ["#mui/system", "styled"]
}
},
"#mui/material/styles": {
styled: {
canonicalImport: ["#emotion/styled", "default"],
styledBaseImport: ["#mui/material/styles", "styled"]
}
}
}
}
]
]
};
With regards to the following code
const Arrow= styled("img")(({ theme,props }) => ({
left: ${(props) => props.direction === "left" && "10px"},
right: ${(props) => props.direction === "right" && "10px"},
}));
Your condition is actually invalid. e.g. if your props.direction, your left property becomes false which is not a valid value.
Probably a better way to write this component would be
const Arrow= styled("img", { shouldForwardProp: (prop) => !['left', 'right'].includes(prop))(({ theme,direction }) => ({
left: ${direction === 'left' ? '10px' : 'auto'},
right: ${direction === 'right' ? '10px' : 'auto'},
}));
Update:
in this code block, you are using " instead of `, which means StyledInfo is being read as plain text.
"&:hover ${StyledInfo}": {
opacity: 1,
},
Try changing to
`&:hover ${StyledInfo}`: {
opacity: 1,
},
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.
How to pass props to the already styled mui menu , I want to be able to use conditional styling on the menu so it could have 2 types of minimum width.. depending on each case problem for me is the menu has they style out side of the component that is getting the props that I want to check against its type, so how can it be able to achieve this ?
const StyledMenu = styled((props: MenuProps) => (
<Menu
elevation={0}
anchorOrigin={{
vertical: 'bottom',
horizontal: 200,
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
{...props}
/>
))(({ theme }) => ({
backgroundColor: 'rgba(255, 255, 455, 0.455)',
backdropFilter: 'blur(1px)',
'& .MuiPaper-root': {
borderRadius: 3,
//{props === 'Type' ? { minWidth: 1360 } : { minWidth: 250 }},
{props === 'Type' ? { minWidth: 1360 } : { minWidth: 250 }}
marginTop: theme.spacing(1),
color: theme.palette.mode === 'light' ? 'rgb(55, 65, 81)' : theme.palette.grey[300],
boxShadow: 'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px',
'& .MuiMenu-list': {
padding: '4px 0',
},
'& .MuiMenuItem-root': {
'& .MuiSvgIcon-root': {
fontSize: 18,
color: theme.palette.text.secondary,
marginRight: theme.spacing(1.5),
},
'&:active': {
backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
},
},
},
}));
export const Expandable: React.FC<Props> = ({ source, type, date, icon }) => {
const context = useContext(movementsContext);
//useEffect(() => {}, [context.StabelItems]);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<Box style={{ margin: 'auto', display: 'flex', justifyContent: 'center' }}>
<StyledMenu
id='demo-customized-menu'
MenuListProps={{
'aria-labelledby': 'demo-customized-button',
}}
anchorEl={anchorEl}
open={open}
onClose={handleClose}
>
</Box>
</Box>
);
};
I've recently developed two different ways of conditional styling using MUI's withStyle & makeStyle
Approach #1
Make two different class styles and conditionally apply them to your element
const useStyles = React.makeStyles(theme => ({
blueStyle: {
color: 'blue'
},
redStyle: {
color: 'red'
},
}));
export default const YourComponent = () => {
const classes = useStyles();
const [condition, setCondition] = React.useState(true);
return <div className={condition ? classes.blueStyle : classes.redStyle}>Hello World!</div>
}
Approach #2
You can conditionally style a table cell (or any element of your choosing) based on screen size
const StyledDiv = withStyles((theme) => ({
root: {
color: 'blue', // default style of color is blue
[theme.breakpoints.up('sm')]: { // you can use sx, sm, md, lg or xl for different screen conditions
color: 'red', // style of color is red if screen size is sm or sx
// other styles can go here
},
}
}))(div);
export default const YourComponent = () => {
return <StyledDiv >Hello World!</StyledDiv>
}
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);
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)',
},
},
},
},