Trying to style an item with a specific custom class with material UI - reactjs

I am trying to manage a music playlist with a material ui table. And I would like to change the appearance of the item I am currently playing. At first I was juste setting it as "selected" but now, I have custom theme, and I don't know what I should overwrite to have the "selected" appearances coherent with the theme of my playlist. So, instead, I would prefer to add a class to my row "playing", and then, style my item differently regarding the class it has.
I did not find anything working to do so. When I tried to add my custom class into my theme, I got this error :
mergeClasses.js:25 Material-UI: The key `&.playing` provided to the classes prop is not implemented in ForwardRef(TableCell).
You can only override one of the following: root,head,body,footer,sizeSmall,paddingCheckbox,paddingNone,alignLeft,alignCenter,alignRight,alignJustify,stickyHeader.
So, I guess what I was trying to do must not be done like I tried to. I tried this :
const StyledTableCell = withStyles((theme) => ({
root: {
borderColor: theme.root.borderColor,
},
head: {
backgroundColor: theme.palette.background.default,
color: theme.palette.common.white,
},
body: {
fontSize: 14,
},
"&.playing": { backgroundColor: "rgba(0, 0, 0, 0.16)" },
}))(TableCell);
How can I add specific rendering rules to a custom classe in material ui ?

&.playing should be inside of root to be applied to the root element.
const StyledTableCell = withStyles((theme) => ({
root: {
'&.playing': {
backgroundColor: '#ccc',
}
},
}))(TableCell);

Related

Using theme palette colors in custom MUI component variants with light/dark mode

For readability reasons, I want to split the components object passed in the createTheme function (components may have large variants) and I do have light/dark mode.
According to docs, this is how we get the design tokens:
const getDesignTokens = (mode: PaletteMode) => ({
palette: {
mode,
...(mode === 'light'
? {
// palette values for light mode
primary: amber,
divider: amber[200],
text: {
primary: grey[900],
secondary: grey[800],
},
}
: {
// palette values for dark mode
primary: deepOrange,
divider: deepOrange[700],
background: {
default: deepOrange[900],
paper: deepOrange[900],
},
text: {
primary: '#fff',
secondary: grey[500],
},
}),
},
});
After that, I create the theme depending on whether the mode is light or dark.
The problem is when I'm trying to add a component to the theme (as stated before, each component will be only referenced in the createTheme, the definition would be somewhere else) I cannot use colors from the theme without wrapping the component is a function which has the parameter the mode used.
I wonder if there is any solution like with the sx prop when you're referencing the color as a string, let's say sx={{ backgroundColor: 'button.background' }} and that would automatically be used from the theme.
Wrapping each component in a function with a parameter does the job, but I would like to know if there is any better solution.
How the code is now:
const dashedVariants = (palette) => ({
props: {variant: 'dashed'},
style: {
border: `1px dashed ${palette.dashColor}`
}
})
const Button = (palette) => ({
styleOverrides: {},
variants: [dashedVariants(palette)]
})
vs what I'm trying to acheive:
const dashedVariants = {
props: {variant: 'dashed'},
style: {
border: `1px dashed palette.dashColor` //something like that??
}
}
Note: I've looked over this existing question, but unfortunately this does seem to help.
Due to complexity of CSS properties, many UI toolkit and its themes only parse singular properties(or provide a detour utility); MUI's one of them. Use separate border properties to make parser working. Palette color property parser only works for the type of React.CSSProperties['color'] property. .border property is Property.Border type. The color parser won't work in this case.
Palette type only works with appropriate properties. it does not provide dashColor property. according to MUI doc, working properties are:
.palette.primary.light
.palette.primary.main
.palette.primary.dark
.palette.primary.contrastText
// ...
.palette.secondary
.palette.error
.palette.warning
.palette.info
.palette.success
const theme = {
palette: {
secondary: {
main: '#...' // user defiend color
}
}
}
const dashedVariants = {
props: {variant: 'dashed'},
style: {
borderColor: 'secondary.main',
borderWidth: '1px',
borderStyle: 'dashed',
}
}
There's an experimental CSS variable feature. With this, it is possible to define CSS variable inside complex property. This is probably the closest to the goal but it's currently experimental stage, might be unstable for production use. I am also looking forward to using this in the future.

Target CSS child selector created by in material ui

