i am using fluent ui which uses Griffel for styling. When i try to provide border: "none" it's throwing error that string not assignable to undefined
import {makeStyles} from "#fluentui/react-components";
export const settingsButtonStyle = makeStyles({
root: {
border: "none",
background: "#E5E5E5",
marginRight: "13px"
},
rootHovered: {
background: "#E5E5E5",
}
});
GriffelJS tries to make Atomic CSS classes, so they don't support CSS shorthands (like border or background) right away. But there is a helper function called shorthands to manage some of theses. Background is not included in the helper function, so there you should use the specific CSS proprety. So your code should look like this:
const useStyles = makeStyles({
root: {
...shorthands.border("0"),
// or
...shorthands.borderStyle("none"),
backgroundColor: "#E5E5E5",
marginRight: "13px"
},
})
You find more infos to shorthands in GriffelJS in their documentation shorthands - GriffelJS
I would like to create a circle as a custom component in Backendless. Here's my code in bundle.js
define(() => {
return function CustomComponent() {
return React.createElement('div',{
className:'test',
height: '125px',
width: '125px',
style:{
background: '#bbb',
display: 'inline-block',
border-radius: '50%',
}
})
}
});
But it doesn't work and I'm getting: Can not render page due to error: "Cannot read properties of undefined (reading 'default')"
The code below is from MUI 5, with a MUI 4 solution for change input field when hovering. But it obviously doesn't work, wonder how to achieve this in MUI 5, can't
seem to change the color from the TextField upon hovering. This is done using createTheme in MUI 5
components: {
MuiInputLabel: {
styleOverrides: {
root: {
color: arcBlue,
fontSize: '1rem',
},
},
},
MuiInput: {
styleOverrides: {
underline: {
'&:before': {
borderBottom: `2px solid ${arcBlue}`,
},
// Code from material ui 4
'&:hover:not($disabled):not($focused):not($error):before': {
borderBottom: `2px solid ${arcGrey}`,
},
},
},
},
},
The $ syntax is a feature from JSS, in MUI v5, they switch to emotion so it doesn't work anymore, you have 2 options now:
Use plain string
From this section, you can see a list of class names that describe different MUI component states:
State
Global class name
active
.Mui-active
checked
.Mui-checked
completed
.Mui-completed
disabled
.Mui-disabled
error
.Mui-error
expanded
.Mui-expanded
focus visible
.Mui-focusVisible
focused
.Mui-focused
required
.Mui-required
selected
.Mui-selected
'&&:hover:not(.Mui-disabled):not(.Mui-error):before': {
borderBottom: `5px solid purple`
}
Use constant
Most MUI components have their own class constants if you don't want to hardcode the class name:
import { [component]Classes } from "#mui/material/[Component]";
import { inputClasses } from "#mui/material/Input";
[`&&:hover:not(${inputClasses.disabled}):not(${inputClasses.focused}):before`]: {
borderBottom: `5px solid purple`
}
Reference
https://mui.com/guides/migration-v4/#migrate-themes-styleoverrides-to-emotion
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.
i don't know what difference in this code.
class a is component and example is example.js
import React, {Component} from 'react';
const styles = {
border: {
display: 'inline-block',
height: '19px',
padding: '1px 8px 0',
border: '2px solid',
borderRadius: '12px',
lineHeight: '20px',
fontSize: '14px',
verticalAlign: 'top',
},
default: {
display: 'inline-block',
height: '20px',
padding: '1px 10px 0',
borderRadius: '10px',
lineHeight: '21px',
fontSize: '13px',
verticalAlign: 'top',
},
state: {
display: 'inline-block',
width: '14px',
height: '13px',
paddingTop: '1px',
lineHeight: '14px',
fontSize: '11px',
color: '#fff',
letterSpacing: '-0.5px',
textAlign: 'center',
verticalAlign: 'top',
}
};
class A extends Component {
static defaultProps = {
type: 'default',
};
render() {
const {
label,
style,
type,
...other
} = this.props;
switch (type) {
case 'border':
elementStyle = styles.border;
break;
case 'default':
elementStyle = styles.default;
break;
case 'state':
elementStyle = styles.state;
break;
}
return (
<span style={Object.assign(elementStyle, style)} {...other}>{label}</span>
);
}
}
export default A;
and example code is example.js
import A from './A';
export default class Example extends React.Component {
render() {
return (
<div>
<A style={{background: '#fe6969', color: '#fff'}} />
<A style={{background: '#ff8137', color: '#fff'}} />
<A style={{background: '#fcb400', color: '#fff'}} />
</div>
);
}
}
this code error is Uncaught TypeError: Cannot assign to read only property 'background' of object '#'
i use babel-loader 8, babel7 ,webpack4
if i correct Object.assgin({}, elementStyle, style) is working.
i think this error occur when rerendering A component.
i don't know why this error...
please help me.
All you need to do is concat/merge two objects like this using spread
{{...elementStyle, ...style}} or
{Object.assign({}, elementStyle , style) }
You should understand the nature of how Object.assign works. It returns the target object as the return value of its operation.
So, in the first syntax:
Object.assign({}, elementStyle , style)
you are creating a brand new object with the enumerable properties of elementStyle and style.
If you do this:
Object.assign(elementStyle, style)
Then elementStyle itself is the target object, so that will be mutated and that will be what is returned from Object.assign.
Here is an example what I mean.
Example 1 :
// With no new target object
const original = [{id:1}, {id:2}, {id:3}];
const newArray = original.map(elem => {
return Object.assign(elem, {id:2});
});
console.log('Original object has changed');
console.log(original);
//------------------------------
// With a new target object
const original2 = [{id:1}, {id:2}, {id:3}];
const newArray2 = original2.map(elem => {
return Object.assign({}, elem, {id:2});
});
console.log('Original object has not changed');
console.log(original2);
Example 2 :
var styles = {
circle: {backgroundColor: 'yellow', height: '1005', width: '100%'},
circleA: {backgroundColor: 'blue'},
};
So we need all circle to have default cir some circle style, but we need to change some property,
// background yellow
<div style={styles.circle}></div>
// background blue
<div style={Object.assign(styles.circle, styles.circleA)}></div>
// expeted background yellow, but it's blue. cus styles.circle still have it's merged value
<div style={styles.circle}></div>
The solution is to pass an empty object to Object.assign(). By doing this, you're telling the method to produce a NEW object with the objects you pass it.
Example 3:
const obj1 = {
name: "J"
}
const obj2 = {
gander: "m"
}
// Here, obj1 is the same after the Object.assign call
console.log(Object.assign({}, obj1, obj2));
console.log(obj1)
console.log(obj2)
console.log("without empty obj passed")
// Note that after this call, obj1 holds both keys. So this will mutate it:
console.log(Object.assign(obj1, obj2));
console.log(obj1) // This is different now
console.log(obj2)
In your case,
`<A propstyle={{background: '#fe6969', color: '#fff'}} />
<A propstyle={{background: '#ff8137', color: '#fff'}} /> `
component A defined twice in Parent, which means that we will get two circles and child component will render twice.
and in Child component you defined like below:
<span style={Object.assign(elementStyle , style) }{...other}>{label}</span>
first render :
Object.assign overwrite properties from right to left props style to elementStyle,here elementStyle itself is the target object,that will be what is returned from Object.assign.
style props : { background: "#fe6969", color: "#fff" }
elementStyle : { background: "#fe6969", borderRadius: "10px", color: "#fff" }
Second render :
Object.assign tries to overwrite properties from right to left, but elementStyle have { background: "#fe6969", borderRadius: "10px", color: "#fff" }
and Object.assign is still in loop (remember example 1 .map())
style props : { background: "#ff8137", color: "#fff" }
error thrown: 'TypeError: Cannot assign to read only property 'background' of object ' when {Object.assign(elementStyle , style) } because there's no new target object.
please find the full code here
Hope it helps. read more
Instead of assigning values directly to the object, clone the object first instead of mutating an object that is immutable due to the fact that the object is a props object or because Object.defineproperties was used to set writable to "false", but just clone the object and assign the values to the cloned object and use the cloned object, but assign the values to the cloned object properly as well.
Instead of assigning and mutating directly like:
object.field = value
Do:
let clonedObject = {...object}
clonedObject = {...clonedObject, field: value}
Otherwise using object.defineproperties to set the writable property to "true" might also be another way that would work.
Object.defineProperty(object, 'field1', {
value: 1,
writable: true
});