react material-ui how to override muibox-root - css

I want to override the MuiBox-root style for the whole application.According to the official documentation I need to identify the class:
And among other things I can override it:
But if I proceed this way, it just removes the styling. What am I doing wrong here?

This will do:
import { withStyles } from "#material-ui/core/styles";
const styles = {
root: {
padding: "10px"
}
};
function App({ classes }) {
return <yourelement className={classes.root}>xyz...<yourelement/>;
}
export default withStyles(styles)(App);

You can use the sx property on the Box component. For example:
<Box sx={{ padding: "10px" }}>
<YourChildComponents/>
</Box>

Lets say aim is to override background css field of root background css field.
Below are the steps
import { makeStyles } from '#mui/styles';
const useStyles = makeStyles({
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
},
});
export default function testFunction() {
const classes = useStyles();
return <Button className={classes.root}>Hook</Button>;
}
Hope this will help.

Related

Override delete icon margin styles in MUI Chip component

I'm using V4 MUI Chip component with size : 'small' and variant: 'outlined' with a deleteIcon specified.
https://v4.mui.com/components/chips/
I'd like to override the margin-right property of the deleteIcon but I'm having trouble getting the right specificity, because MUI is applying more specific styles.
The following styles are applied to the delete icon by MUI:
.MuiChip-outlined-253 .MuiChip-deleteIconSmall-267 {
margin-right: 3px;
}
.MuiChip-outlined-253 .MuiChip-deleteIcon-266 {
margin-right: 5px;
}
How do I apply a style to override the margin-right of the deleteIcon and set it to e.g. '10px'?
You can use the class .MuiChip-deleteIcon based on the Chip api documentation (https://v4.mui.com/api/chip/)
Here is a working codesandbox to play with (has for the both default and outlined variants).
Here is the code to implement the change you want.
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Chip from "#material-ui/core/Chip";
import FaceIcon from "#material-ui/icons/Face";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
justifyContent: "center",
flexWrap: "wrap",
"& > *": {
margin: theme.spacing(0.5)
},
//Here is where you customise the css for the delete icon
"& .MuiChip-deleteIcon": {
marginRight: "20px", // Change those values to yours
},
//For customising the outlined the css for the delete icon
"& .MuiChip-outlined": {
"& .MuiChip-deleteIcon": {
marginRight: "10px", // Change those values to yours
}
}
}
}));
export default function Chips() {
const classes = useStyles();
const handleDelete = () => {
console.info("You clicked the delete icon.");
};
const handleClick = () => {
console.info("You clicked the Chip.");
};
return (
<div className={classes.root}>
<Chip label="Deletable primary" onDelete={handleDelete} color="primary" />
<Chip
icon={<FaceIcon />}
label="Deletable secondary"
onDelete={handleDelete}
color="secondary"
/>
<Chip
icon={<FaceIcon />}
label="Deletable secondary"
onDelete={handleDelete}
color="secondary"
variant="outlined"
/>
</div>
);
}
Another way would be to do something similar in the theme.

Reactjs Media query application

I have a separate App.css file that has global css attributes and have classes for responsiveness. The issue is I want to render elements differently for separate devices but can't seem to figure out how to do that as using conditionals isn't applying as such.
import UserItem from "./UserItem";
import Spinner from "../layout/Spinner";
import PropTypes from "prop-types";
const Users = ({ users, loading }) => {
if (loading) {
return <Spinner />;
} else {
return (
<div style={userStyle} className='body'>
{users.map((user) => {
return <UserItem key={user.id} user={user} />;
})}
</div>
);
}
};
const windowWidth = window.innerWidth;
Users.propTypes = {
users: PropTypes.array.isRequired,
loading: PropTypes.bool.isRequired,
};
const userStyle = {
display: "grid",
gridTemplateColumns: "repeat(3, 1fr)",
gridGap: "1rem",
};
export default Users;
My css #media query which I am trying to apply to effect change on a small device.
/* Mobile Styles */
#media (max-width: 700px) {
.hide-sm {
display: none;
}
}
How do I implement this #media css style so that it can render the page differents through jsx?
You can use material ui. that will fulfil your requirement. Please check this example:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Typography from '#material-ui/core/Typography';
import { green } from '#material-ui/core/colors';
const useStyles = makeStyles(theme => ({
root: {
padding: theme.spacing(1),
[theme.breakpoints.down('sm')]: {
backgroundColor: theme.palette.secondary.main,
},
[theme.breakpoints.up('md')]: {
backgroundColor: theme.palette.primary.main,
},
[theme.breakpoints.up('lg')]: {
backgroundColor: green[500],
},
},
}));
export default function MediaQuery() {
const classes = useStyles();
return (
<div className={classes.root}>
<Typography variant="subtitle1">{'down(sm): red'}</Typography>
<Typography variant="subtitle1">{'up(md): blue'}</Typography>
<Typography variant="subtitle1">{'up(lg): green'}</Typography>
</div>
);
}
Material UI
You can use following example too.
class Card extends Component {
constructor() {
super();
this.mediaQuery = {
desktop: 1200,
tablet: 768,
phone: 576,
};
this.state = {
windowWidth: null
};
}
componentDidMount() {
window.addEventListener('resize', () => {
this.setState({windowWidth: document.body.clientWidth})
});
}
render() {
return (
<div style={{
width: this.state.windowWidth > this.mediaQuery.phone
? '50%'
: '100%',
//more styling :)
}}>
<!-- <Card> contents -->
</div>
);
}
}
Source
I suggest that use CSS #media query to make responsive layouts.
But if you insist on implement with JS and React you should get windowWidth after component mounted. You can use useEffect hook to do so and save value in a state:
const [windowWidth, setWindowWidth] = useState('');
useEffect(() => {
setWindowWidth(window.innerWidth) // or better one -> window.clientWidth
});

