Material-ui makeStyles with both before and after - css

I'm working on a project which requires the following CSS code.
.hexagon, .hexagon::before, .hexagon::after {
width: 67px;
height: 116px;
border-radius: 18%/5%;
}
Is there a way to implement the above style using Material-UI makeStyles without separate use of before and after selectors?

You can use the below code, '&' means the generated class name that will be passed to the component
const useStyles = makeStyles({
root: {
"&, &:before, &:after": {
// your styles
}
}
});
<div className={classes.root}>

Related

How to rewrite a modal CSS without affecting other modals in the project?

I have a loading component that I am importing on many pages in my project in that component I am using a modal, a modal that I have rewritten some of his CSS styles in a CSS file that I imported in the component
the problem that I have is that this CSS change of the modal effects other modals in my project
how can I let this CSS change only related to my component modal without affecting others
my loading component
import React, {Component, PropTypes} from 'react';
import {Modal} from "react-bootstrap";
import ReactLoading from 'react-loading';
import './loading.css'
export default class Loading extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
const {show} = this.props;
return(
<div >
<Modal show={show} className="loadingModal" keyboard={false}>
<Modal.Body className="testtest">
<ReactLoading id="modale" type={"bubbles"} color={"#2f96a1"} height={120} width={120} />
</Modal.Body>
</Modal>
</div>
)
}
}
my loading css:
.modal-backdrop.in {
opacity: 0;
filter: alpha(opacity=00);
}
.modal.in .modal-dialog {
display: flex;
justify-content: center;
margin-top: 9%;
}
#modale{
display: flex;
justifyContent: 'center';
margin: auto;
}
.testtest{
flex: 1;
alignItems: 'center';
justifyContent: 'center'
}
If you're not using CSS modules or such, I think the best way would be to respect the cascade and always assume that the css you import will spill. To do so I would encourage you to use BEM model. With it, it could be rewritten as:
<div>
<Modal show={show} className="loading-modal modal--test" keyboard={false}>
<Modal.Body className="modal--test__body">
<ReactLoading id="modale" class="modal--test__content" type={"bubbles"} color={"#2f96a1"} height={120} width={120} />
</Modal.Body>
</Modal>
</div>
And for css:
.modal--test .modal-backdrop.in {
opacity: 0;
filter: alpha(opacity=00);
}
.modal--test .modal.in .modal-dialog {
display: flex;
justify-content: center;
margin-top: 9%;
}
/* don't use ids for css */
.modal--test__content{
display: flex;
justify-content: 'center';
margin: auto;
}
.modal--test__body{
flex: 1;
alignItems: 'center';
justifyContent: 'center'
}
Naturally, this doesn't follow BEM model exactly as it would require passing classes to the internal elements. Alternatively, for scoping, you can use CSS modules.
You have multiple options:
assign a unique ID for the Modal and change your CSS selectors to target elements with this ID only (recommended)
use the Modal.container property to attach the modal to your Loading component rather than to the document body (discouraged if you do some tricky CSS styling, especially use absolute or fixed positioning of elements - this may mess up the Modal positioning logic)
use the Modal.bsPrefix property to change the class names of the modal elements. Probably OK to do, even though the documentation states that this should be used only if absolutely necessary
You should use CSS-module
According to the official repo CSS Modules are “CSS files in which all class names and animation names are scoped locally by default”.

How to style react styled components using classNames

How to style a styled component based on the class name it has. I found the following implementation through some blogs, but this isn't working. Can someone help me with this? I really appreciate any help you can provide.
import React from "react";
import { TiStarFullOutline } from "react-icons/ti";
import styled from "styled-components";
function StarRating() {
return (
<Star className="filled">
<TiStarFullOutline></TiStarFullOutline>
</Star>
);
}
export default StarRating;
//notworking
const Star = styled.div`
font-size: 2rem;
& .filled {
color: red;
}
`;
//working
const Star = styled.div`
color:red;
`
;
When accessing a child or a selector, you don'thave to use space. Below is an example:
const Star = styled.div`
font-size: 2rem;
&.filled {
color: red;
}
`;
Styled Components Documentation

Apply onHover styles to elements in MuiButton

