Use breakpoints in Material-UI Container - reactjs

I use Container and it needs to be different size for mobile and for desktop.
How can I have the Container maxWidth different size based on Breakpoints like this:
<Container maxWidth={{xs:"lg", lg:"md"}}>
instead of using the useStyle and adding a className.

I found most of answer related to functional component, but if you are using class component we can directly use like this. I like to use 'vh' and 'vw' as this unit is direclty adjustable to viewport.
<Container
sx={{
width: {
lg: '35vw',
md: '50vw',
xs: '70vw'
}
}}>

You can do that by using the sx prop which supports responsive values. The breakpoint values can be accessed in theme.breakpoints.values object. See the default theme here to know more.
const theme = useTheme();
<Container
sx={{
bgcolor: "wheat",
maxWidth: {
lg: theme.breakpoints.values["md"],
md: 80,
xs: 20
}
}}
>
<Box sx={{ bgcolor: "#cfe8fc", height: "100vh", width: "100%" }} />
</Container>

Related

Mui conditional rendering of one component

I would like to set disableGutters for MUI Container when xs size.
So far I was only able to do it like so:
<Container disableGutters sx={{ display: { xs: 'block', md: 'none' } }}>
...lot of code
</Container>
<Container sx={{ display: { xs: 'none', md: 'block' } }}>
...lot of duplicit code
</Container>
But because there is a lot of duplicit code I don't feel good about this solution, so is there a better way?
What you can do is use the MUI breakpoints like this:
In your component you should add:
import { useMediaQuery, useTheme } from "#mui/material";
inside de component:
const theme = useTheme();
const isExtraSmallSize = useMediaQuery(theme.breakpoints.down("xs"));
and then:
<Container disableGutters={isExtraSmallSize ? true : false} sx={{ display: { xs: 'block', md: 'none' } }}>
...lot of code
</Container>
or what you can do is use isExtraSmallSize to create the conditional rendering you need
A custom hook with theme and useMediaQuery is very useful, I recommend you to do it

using default theme colors material ui

how to use default theme colors like "primary" or "secondary" in sx property? I don't want to change them, I just want to write sx={{ backgroundColor: "primary" }} or smth like that
You need to be a bit more specific which color you want:
For example to access priamry.main, use:
<Box sx={{ borderColor: 'primary.main' }} />
or for the current text color:
<Box sx={{ color: 'text.secondary' }}>Sessions</Box>
More information

Mui Typography alignment based on breakpoints