How to add linear-gradient color to Slider?

I want to add linear-gradient to Material-UI Slider as color. Is it possible? I try everything.
color: 'linear-gradient(180deg, #29ABE2 0%, #00EAA6 100%)'
linear-gradient creates an image not a color. So you need to use it in CSS that specifies an image (e.g. background-image).
Below is an example of a Slider using a gradient.
import React from "react";
import { makeStyles, withStyles } from "#material-ui/core/styles";
import Slider from "#material-ui/core/Slider";
const useStyles = makeStyles({
root: {
width: 200
}
});
const CustomSlider = withStyles({
rail: {
backgroundImage: "linear-gradient(.25turn, #f00, #00f)"
},
track: {
backgroundImage: "linear-gradient(.25turn, #f00, #00f)"
}
})(Slider);
export default function ContinuousSlider() {
const classes = useStyles();
const [value, setValue] = React.useState(30);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<CustomSlider
value={value}
onChange={handleChange}
aria-labelledby="continuous-slider"
/>
</div>
);
}

How can I understand MaterialUI styled component?

I'm trying to make sense of how to inject styles into component with MaterialUI and I'm very confused! Can anyone please explain what I did wrong? i read the documentation but it honestly didn't make sense to me. What are classes? And how do I attach the const style into the component BeerList?
My code threw an error "Cannot read property of classes undefined. I know I must have pulled from the wrong props. But I don't know how to fix it...
import React from 'react';
import BeerListItem from './BeerListItem';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import GridList from '#material-ui/core/GridList';
import GridListTile from '#material-ui/core/GridListTile';
import GridListTileBar from '#material-ui/core/GridListTileBar';
import IconButton from '#material-ui/core/IconButton';
import StarBorderIcon from '#material-ui/icons/StarBorder';
const styles = theme => ({
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
overflow: 'hidden',
backgroundColor: theme.palette.background.paper,
},
gridList: {
width: '100%',
height: '100%',
transform: 'translateZ(0)',
},
titleBar: {
background:
'linear-gradient(to bottom, rgba(0,0,0,0.7) 0%, ' +
'rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)'
},
icon: {
color: 'white',
},
});
const BeerList = ({beers}) =>{
const {classes} = beers;
const beerItems = beers.map((beer) => {
return <BeerListItem key={beer.id} beer = {beer}/>
});
return (<div className={classes.root} >
<GridList cellHeight={250} spacing={1} >
{beerItems}
</GridList>
</div>);
};
export default withStyles(styles)(BeerList);
classes distructured from props.
you need a little change on your components like:
const BeerList = (props) =>{
const {classes, beers} = props;
// rest of your code
return <div className={classes.root} >
<GridList cellHeight={250} spacing={1} >
{beerItems}
</GridList>
</div>
};
That's it.

Using ReactCSSTransitionGroup with styled-component