I am using styled components and Material UI and I can't figure out how to add on hover styles the MuiButton children. I've searched online and followed some of the docs, but I cannot seem to get it to take. I have my jsx setup like so:
<StyledMuiButton onClick={() => ()}>
<Svg />
<MuiTypography color={Color.gray} variant="caption">
Text
</MuiTypography>
</StyledMuiButton>
and the styled component set up like so:
const StyledMuiButton = styled(MuiButton)`
&& {
& .MuiButton-label {
flex-direction: column;
}
&:hover ${MuiTypography} {
color: ${Color.primary};
}
}
`;
Can anyone point me in the correct direction
Here's an example showing a couple ways of targeting elements within a button:
import React from "react";
import Button from "#material-ui/core/Button";
import Typography from "#material-ui/core/Typography";
import DoneIcon from "#material-ui/icons/Done";
import styled from "styled-components";
const StyledButton = styled(Button)`
& .MuiButton-label {
display: flex;
flex-direction: column;
}
&:hover {
color: red;
.MuiSvgIcon-root {
background-color: blue;
}
.MuiTypography-root {
color: green;
&:nth-of-type(2) {
color: purple;
}
}
}
`;
export default function App() {
return (
<div className="App">
<Button>Default Button</Button>
<StyledButton>Styled Button</StyledButton>
<StyledButton>
<DoneIcon />
<span>Styled Button</span>
<Typography>Typography 1</Typography>
<Typography>Typography 2</Typography>
</StyledButton>
</div>
);
}
This leverages the global class names applied to the elements which are documented in the CSS portion of the API page for each component (for instance the Typography documentation is here: https://material-ui.com/api/typography/#css). As a general rule the top-most element within a Material-UI component can be targeted via MuiComponentName-root (e.g. MuiTypography-root for Typography).

Targeting a styled component in React with a webpack generated identifier?

I have a component called LargeDialog which encapsulates a StyledDialogContent (both of which are from the Dialog class of the Material UI library).
LargeDialog.jsx
...
const StyledDialogContent = styled(DialogContent)`
padding: 30px;
`;
class LargeDialog extends Component {
...
render(){
return (<StyledDialogContent> ... </StyledDialogContent>) // Some content within.
}
}
...
The styled components adds a padding: 30px to the DialogContent.
I would like to override this with padding: 0px if the LargeDialog modal is reused in another place.
However, the generated webpack CSS has a random identifier i.e. MuiDialogContentroot-0-3-439 FullDialogModal__StyledDialogContent-ogd6um-6 iMpISc and I'm not sure how to target this.
AnotherComponent.jsx
import LargeDialog from './LargeDialog'
...
const LargeDialogWrapper = styled(LargeDialog)`
// What do I put here to override StyledDialogContent with a random identifier?
`;
class AnotherComponent extends Component {
}
...
I tried exporting StyledDialogContent and targetting it as such:
import LargeDialog, {StyledDialogContent} from './LargeDialog'
...
const LargeDialogWrapper = styled(LargeDialog)`
${StyledDialogContent} {
padding: 0px;
}
`;
But that didn't work too.
Example:
https://codesandbox.io/embed/styled-components-d5pzv?fontsize=14&hidenavigation=1&theme=dark
You target it within the style like so:
const Box = styled.div`
background-color: black;
height: 100px;
`;
const Yellow = styled.div`
background-color: blue;
height: 200px;
${Box} {
background-color: yellow;
}
`;
const App = () => {
return (
<>
<Box />
<Yellow>
<Box />
</Yellow>
</>
);
};
Refer to the related docs section.
If it helps, you can check this example file (note the Heading style for example).
An edit after OP question update
In your example, you missing className if you want to enable styling for your components.
Also, you need WrapperDiv to be a direct child, this is how the CSS works, remember that you writing simple CSS just in javascript:
class LargeDialog extends Component {
render() {
return (
<WrapperDiv className={this.props.className}>
<div>{this.props.children}</div>
</WrapperDiv>
);
}
}
const WrapperLargeDialog = styled(LargeDialog)`
${WrapperDiv} {
background-color: blue;
}
`;
// LargeDialog should be red.
// WrapperLargeDialog should be blue.
class App extends Component {
render() {
return (
<div>
<LargeDialog />
<br />
<WrapperLargeDialog>
<WrapperDiv />
</WrapperLargeDialog>
</div>
);
}
}

How to properly overwrite existing className with emotionJS

I'm trying to use emotion to overwrite the styling of an existing React component from a 3rd party library.
I try my best to simplified the problem in this codesandbox
The ExternalLib simulates a 3rd party component I'm using which I should not change the code.
As you can see it accepts a "prefix" props for css namespace and uses className in static string.(the original one has it as sass variable also)
I first try to get the base className hash with css function, then I try to compose those in emotion way of composition, and I get the expected visual result.
const baseStyle = css`
background-color: blue;
width: 200px;
height: 200px;
`;
const getItemStyle = ({ disabled }) => {
return `
height: 50px;
margin: 4px;
background-color: ${disabled ? "gray" : "yellow"};
`;
};
const getTextStyle = ({ color }) => {
return `
color: ${color}
`;
};
const StyledExternalLib = styled(ExternalLib)`
.${baseStyle}-track {
${getItemStyle};
}
.${baseStyle}-text {
${getTextStyle};
}
`;
however inspecting the style tags, I got many duplicated styles, what am I doing wrong?
you can see there are twice the yellow background
Here what i found, use css prop to the parent tag
css={{
"& .class__youwant--overwrite": {
margin: 80
}
}}
Worked in my case

Resources