How to style DraftJS editor in React - css

I am implementing a web ui with React and the Material UI library.
I need a custom styled DraftJS editor component but none of my tries worked.
Let's imagine I want to have a red color for my hole text block within my editor component.
The Editor Component got child <div class="DraftEditor-root"> which I want to style through my Editor component.
For that I tried the className:
const styles = () => ({
myEditorStyle: {
"& root": {
color: "red"
}
}
})
render() {
const { classes } = this.props;
return (
<Editor className={classes.myEditorStyle}/>
)
}
export default withStyles(styles)(MaterialTextEditor);
and classes:
const styles = {
myEditorStyle: {
color: "red"
}
}
render() {
const { classes } = this.props;
return (
<Editor classes={{ root={classes.myEditorStyle} }}
)
}
export default withStyles(styles)(MaterialTextEditor);
But that does not work. What am I doing wrong?

Related

useTheme hook within className not working

I have the following within my App.js file:
let theme = createTheme({
palette: {
bgCells: {
textAlign: 'right',
color: '#8ccadf',
backgroundColor: '#eef7ff'
}
}
});
I then have another component Report.js where I would like to access bgCells within a className via the useTheme hook, i.e.:
import React from 'react';
import { TableCell, TableRow, useTheme } from '#mui/material';
export default function Report(props) {
const { info } = props;
const theme = useTheme();
let myClass;
if (info.is_active) {
myClass = classes.someStyles;
} else {
myClass = theme.palette.bgCells;
}
return (
<TableRow className={myClass}>
<TableCell>
{
. . . .
Unfortuantely this is not working as myClass = theme.palette.bgCells is not being reference within my <TableRow className={myClass}>
Any ideas as to what I am missing?
palette in createTheme is not the right place for styling. You should put only colors there.
bgCells is an object, you can not add object as className. className must be string.
You can style the component with object via sx prop
<TableRow sx={{textAlign: 'right', ...}}> ... </TableRow>
Wrap your app with ThemeProvider from MaterialUI: https://mui.com/material-ui/customization/theming/#theme-provider

How to Overwrite CSS of an external [third-party] component using Material-UI-React?

I'm trying to overwrite the default CSS of an external component which isn't developed in Material-UI or my project. In styled-components, I can just take the root classes and replace them with my custom CSS. How do I do the same with Material-UI-React?
.ace-tm .ace_variable {
color : red
}
Suppose I've to replace those two classes with the new color property, how do I do it in Material styles?
This is what I've tried with no luck!
const Styles = {
" & ace-tm": {
"& ace_variable": {
color: red,
fontSize: "16px"
},
}
};
I'm using withStyles to later inject them in the components.
I just found this and thought I'd share the solution for posterity:
const GlobalCss = withStyles((theme) => ({
'#global': {
'.ace-tm .ace_variable': {
color: 'red',
},
},
}))(() => null)
const SomeComponent = () => {
return (
<>
<GlobalCss />
<h1>Hey Jude</h1>
<SomeComponentWhoseCSSWillBeModified />
</>
}
Read more on this here: https://material-ui.com/styles/advanced/#global-css

Changing styles during clicking

I have ReactJS project and I want to change colour of button during clicking. I know that it is a Ripple API but it's very incomprehensible to use it. Could someone advise me how can I do that?
I've tried to create two elements - parent and child - and changed background of child to transparent while clicking. Unfortunately I have also 'classes' object responsible for changing class if button is active and it is just not working.
My code below:
import React, { Component } from 'react';
import { withStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import PropTypes from 'prop-types';
import styles from './MydButton.style';
class MyButton extends Component {
constructor(props) {
super(props);
this.state = {
isClicked: false
};
}
handleClick = () => {
this.setState({ isClicked: !this.state.isClicked });
}
render() {
const {
classes,
children,
color,
disabled,
className,
onClick,
type,
border,
...props
} = this.props;
const myClass = this.state.isClicked ? 'auxClass' : 'buttonDefaultRoot';
return (
<div className={classes.parentRoot} >
<Button
classes={{
root: disabled
? classes.buttonDisabledRoot
: classes.buttonRoot,
label: disabled
? classes.buttonLabelDisabled
: classes.buttonLabel,
}}
{...props}
onClick={this.handleClick}
className={myClass}
disabled={disabled}
type={type === undefined ? 'button' : type}
>
{children}
</Button>
</div>
)
}
};
MyButton.propTypes = {
children: PropTypes.string.isRequired,
disabled: PropTypes.bool,
classes: PropTypes.object.isRequired,
};
MyButton.defaultProps = {
disabled: false,
};
export default withStyles(styles)(MyButton);
and styles:
const buttonRoot = {
border: 0,
height: 48,
width: '100%',
}
export default theme => ({
buttonDefaultRoot: {
...buttonRoot,
transition: 'all 1s ease-in-out',
backgroundImage: 'linear-gradient(to right, #F59C81, #E65DA2, #E65DA2, #B13A97, #881E8E)',
boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.16)',
backgroundSize: '300% 100%',
marginTop: 0,
'&:hover': {
backgroundPosition: '100% 0%',
transition: 'all 1s ease-in-out',
}
},
parentRoot: {
...buttonRoot,
backgroundColor: 'red',
backgroundSize: '300% 100%',
marginTop: 36,
},
auxClass: {
backgroundImage: 'none',
},
Material UI Core for ReactJS
The documentation is very good. I have updated my answer to accomodate the specific needs of this question. I have also included two general solutions for anyone who stumbles upon this question.
Tailored Solution:
Changes background color of button from classes.buttonDefaultRoot (a color defined by owner of question) to the gradient defined by the owner of this question.
First step, have a variable stored in state. You can call it whatever you want, but I'm calling bgButton. Set this to this.props.classes.buttonDefaultRoot like so:
state = {
bgButton: this.props.classes.buttonDefaultRoot,
}
Next, you want to define your function that will handle the click. Again, call it what you want. I will call it handleClick.
handleClick = () => {
const { classes } = this.props; //this grabs your css style theme
this.setState({ bgButton: classes.parentRoot.auxClass }); //accessing styles
};
A couple of things are happening here. First, I am destructuring props. So, I am creating a new const variable called classes that has the same value as this.props.classes. The classes contains a set of objects that defines your css styles for your buttons, margins, etc. You can access those styles just like you would if you were trying to get the value of a prop in an obj.
In this case you can access your button style by doing, classes.buttonDefaultRoot. That takes care of your handle click function.
Last step: render the button. In your render method you want to grab your bgButton from state like so:
render() {
const { bgButton } = this.state;
Then you want to assign your className of your button to bgButton and add the onClick functionality like this (this follows the Material UI Core documentation):
<Button variant="contained" color="primary" className={classNames(bgButton)} onClick={this.handleClick}>Button Name</Button>
Putting it all together you get this:
import React, { Component } from "react";
import Button from "#material-ui/core/Button";
import PropTypes from "prop-types";
import classNames from "classnames";
import { withStyles } from "#material-ui/core/styles";
export default theme => ({ ... }) //not going to copy all of this
class MyButton extends Component {
state = {
bgButton: null
};
handleClick = () => {
const { classes } = this.props;
this.setState({ bgButton: classes.parentRoot.auxClass });
};
render() {
const { bgButton } = this.state;
return (
<div className={classes.container}>
<Button
variant="contained"
color="primary"
className={classNames(bgButton)}
onClick={this.handleClick}
>
Custom CSS
</Button>
</div>
);
}
}
MyButton.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(MyButton);
General Solution
This solution is for those who want to use the predefined colors, i.e. default, primary, secondary, inherit. This implementation does not need the PropTypes or className imports. This will change the color from the predefined blue to the predefined pink. That's it.
state = {
bgButton: "primary",
}
handleClick = () => {
this.setState({ bgButton: "secondary" });
}
render() {
const { bgButton } = this.state;
return(
...
<Button
onClick = {this.handleClick}
variant = "contained" //checked Material UI documentation
color={bgButton}
> ..etc.
General Solution 2
To accommodate your custom styles to the button, you would have to import PropTypes and classNames and take a similar approach as the tailored solution above. The only difference here will be my syntax and class name. I am closely following the documentation here so you can easily follow along and readjust where necessary.
import React, { Component } from "react";
import Button from "#material-ui/core/Button";
import PropTypes from "prop-types";
import classNames from "classnames";
import { withStyles } from "#material-ui/core/styles";
import purple from "#material-ui/core/colors/purple";
const styles = theme => ({
container: {
display: "flex",
flexWrap: "wrap"
},
margin: {
margin: theme.spacing.unit
},
cssRoot: {
color: theme.palette.getContrastText(purple[500]),
backgroundColor: purple[500],
"&:hover": {
backgroundColor: purple[700]
}
},
bootstrapRoot: {
boxShadow: "none",
textTransform: "none",
fontSize: 16,
padding: "6px 12px",
border: "1px solid",
backgroundColor: "#007bff",
borderColor: "#007bff",
fontFamily: [
"-apple-system",
"BlinkMacSystemFont",
'"Segoe UI"',
"Roboto",
'"Helvetica Neue"',
"Arial",
"sans-serif",
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"'
].join(","),
"&:hover": {
backgroundColor: "#0069d9",
borderColor: "#0062cc"
},
"&:active": {
boxShadow: "none",
backgroundColor: "#0062cc",
borderColor: "#005cbf"
},
"&:focus": {
boxShadow: "0 0 0 0.2rem rgba(0,123,255,.5)"
}
}
});
class MyButton extends Component {
state = {
bgButton: null
};
handleClick = () => {
const { classes } = this.props;
this.setState({ bgButton: classes.cssRoot });
};
render() {
const { classes } = this.props; //this gives you access to all styles defined above, so in your className prop for your HTML tags you can put classes.container, classes.margin, classes.cssRoot, or classes.bootstrapRoot in this example.
const { bgButton } = this.state;
return (
<div className={classes.container}>
<Button
variant="contained"
color="primary"
className={classNames(bgButton)}
onClick={this.handleClick}
>
Custom CSS
</Button>
</div>
);
}
}
MyButton.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(MyButton);
A tip. You no longer need a constructor or to bind methods.
Hope this helps.

How do I access css/scss with react?

I have a react component where I am trying to change the background color of the css when clicking the div.
I know you can set the color in the component, but I am using this component many times, and don't to make multiple component files with just a different color, and even if I did, I am curious besides the fact.
How can I access (or even console.log to figure it out on my own) the css file and its properties through the component? Thanks ahead of time.
If you want to keep all background-color styles in your .css/.scss file, you will need to have a good className strategy to link the styles to your components. Here is my suggestion:
styles.scss
.blue {
background-color: blue;
&.clicked {
background-color: red;
}
}
Container.js
import React from 'react';
import ClickableDiv from './ClickableDiv.js';
const Container = () => (
<ClickableDiv className="blue">
<p>This is my text.</p>
</ClickableDiv>
);
export default Container;
ClickableDiv.js
import React, { Component } from 'react';
class ClickableDiv extends Component {
constructor() {
super();
this.state = { clicked: false };
this.handleDivClick = this.handleDivClick.bind(this);
}
handleDivClick() {
this.setState({ clicked: true });
}
render() {
const divClassName = [this.props.classname];
if (this.state.clicked) divClassName.push('clicked');
return (
<div className={divClassName.join(' ').trim()} onClick={this.handleDivClick}>
{this.props.children}
</div>
);
}
}
export default ClickableDiv;
Rendered Markup
Unclicked:
<div class="blue"><p>This is my text.</p></div>
Clicked:
<div class="blue clicked"><p>This is my text.</p></div>
You can pass in the desired background color as a prop, and use internal state with an onClick handler.
Container.js
import React from 'react';
import ClickableDiv from './ClickableDiv';
const Container = () => (
<ClickableDiv backgroundColor="#FF0000">
<p>This is my text.</p>
</ClickableDiv>
);
export default Container;
ClickableDiv.js
import React, { Component } from 'react';
class ClickableDiv extends Component {
constructor() {
super();
this.state = {};
this.handleDivClick = this.handleDivClick.bind(this);
}
handleDivClick() {
const { backgroundColor } = this.props;
if (backgroundColor) this.setState({ backgroundColor });
}
render() {
const { backgroundColor } = this.state;
return (
<div style={{ backgroundColor }} onClick={this.handleDivClick}>
{this.props.children}
</div>
);
}
}
export default ClickableDiv;
Better to make an external css file and write your css code in that file and just import that one in index.html

React Radium - How to change property values dynamically

I want to dynamically change, say, the background color of the button dynamically.
If this is my radium js styles file:
button-styles.js
export const styles = {
base: {
backgroundColor: 'red',
}
};
button.js
const myStyles = require('./styles/button-styles.js');
#Radium
class MyButton extends Component {
render() {
{/*
How do I tell the button to override the default value
for background color of red, to the props value if it exists,
(and in this scenario it does and is the color green)?
*/}
return (<Button style={ ??? }>Click Me</Button>)
}
}
MyButton.defaultProps = {
btnBg: 'green'
}
MyButton.propTypes = {
btnBg: PropTYpes.string
}
(A side note to the powers that be; there is no react-radium tag.)
You could create your styles as a function of your props.
Advantage: You do not need to have the fetching algorithm which just basically assigns your styles.
button-styles.js
export default props => ({
backgroundColor: props.btnBg
// if you need a default value you could use
// props.btnBg || 'green'
})
// You could even use ES6 object destruction
export default ({btnBg}) => ({
backgroundColor: btnBg
})
button.js
const myStyles = require('./styles/button-styles.js');
#Radium
class MyButton extends Component {
render() {
return <Button style={ myStyles(this.props) }>Click Me</Button>
}
}
MyButton.defaultProps = {
btnBg: 'green'
}
MyButton.propTypes = {
btnBg: PropTypes.string
}
Don't know if this is proper way to do it, but this worked for me.
Default properties in base remained, while only those with a matching
prop name in the dynamicStyle prop object were affected. So in this
example color and fontSize were not affected and remained with the
return settings, with only backgroundColor now being green..
UPDATE:
Per Janaka Stevens recommendation, I made the settings immutable. But I did so in the fetchBtnStyle method and not a hard coding in the component per Janaka Stevens' idea (ie the color property), because I theorize I would have no clue what property the user may wish to change; the user may want to change color, font-size or background-color.
button-styles.js
const styleValues = {
base: {
fontSize: '1.0em',
color: '#fff',
backgroundColor: 'red',
}
};
module.exports = {
fetchBtnStyle(values) {
const settings = {};
// making the value immutable here <-------------
Object.assign(settings, styleValues.base)
if (values !== undefined) {
Object.assign(settings, values);
}
return settings;
}
};
button.js
import btnStyles = require('./styles/button-styles.js');
#Radium
class MyButton extends Component {
render() {
return (
<Button style={ btnStyles.fetchBtnStyle(this.props.dynamicStyle) }>
Click Me
</Button>)
}
}
MyButton.defaultProps = {
dynamicStyle: {
backgroundColor: 'green'
}
}
MyButton.propTypes = {
dynamicStyle: PropTypes.object
}
The style needs to be immutable so you will want to define it in the render like so.
class MyButton extends Component {
render() {
let btnSty = MyStyles.base;
if (this.props.dynamicSty)
btnSty.color = this.props.dynamicSty.color;
else
btnSty.color = MyStyles.base.color;
return (
<Button style={btnSty}>
Click Me
</Button>)
}
}

Resources