How to override MUI PaperProps with styled components? - javascript

I am using MUI and I want to override the width of the menu with styled components.
I tried this:
const StyledMenu = styled(Menu)`
&& {
width: 100%;
}
`;
And nothing happened.
Then I found out that MUI has the PaperProps and when applying:
<StyledMenu
id="menu-appbar"
PaperProps={{
style: {
width: '100%',
},
}}
>
I got the desiered result but I would like to accomplish it via styled-components, is it possible?

Every style that you write in PaperProps attribute will make it's impact in .MuiPaper-root class.
So your code can be like this:
const StyledMenu = styled(Menu)`
&& {
& .MuiPaper-root {
width: 100%;
}
}
`;
More insights can be found in the docs.

Related

How can I style a toastify toast in the same js file, without using the styled toastcontainer?

in my app I use the ToastContainer component to display more than one type of toast. I do not want them both to have the same style, therefore I cannot use a styled ToastContainer to achieve what I want.
I know from the documentation for toastify that a toast can have it's own className for which you can specify the color etc. in a css file. But I want to have the css in the javascript file. But I have not yet found a way for it to work.
This is what I have come up with:
const notify = () => {
toast(customMsg, {
className: container,
autoClose: false,
closeOnClick: false,
position: toast.POSITION.BOTTOM_RIGHT,
});
};
const container = {
backgroundColor: 'yellow !important',
color: ' black !important',
borderRadius: '10px !important',
border: '2px solid orange',
width: '200px'
};
This does not work, but if I change className to "container" and put the styling in a css file it works. Is there a way for the className to be specified in the javascript file?

Material-UI Override .MuiDataGrid-columnsContainer CSS

I am trying to override the CSS property position on the .MuiDataGrid-columnsContainer. When looking at the https://material-ui.com/api/data-grid/#css you can see there is a rule for root but there isn't a rule for .MuiDataGrid-columnsContainer. I have read the documentation on overriding the CSS properties but I can't seem to get it to work for that class.
Normally I would leverage the rule and do the following
const useStyles = makeStyles({
paper: {
background: '#010310',
}
});
Then return something like this
const classes = useStyles();
return (
<DataGrid classes={{ paper: classes.paper }} />
);
However, when I replace the word paper in the makeStyles and in the return to be columnsContainer it doesn't work.
Possible Reasons It's Not Working
Based on the documentation on the CSS for datagrid (link above), the only Rule is root and since the .MuiDataGrid-columnsContainer doesn't have a Rule then I need to do it differently. Unfortunately, I haven't found another way that has worked.
I appreciate any help I get, Thank you!
You can give inline style to the class that you want to override and give it an !important flag.
For example if the class you want to override is .MuiDataGrid-columnsContainer then you can simply do this .
.MuiDataGrid-columnsContainer{
position: relative !important; // to override the default css property
}
For a local overriding of MuiDataGrid-columnsContainer, as you can see on api doc, you have to pass your css to root class. So:
<DataGrid classes={{ root: classes.root }} />
Now if you want to override MuiDataGrid-columnsContainer in particular, in your makeStyles write something like:
const useStyles = makeStyles({
root: {
"&.MuiDataGrid-columnsContainer":{
background: '#010310',
}
}
});
Thats it.
root: {
"& .MuiDataGrid-root": {
color: `#fff`
},
"& .MuiIconButton-label": {
color: `#fff`
}
},
I put this "& .MuiDataGrid-root" in my main layout and it works very well.
const useStyles = makeStyles(() => ({
root: {
display: 'flex',
"& .MuiDataGrid-root": {
color: `#fff`
},
"& .MuiIconButton-label": {
color: `#fff`
}
},
appBar: {
backgroundColor:'#181745',
color:theme.palette.primary.main,
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
},
}))

Change the styling of the component with props or css variables?