I'm using styled-components instead of tradition way of css. But I don't know how it can work together with ReactCSSTransitionGroup.
Basically, ReactCSSTransitionGroup looks for certain classnames in css resource, then apply to a component throughout its lifecycle. However, with styled-components, there are not any class names, styles are applied to components directly.
I know I can choose not to use ReactCSSTransitionGroup because the two technique doesn't look compatible. But when I use only styled-components, seems I can't render any animation when a component is unmounted - it's pure css, can't access component's lifecycle.
Any help or recommendation is appreciated.
I didn't want to use injectGlobal as suggested in another answer because I needed to make the transitions different per component.
It turns out to be pretty easy - just nest the transition classes in the styling for the component:
import React from "react";
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import styled from 'styled-components';
const appearDuration = 500;
const transitionName = `example`;
const Container = styled.section`
font-size: 1.5em;
padding: 0;
margin: 0;
&.${transitionName}-appear {
opacity: 0.01;
}
&.${transitionName}-appear-active {
opacity: 1;
transition: opacity ${appearDuration}ms ease-out;
}`;
export default () => {
return (
<CSSTransitionGroup
transitionName={transitionName}
transitionAppear={true}
transitionAppearTimeout={appearDuration}>
<Container>
This will have the appear transition applied!
</Container>
</CSSTransitionGroup>
);
};
Note that I'm using the newer CSSTransitionGroup, rather than ReactCSSTransitionGroup, but it should work for that too.
Mike Goatly's approach is great, but I had to make small changes to make it work. I changed the <CSSTransition>'s props, and used a function as its child.
See below for an example of a component, which fades in/out based on a state change:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { CSSTransition } from "react-transition-group";
import styled from "styled-components";
const Box = styled.div`
width: 300px;
height: 300px;
background: red;
transition: opacity 0.3s;
// enter from
&.fade-enter {
opacity: 0;
}
// enter to
&.fade-enter-active {
opacity: 1;
}
// exit from
&.fade-exit {
opacity: 1;
}
// exit to
&.fade-exit-active {
opacity: 0;
}
}`;
export default class App extends Component {
constructor() {
super();
this.state = {
active: true
};
setInterval(() => this.setState({ active: !this.state.active }), 1000);
}
render() {
return (
<CSSTransition
in={this.state.active}
classNames="fade"
timeout={300}
unmountOnExit
>
{() => <Box />}
</CSSTransition>
);
}
}
You can use css variable selector in styled-components. Like this:
const Animation = styled(ReactCSSTransitionGroup)`
${({ transitionName }) => `.${transitionName}-enter`} {
opacity: 0;
}
${({transitionName}) => `.${transitionName}-leave`} {
opacity: 1;
}
`
const animationID = 'some-hashed-text'
const AnimationComponent = props => (
<Animation
transitionName={animationID}
transitionEnterTimeout={0.1}
transitionLeaveTimeout={2000}
>
<div>some content</div>
</Animation>
)
Use the injectGlobal() styled-component helper method where your React app is bootstrapped. With this method you can style any CSS selector as if you'd be using conventional CSS.
First create a JS file exporting a template literal with your CSS for the react-transition-group (please not I'm using v2.1 new class names syntax):
globalCss.js
const globalCss = `
.transition-classes {
/* The double class name is to add more specifity */
/* so that this CSS has preference over the component one. */
/* Try removing it, you may not need it if properties don't collide */
/* https://www.styled-components.com/docs/advanced#issues-with-specificity */
&-enter&-enter {
}
&-enter&-enter-active {
}
&-exit&-exit {
}
&-exit&-exit-active {
}
}
`;
export default globalCss;
Then on your entry point file:
index.jsx
import { injectGlobal } from "styled-components";
import globalCss from "./globalCss.js";
injectGlobal`${ globalCss }`; // <-- This will do the trick
ReactDOM.render(
<Provider store={ Store } >
<HashRouter >
<Route path="/" component={ Component1 } />
<Route path="/" component={ Component2 } />
</HashRouter>
</Provider>,
document.getElementsByClassName("react-app")[0]
);
However, if you just use CSS/SASS/Less to write the classes for the react-trasition-group even when you use styled-components, it also works well.
There is a great blog post explaining how to do this:
https://dev.to/terrierscript/styled-component--react-transition-group--very-simple-transition-jja
They use a low level Transiton component available from react-transition-group:
http://reactcommunity.org/react-transition-group/transition
// This is overly simplified, but styles change depend on state from Transition
const MyStyledComponent = styled.div`
transform: translateY(${({ state }) => (state === 'exited' ? "0" : "-100%")});
transition: transform 2s;
`
const App = () =>
<Transition in={animate} timeout={500}>
{(state) => (
// state change: exited -> entering -> entered -> exiting -> exited
<MyStyledComponent state={state}>Hello</MyStyledComponent>
)}
</Transition>
import React from "react";
import { CSSTransition } from 'react-transition-group';
const styles = theme => ({
'fade-enter':{
opacity: 0,
},
'fade-enter-active':{
opacity: 1,
transition: "opacity 300ms"
},
'fade-exit':{
opacity: 1,
},
'fade-exit-active':{
opacity: 0,
transition: "opacity 300ms"
},
})
class myAnimatedComponent extends React.Component {
constructor(props){
super(props);
}
render(){
let {classes} = this.props;
return (
<CSSTransition
in={this.props.conditionVariable}
classNames={{
enter: classes['fade-enter'],
enterActive: classes['fade-enter-active'],
exit: classes['fade-exit'],
exitActive: classes['fade-exit-active'],
}}
timeout={300}
unmountOnExit>
<span>This will have the transition applied to it!</span>
</CSSTransition>
);
}
};
export default (styles)(myAnimatedComponent);
I had to use classes['fade-enter'] etc, because React changes the name of all classes in this component due to the fact that I used withStyles. And because of that too, when I export the component, React inserts my classes into this component's props, that's why I also had to create a variable called classes to catch those classes.

Resources