Material UI responsive grid direction - reactjs

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 }}
...
/>

Related

MUI Grid System to Take Up 100% of Width

hope you're all good.
I'm having an issue finding out how to make my MUI Grid take up the entire width of the Box component it is nested within.
Here is how it looks:
I want the empty space at the end right to be taken up by the entire grid but I can't seem to find a concise answer on how to fix this.
Here is my code in VS Code:
Here is the code in text for the Grid:
<Grid item key={days}>
<Box
key={days}
sx={{
width: 150,
height: 150,
backgroundColor: 'primary.dark',
'&:hover': {
backgroundColor: 'primary.main',
opacity: [0.9, 0.8, 0.7],
},
}}
/>
</Grid>
);
}
return (
<Grid container spacing={1}>
{/* And here I render the box array */}
{box}
</Grid>
);
And here is the parent elements:
Here is the code in real text for the parent elements:
// Parent Element
<Container>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
width: 1,
}}
>
{/* The Title of The Page */}
<Typography align="center" variant="h4" mt={2} mb={2} sx={{ fontWeight: 'bold' }}>
{t('Happy Chocolate Days!')}
</Typography>
{/* My Calendar Grid Component Inside The Box Component */}
<Calendar />
</Box>
</Container>
Thanks for any help in advance
You are setting the boxes to a fixed width & height of 150, thus even though their wrapper has more space left, there is not enough space for another box so it breaks into a new line, thus leaving you with the empty space on the right.
You either set the boxes all of them in the middle of the Container,
OR pick a width for the Container that can have 7 boxes of the same width with some space between them, like 770px width for container, and 10px spaces between them. but in that case you wont need Grid, just pure css.

MUI v5: Failed prop type: The prop `direction` of `Grid` can only be used together with the `container` prop

I'm styling a MUI v5 Grid as follows:
const SettingsGrid = styled(Grid)(({ theme }) => ({
width: `calc(100% - calc(${Number(theme.spacing(2))} * 2))`,
margin: theme.spacing(2),
'& .MuiCard-root + .MuiTypography-subtitle1': {
marginTop: theme.spacing(4),
},
}))
Then, I'm using it as follows:
<Box m={1} overflow="auto">
<SettingsGrid
container
direction="row"
justifyContent="center"
>
<Grid
direction="column"
style={{ minWidth: '35em', maxWidth: '60em' }}
>
<!-- ... -->
</Grid>
</SettingsGrid>
</Box>
This now throws this console warning at runtime:
Failed prop type: The prop `direction` of `Grid` can only be used together with the `container` prop.
I've tried with container={true} but this doesn't help. It seems as if the container property gets lost in styled(). How can I fix this? I'm at a loss.
EDITH: https://codesandbox.io/s/gritty-styled-grid-7l04g
The direction prop of your Grid is only valid if the container prop is set to true, so add the missing container prop in your inner Grid. Internally, a container Grid has the display set to flex, and the direction is mapped to flex-direction, flex-direction is meaningless if the layout is not flex:
<Grid container direction='column'
Just to add to what NearHuscarl has mentioned, this is the place where you are missing the container prop.
<Box m={1} overflow="auto">
<SettingsGrid
container
direction="row"
justifyContent="center"
>
<Grid
container <<<------------------ you are missing this
direction="column"
style={{ minWidth: '35em', maxWidth: '60em' }}
>
<!-- ... -->
</Grid>
</SettingsGrid>
</Box>

Use breakpoints in Material-UI Container

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>

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',
},
}}
>

Unable to scale down mui button size for mobile devices

So I'm struggling to dim the size of buttons with makeStyles hook and newest version of Mui. And whatever kind of property I try to give to my buttons they won't get any narrower than 64px wide in mobile view (media queried ). Do I have to override root theme to achieve my goal?
<Grid container spacing={0} justify="center" className={classes.nav_mobile}>
<Grid container spacing={0} item sm={12} direction="row" justify="space-evenly" >
<Button className={classes.button_mobile}>Home</Button>
</Grid>
</Grid>
makeStyle hook:
button_mobile: {
padding: "0",
fontFamily: ["Comfortaa" , "cursive"],
fontSize: '1.5vw',
backgroundColor: "transparent",
width: ['8vw', '!important'],
height: "2vh",
boxShadow: "none",
color: "#30786E",
margin: " 0",
Thanks to #bertdida.
The .MuiButton-root has min-width: 64px.
I just added new min-width property and it solved things.

Resources