Is there a way for me to change my Typography align property based on the pre-defined breakpoints?
For example:
<Typography
align={{ xs: 'left', sm: 'left', md: 'left', lg: 'right', xl: 'right' }}>
The following will cause my page to display nothing but white. I usually use that syntax to work with margins in the Box class and it works fine.
You can't set the Typography align attribute with an object.
As specified in the documentation for the Typography component, the align attribute can only be 'inherit' | 'left' | 'center' | 'right' | 'justify'.
Instead, you could use the withWidth HOC:
Sometimes you might want to change the React rendering tree based on the breakpoint value. We provide a withWidth() higher-order component for this use case.
withWidth injects a width property into your component that gives you access to the current breakpoint value. This allows you to render different props or content based on screen size.
function ResponsiveTypography({ width }) {
// This is equivalent to theme.breakpoints.down("md")
const isSmallScreen = /xs|sm|md/.test(width);
const typographyProps = {
align: isSmallScreen ? "left" : "right"
};
return (
<Typography {...typographyProps}>
Some text
</Typography>
);
}
export default withWidth()(ResponsiveTypography);
This seem to work for me, MUI v5:
import { useTheme } from '#mui/material/styles';
...
const theme = useTheme();
...
<Typography
sx={{
textAlign: 'center',
[theme.breakpoints.up('md')]: {
textAlign: 'left',
},
[theme.breakpoints.up('xl')]: {
textAlign: 'right',
},
[theme.breakpoints.between('sm', 'md')]: {
}
[theme.breakpoints.not('md')]: {
}
}}
>
Breakpoints API
https://mui.com/material-ui/customization/breakpoints/
With MUI v5, I found that sx prop has the ability to do breakpoints without importing the theme object (like in #atazmin's answer).
The breakpoints are mobile-first and get translated to min-width Media Queries. You can specify the starting value with xs and change it by breakpoint using lg and up.
<Typography
sx={{
textAlign: {
xs: 'left',
lg: 'right',
},
}}
>

Material UI responsive grid direction

I want the container direction as "row" above md size screen and "column" below md size screen?
How can I implement it?
<Grid container direction = "row"(in large screens)/direction = "column"(in small screens)>
I tried something this.
<Grid container classes={gridDirection}>
gridDirection: {
direction = "row",
[theme.breakpoints.down('md')]: {
direction = "column",
},
}
but it is not working probably because "direction" is a react prop and not a CSS style.
Is there a way to access these react props inside stylesheet file?
The easiest way and I believe the modern way is to use the sx attribute. Then let MUI handle the breakpoints for you.
These are the default MUI breakpoints as of writing.
xs = extra-small: 0px
sm = small: 600px
md = medium: 900px
lg = large: 1200px
xl = extra-large: 1536px
xs and sm are generally considered to be mobile/small tablet. MUI is mobile first, so xs will be set and not overwritten until the size is md or larger in my example below.
<Grid container sx={{ flexDirection: { xs: "column", md: "row"} }}>
</Grid>
You can use useMediaQuery
import useMediaQuery from '#material-ui/core/useMediaQuery';
const largeScreen = useMediaQuery(theme => theme.breakpoints.up('md'));
<Grid container direction={largescreen?"row":"column"}>
in MUI v5 you can do it like below:
<Grid container direction={{xs: "column", md: "row"}}>
</Grid>
I am thinking there should be at least 3 ways to do it in MUI v5.
with default prop
<Grid
container
spacing={0}
direction={{ xs: 'column', md: 'row' }}
justifyContent={{ xs: 'center', md: 'flex-end' }}
alignItems={{ xs: 'center', md: 'flex-end' }}
>
...
with sx props
<Grid
container
spacing={0}
sx={{ flexDirection: { xs: 'column', md: 'row'} }}
>
in theme override
MuiGrid: {
styleOverrides: {
root: {
'&.MuiGrid-container': {
flexDirection: 'column'
[theme.breakpoints.up('md')]: {
flexDirection: 'row'
},
},
Use flexDirection instead of direction.
gridDirection: {
flexDirection = "row",
[theme.breakpoints.down('md')]: {
flexDirection = "column",
},
}
At least as on date of answering here, Material UI supports direction or flexDirection attributes with component, with these attributes supporting responsive value based on breakpoints mapped object passed to it.
For example, in your case, if direction="row" is needed on large screens and direction="column" is needed for small screens, then the prop can be passed in as:
direction={{xs:'row', lg:'column'}}, thus letting MUI prop handle it with the Grid element as:
<Grid container direction={{xs:'row', lg:'column'}}> ... </Grid>
This is the right style to use it in your code, for this case, in my opinion, though other alternative answers here also work well.
Just set the container false for column view and true for row view
<Grid container={{ lg: true, sm: false }}
...
/>

Reusable component using theme-based Box features

I'd like to create a reusable component using Material-UI's api (not using styled-components.) I got this far - and it almost works - but the settings that use theme variable don't work (e.g, bgcolor and padding). Am I doing something wrong - or is this not possible?
const BigPanel = styled(Box)({
display: 'flex',
width: '100%',
flexgrow: 1,
bgcolor: 'background.paper',
borderRadius: 10,
boxShadow:'1',
p:{ xs: 4, md: 8 }
});
The object passed to styled is intended to be CSS properties, but you have a mixture of CSS properties and Box props (bgcolor, p). Even the ones that are valid CSS properties (display, width) are also valid Box props, so the most straightforward solution is to specify all of them as props.
One way to handle this is to use defaultProps. This makes it very easy to override some of the props when using the component by specifying them explicitly as shown in the example below.
import React from "react";
import Box from "#material-ui/core/Box";
import CssBaseline from "#material-ui/core/CssBaseline";
import { styled } from "#material-ui/core/styles";
const BigPanel = styled(Box)({});
BigPanel.defaultProps = {
display: "flex",
width: "100%",
borderRadius: 10,
flexGrow: 1,
bgcolor: "background.paper",
p: { xs: 4, md: 8 },
boxShadow: "1"
};
export default function App() {
return (
<>
<CssBaseline />
<BigPanel>Default BigPanel</BigPanel>
<BigPanel bgcolor="primary.main" color="primary.contrastText">
BigPanel with explicit props
</BigPanel>
</>
);
}
In the example above, styled isn't really serving any purpose anymore except to create a new component type. Though it isn't less code, below is an alternative way to get the same effect without using styled:
const BigPanel = React.forwardRef(function BigPanel(props, ref) {
return <Box ref={ref} {...props} />;
});
BigPanel.defaultProps = {
display: "flex",
width: "100%",
borderRadius: 10,
flexGrow: 1,
bgcolor: "background.paper",
p: { xs: 4, md: 8 },
boxShadow: "1"
};

Resources