There is the following block, which I put in a separate component: img
And at certain breakpoints, I need to change its styling.
I see 2 possible normal options, but I can't figure out which one is more convenient.
through the props :
<InfoBlock
options={
iconWidth: 100,
iconMargin: 50,
color: 'red',
breakpoints: {
991: {
iconWidth: 50,
iconMargin: 25
},
767: {
iconWidth: 20,
color: 'brown'
}
}
}
/>
That is, in this scenario, I can essentially turn the received props inside the component itself as much as I want and change what is necessary
change the component styling via css variables
<InfoBlock class="info-block"/>
.info-block {
--icon-width: 100px;
--icon-margin: 50px;
--color: red;
#media (max-width: 991px) {
--icon-width: 50px;
--icon-margin: 25px;
}
#media (max-width: 767px) {
--icon-width: 20px;
--color: brown;
}
}
Both options are working, and the question is, is it logical to change the css properties by using the component's propses? Just for me personally, using #media looks easier and more familiar
I use makeStyles from Material UI to achieve the same.
const useStyles = makeStyles({
anyClassName:{
backgroundColor: 'red', // You can't type background-color as '-' are not accepted as variable names
fontSize: '1Rem';
// After doing the styling
},
AnotherClassName: {
backgroundColor: 'green';
fontSize: '0.8rem';
}
})
// Now we have to assign it like this
const classes = useStyles();
Once if we do this we can assign the class to any component we want like this.
<td className={classes.anyClassName}>I'm the red boi</td>
<h3 className={classes.AnotherClassName}>I'm the Green Guy</h3>

How to create button with text under icon by reactjs?