I have styles like this:
const useStyles = makeStyles(theme => ({
root: {
margin: 5
},
container: {
backgroundColor: 'red'
},
active: {
// here I want to target the 'container' className I created above like
'& .container': {
backgroundColor: 'green'
}
}
});
I want to target the container className I created inside of the active className. The above won't work because in the DOM, MUI will generate a unique name so I won't be targeting the right class. Wasn't able to find any SO answer or blog or documentation addressing this.
$ rulename is used for this purpose. Here is the documentation of it on Material-UI.
CSS in JS documentation also explains this feature.
container: {
//other styles
},
active: {
"& $container": {
background: "green",
color: "#fff"
}
}
Here one thing which is important that for referencing 'containerrule, it should be defined in the rules object. trying to use"& $containerwithout defining thecontainerrule inside themakeStyles` will not work.
Here is the working demo:
You can refer using $
You will have to modify your DOM little bit such that the active className is not the parent of container. Instead add the active className to the conatiner element itself.
so your css style might look like below
const useStyles = makeStyles(theme => ({
root: {
margin: 5
},
container: {
backgroundColor: 'red',
'&$active': {
backgroundColor: 'green'
}
},
});
I think this is what you are looking for $rulename
How to Use $ruleName to reference a local rule within the same style sheet
In your case i think the solution would be
const useStyles = makeStyles(theme => ({
root: {
margin: 5
},
container: {
backgroundColor: 'red'
},
active: {
.container: {
backgroundColor: 'green'
}
}
});
Which should compile to
.root.container.active{}
and on the target tag taking a example of button here
<Button
classes={{
root: classes.root,
container: classes.container,
active: classes.active,
}}>
Havent worked with MUI yet but even in vue or react the way this is achived is by setting a dynamic name on the tag that is targeted via script.

pass material ui styles to component - react

I am using a functional component with React, I need to show SVG Icon based on state and I want to load the relevant icon
so the parent will show only call :
<icon classes:... , state..></icon>
1- how can I pass style and if it does not exist and use a default style in the child?
now I have smth like in the parent :
... createStyle
IconSuccess: {
fontSize: 20,
width: 20,
},
IconWarning: {
fontSize: 20,
width: 20,
},
but i want smth like :
icon:{
width:..
font ..
warning: { color}
success: { color}
}
then
<IconChild state={state} classes={{ icon: itemStyle.icon}} />
this is work only if I pass specific style like:
<IconChild state={state} classes={{ iconWarning: itemStyle.iconWarning}} />
then in the childCOmponent I am doing smth like:
const classes = useStyles(props);
if( props.state == 1){
return <className={`${classes.iconWarning}`} />
}
else{
return <className={`${classes.iconSuccess}`} />
}
so basically I am trying to understand how to create a really generic component that I can use and pass and that need a state to choose the specific icon and also from specific class
do I need HOC ? or different approach
As I understand, you want to:
Reuse some common properties like width and fontSize.
Custom render other properties like color.
Then this is my approach:
First, make new style for commonly used properties.
Secondly, create new styles for conditional use of each state.
Last, use something like classnames to combine all classes.
So the main idea here is: instead of using one class for each item, now using two classes for each one. That's it!
const useStyles = withStyles({
commonProperty: {
fontSize: '20px',
width: '20px',
},
successOnlyProperty: {
color: 'green'
},
warningOnlyProperty: {
color: 'orange'
},
});

Apply radiobutton color using styled-components in Material UI?

In the Material UI documents, they provided sample code to show how one can change the color of a Radiobutton.
const GreenRadio = withStyles({
root: {
color: green[400],
'&$checked': {
color: green[600],
},
},
checked: {},
})(props => <Radio color="default" {...props} />);
I would like to replicate this with styled-component instead i.e. const StyledRadio = styled(Radio) but I am not too familiar with the syntax such as the ampersand and the dollar sign - how can I do this?
When using styled components with MUI, the CSS is applied to the root class of the component. If you need to apply a more specific style, then you'll need to target the relevant class. In this case, you'll need to target the .Mui-checked class:
const StyledRadio = styled(Radio)`
color: ${green[400]};
&.Mui-checked {
color: ${green[600]};
}
`;
The MUI docs are really good in that they list the CSS classnames for each component. If you visit the API docs for the Radio component, you'll see the .Mui-checked class listed there (under the 'Global Styles' column).
Here's a working example in Code Sandbox: https://codesandbox.io/embed/styled-components-9pewl
Here's the appropriate styled-components syntax:
const GreenRadio = styled(Radio)`
color: ${green[400]};
&.Mui-checked {
color: ${green[600]};
}
`;
Related documentation: https://material-ui.com/customization/components/#pseudo-classes

How can I customize material-ui V1 components across entire application when creating a theme?

in material-ui v0, when creating a theme with const muiThemeV0 = getMuiTheme(theme);
i can simply add a property to the themeOptions for each component based on this file:
https://github.com/mui-org/material-ui/blob/master/src/styles/getMuiTheme.js (currently on the master branch when writing this question), and can customize not only colors but the theme border-radius etc, and specific components sizes and colors.
for example:
const theme = {
slider: {
selectionColor: colors.primary1Color,
handleFillColor: colors.primary1Color,
trackSize: 6,
}
}
I tried going through the https://material-ui-next.com/customization/overrides/ docs, but can't see examples and/or a list of options in the source code like MUI-v0 when i want to use const muiThemeV1 = createMuiTheme(theme);
are there any docs for this kind of customization in v1?
is this even possible?
In v1, you can use the theme overrides property to customize the styles of a specific component type. Instead of providing theme options for individual components, this feature allows you to customize every style that material-ui injects into the DOM.
You can find a list of the CSS classes for each component on the website (in component API section).
The following example customizes the appearance of the Button component
const theme = createMuiTheme({
overrides: {
MuiButton: {
// override root styles for the button component.
root: {
// Name of the rule
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
borderRadius: 3,
color: 'white',
height: 48,
padding: '0 30px',
marginRight: 32,
},
// Custom styles for the raised button variant
raised: {
borderRadius: 50,
color: 'white',
// Custom hover styles for raised button
'&:hover': {
boxShadow: shadows[4],
},
// Custom active styles for raised button
'&:active': {
boxShadow: `${shadows[24]} !important`,
},
},
},
}
});
Live example on code sandbox
Documentation on theme overrides

Resources