Now, I have component like this:
code of it:
import React from "react";
import {withStyles} from "material-ui/styles";
import Settings from "material-ui-icons/Settings";
import Button from "material-ui/Button";
const styles = {
button: {
color: "primary",
height: 95,
width: 95,
disableRipple: "true",
focusRipple: "true",
},
icon: {
height: 35,
width: 35,
display: "block",
float: "none",
},
text: {
height: 35,
width: 35,
display: "block",
float: "none",
marginTop: 10,
},
};
/* eslint-disable react/prop-types */
const IconedLabel = ({classes}) => (
<section>
<Button className={classes.iconButton} variant="raised" color="primary">
<Settings className={classes.icon}/>
<div className={classes.text}>Message</div>
</Button>
</section>
);
export default withStyles(styles)(IconedLabel);
But need to button, that in top part contains icon and text message in bottom.
I use reactjs and material-ui lib from here https://material-ui-next.com/demos/buttons/
The Button component uses flexbox to control the layout/alignment of content. To align the content vertically (so the icon is above the text), you can simply change the flex-direction to column.
This style needs to be applied to an element inside the button component, not to the root element. You can use the classes property to override all of the styles in a component.
In this case, you want to add flexDirection: column to the label class.
Documentation on class overrides in material ui v1
Here's a working example. Hope it helps.
const [React, ReactDOM, Button, Settings, withStyles] = [window.React, window.ReactDOM, window['material-ui'].Button, ({className}) => <i className={`material-icons ${className}`}>settings</i>, window['material-ui'].withStyles]
// Ignore code above this line
const styles = theme => ({
button: {
height: 95, // setting height/width is optional
},
label: {
// Aligns the content of the button vertically.
flexDirection: 'column'
},
icon: {
fontSize: '32px !important',
marginBottom: theme.spacing.unit
}
})
const CustomButton = ({ classes }) => (
<Button
/* Use classes property to inject custom styles */
classes={{ root: classes.button, label: classes.label }}
variant="raised"
color="primary"
disableRipple={true}
>
<Settings className={classes.icon} />
Message
</Button>
)
const WrappedCustomButton = withStyles(styles)(CustomButton)
ReactDOM.render(<WrappedCustomButton />, document.querySelector('#root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script><script src="https://unpkg.com/material-ui#1.0.0-beta.40/umd/material-ui.production.min.js"></script><link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"><div id="root" />
A (potentially bad) solution would simply be:
.MuiIconButton-label {
flex-direction: column
}
I say bad, because you might want to use it in it's standard format elsewhere.
What I opted to do was add a class name nav-bar-icon-wrapper to the IconButton & set the flex direction in it's parent:
.nav-bar-icon-wrapper {
flex-direction: column
}
.MuiIconButton-label {
flex-direction: inherit
}
If I run into instance later where I want the icon/label button to be standard, I'll just add a new class default-icon-wrapper and css that handles that:
.default-icon-wrapper {
flex-direction: row
}
FWIW:
I preach the BEM http://getbem.com/introduction/ convention AND that whenever you make a component, you add an optional modifier prop.
I have functions in a shared dir that looks these:
export function BEMifyThis(modifier) {
return (klass) => BEMify(klass, modifier)
}
export function BEMify(klass, modifier=false) {
if (modifier) {
klass += ` ${klass}-${modifier}`
}
return klass
}
Then I use that everywhere in my component so the user can access the component elements as a group or individually using their modifiers.
import {BEMifyThis} from '../shared/bem'
const BEMify = BEMifyThis(this.props.modifier)
className={"navbar__menu_item")}
becomes
className={BEMify("navbar__menu_item")}
so something like navbar__menu_item becomes navbar__menu_item navbar__menu_item-logout

How to align text in Draft.js

I'm wondering how to align text in Draft.js just like on the picture below.
I have searched this several days, but I haven't found the solution.
After reading the source code, I found a way for it. Using blockRenderMap, you can add some custom block types like this:
const blockRenderMap: Record<string, DraftBlockRenderConfig> = {
'header-one-right': {
element: 'h1',
wrapper: <StyleHOC style={{ ...blockStylesMap['header-one'], display: 'flex', justifyContent: 'flex-end' }} />,
},
'header-two-right': {
element: 'h2',
wrapper: <StyleHOC style={{ ...blockStylesMap['header-two'], display: 'flex', justifyContent: 'flex-end' }} />,
},
'header-three-right': {
element: 'h3',
wrapper: <StyleHOC style={{ ...blockStylesMap['header-three'], display: 'flex', justifyContent: 'flex-end' }} />,
},
'unstyled-right': {
element: 'div',
wrapper: <StyleHOC style={{ ...blockStylesMap['unstyled'], display: 'flex', justifyContent: 'flex-end' }} />,
},
};
I use flex to avoid wasting time to find a away to override the internal style .public-DraftStyleDefault-ltr.
StyleHOC is quite simple:
const StyleHOC: React.FC<Props> = ({ style, children }) => {
const childrenWithStyle = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { style });
}
return child;
});
return <>{childrenWithStyle}</>;
};
And then you can toggle the blockType using RichUtils.toggleBlockType(editorState, blockType).
The Editor component has a div with the class .public-DraftStyleDefault-ltr. This controls the text alignment of each paragraph that you write. As you create more paragraphs, more of these divs are created to contain the text. The text is wrapped in a span element and .public-DraftStyleDefault-ltr has a default alignment of text-align: left.
I created some css classes for text-align: left, text-align: center, text-align: right and text-align: justify and added this basic for loop to my component for creating text alignment buttons.
const textBlock = document.querySelectorAll(".public-DraftStyleDefault-ltr");
for (let i = 0; i < textBlock.length; i++) {
textBlock[i].classList.toggle(this.props.style);
}
this.props.style is the name of the css class that determines the text-alignment I wanted.
It is a pretty basic fix since this way when you click align right say, the whole document is aligned right. I am planning to work on this so only the selected text is aligned so should be able to update this answer soon. Hope it helps in some way
I tried to make almost the same thing. But my trouble was in text-align property, which was correctly set to block span, but .public-DraftStyleDefault-ltr doesn't react to it.
So, I have made next decision, which get the first div child, and copy it's params:
const paragraphs: any = document.querySelectorAll(".public-DraftStyleDefault-ltr");
for (let i = 0; i < paragraphs.length; i++) {
const paragraph = paragraphs.item(i);
if (paragraph) {
const firstItem = paragraph.querySelectorAll('*').item(0);
// Apply to the parent the first child style
paragraph.style.textAlign = firstItem.style.textAlign;
}
}
To change block alignment you can:
1- set alignment data
const modifiedBlockState = Modifier.setBlockData(editorState.getCurrentContent(),
editorState.getSelection(),Map({align:'align-center'}));
setEditorState(EditorState.push(modifiedBlockState,'change-block-data'));
2- use it in styling function
/*
JSX
blockStyleFn={ block => block.getData().get('align')
this will return 'align-center|left|right' which will be assigned as a classname
*/
<Editor blockStyleFn={ block => block.getData().get('align')} .../>
//CSS
.align-center div{
text-align: center;
}
.align-right div{
text-align: right;
}
.....

Categories

Resources