useMediaQuery lg Theme Breakpoint Not Breaking at 1280px - reactjs

I'm trying to create an Ad component on the right hand side of the Page component that disappears whenever the screen size gets below 1280px (MUI lg). Without adding height or content, this works fine, but when the components have a height of 600px or so, the breakpoint shortens to about 1200px. This causes the Ad component to snap below the Page for about 80px or so.
Here's a codesandbox of my desired outcome: code
Here's a codesandbox of what's currently happening when I add height & content: code
(adjust the screen width to see what I'm talking about)
Here's my code:
import useMediaQuery from "#mui/material/useMediaQuery";
import { useTheme } from "#mui/material/styles";
import Box from "#material-ui/core/Box";
import { Grid } from "#material-ui/core";
export default function App() {
const theme = useTheme();
const lgScreen = useMediaQuery(theme.breakpoints.up("lg"));
return (
<Box p={5}>
<Grid container spacing={3}>
<Grid item xs={12} sm={12} md={12} lg>
<Box sx={{ bgcolor: "warning.main", height: "600px" }}>Page</Box>
</Grid>
<Grid item style={{ width: 335 }}>
{lgScreen ? (
<Box sx={{ bgcolor: "secondary.main", height: "600px" }}>Ad</Box>
) : null}
</Grid>
</Grid>
</Box>
);
}

Related

How to pass props to a component being "styled" in MUI?

Learning MUI and following the docs pretty well. However, I'm trying to style the Paper component as in the examples, but I want the Paper component to have elevation={3}.
How do I pass that prop to Paper in the below code?
import * as React from 'react';
import { styled } from '#mui/material/styles';
import Box from '#mui/material/Box';
import Paper from '#mui/material/Paper';
import Grid from '#mui/material/Unstable_Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
}));
export default function BasicGrid() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2}>
<Grid xs={8}>
<Item>xs=8</Item>
</Grid>
<Grid xs={4}>
<Item>xs=4</Item>
</Grid>
<Grid xs={4}>
<Item>xs=4</Item>
</Grid>
<Grid xs={8}>
<Item>xs=8</Item>
</Grid>
</Grid>
</Box>
);
}
You can pass the prop and access it. within the Styled component. Remember these are mostly passed as HTML attributes so boolean works a little differently as a string.
Here's a working example at Codesandbox. You can check how we have added a border to the item based on the prop.
import * as React from "react";
import ReactDOM from "react-dom";
import { styled } from "#mui/material/styles";
import Box from "#mui/material/Box";
import Paper from "#mui/material/Paper";
import Grid from "#mui/material/Unstable_Grid2";
function App() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2}>
<Grid xs={8}>
<Item border={"true"}>xs=8</Item>
</Grid>
<Grid xs={4}>
<Item>xs=4</Item>
</Grid>
<Grid xs={4}>
<Item>xs=4</Item>
</Grid>
<Grid xs={8}>
<Item>xs=8</Item>
</Grid>
</Grid>
</Box>
);
}
const Item = styled(Paper)(({ theme, border }) => ({
backgroundColor: theme.palette.mode === "dark" ? "#1A2027" : "#fff",
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: "center",
border: border === "true" ? "1px solid red" : "none",
color: theme.palette.text.secondary
}));
ReactDOM.render(<App />, document.querySelector("#app"));

Material-UI: How to center pagination button?

I tried to get Pagination from Material-UI
but I want to center the buttons of the arrow and number of page.
I tried to center by creating a <div style={{textAlign: "center"}}> but it doesn't work because it came all in one box.
there is any way to get inside the this component and make the numbers and button to get in the center?
If you're using TablePagination, you need to remove the spacer div which push the pagination content to the right and set the container justify-content to center:
import TablePagination, {
tablePaginationClasses
} from "#mui/material/TablePagination";
<TablePagination
sx={{
[`& .${tablePaginationClasses.spacer}`]: {
display: "none"
},
[`& .${tablePaginationClasses.toolbar}`]: {
justifyContent: "center"
}
}}
{...}
/>
If you're using the Pagination from DataGrid, just set the justify-content to center because the container is already flex:
import { makeStyles } from "#mui/styles";
import { paginationClasses } from "#mui/material/Pagination";
const useStyles = makeStyles({
root: {
[`& .${gridClasses.footerContainer}`]: {
justifyContent: "center"
}
}
});
<DataGrid pagination {...data} className={classes.root} />
Their Pagination component is using display: flex. Adding the following style rule should achieve what you're trying to do
.MuiPagination-ul { justify-content: center; }
using below code
<Box display="flex" justifyContent="center">
<Pagination ... />
</Box>
To center pagination, i suggest you wrap it inside a Grid System, then put it in the middle of two grid items with the flexGrow property equal to 1.
<Grid container>
<Grid item sx={{ flexGrow: 1 }}></Grid>
<Grid item>
<Pagination />
</Grid>
<Grid item sx={{ flexGrow: 1 }}></Grid>
</Grid>

Create a grid with variable card heights using material-ui react

I am trying to create a grid similar to this website by using Material-UI. However when the height of one card changes every card height changes. I tried to use direction="row" and direction="column" but it doesn't seem to work. I was wondering if there a way to change the height of the image inside depending on the size of the image while having a grid like the website above.
All I can see at the moment is this:
Here is my code for the card:
import React from 'react';
import Card from '#material-ui/core/Card';
import CardHeader from '#material-ui/core/CardHeader';
import CardMedia from '#material-ui/core/CardMedia';
import CardContent from '#material-ui/core/CardContent';
import CardActions from '#material-ui/core/CardActions';
import Avatar from '#material-ui/core/Avatar';
import IconButton from '#material-ui/core/IconButton';
// import Typography from '#material-ui/core/Typography';
import FavoriteIcon from '#material-ui/icons/Favorite';
import ShareIcon from '#material-ui/icons/Share';
import MoreVertIcon from '#material-ui/icons/MoreVert';
import { useStyles } from '../style/card.styles';
export default function Cards({ profile, sourceImage }) {
const classes = useStyles();
return (
<Card className={classes.root} style={{ height: '100%' }}>
<CardHeader
avatar={
<Avatar aria-label="recipe" src={profile} className={classes.avatar}>
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title="Shrimp and Chorizo Paella"
subheader="September 14, 2016"
/>
<CardContent>
<CardMedia
className={classes.media}
image={sourceImage}
title="Paella dish"
/>
{/* <img src={sourceImage} style={{ maxHeight: '20rem' }} /> */}
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<FavoriteIcon />
</IconButton>
<IconButton aria-label="share">
<ShareIcon />
</IconButton>
</CardActions>
</Card>
);
}
And the layout page:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Grid from '#material-ui/core/Grid';
import Cards from './Card';
import vertical from '../images/v1.jfif';
import horizontal from '../images/h1.png';
import '../style/card.css';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
paper: {
height: 140,
width: 100,
},
control: {
padding: theme.spacing(2),
}
}));
export default function HomePage() {
const imagess = [vertical, horizontal, vertical, horizontal]
const classes = useStyles();
return (
<Grid container justify="center" className={classes.root} spacing={2}>
<Grid item xs={12}>
<Grid container alignItems="flex-start" justify="center" spacing={1}>
{imagess.map((image, index) => (
<Grid key={index} item>
<Cards profile={""} sourceImage={image} />
</Grid>
))}
</Grid>
<Grid container alignItems="flex-start" justify="center" spacing={1}>
{imagess.map((image, index) => (
<Grid key={index} item>
<Cards profile={""} sourceImage={image} />
</Grid>
))}
</Grid>
</Grid>
</Grid>
);
}
I think what you are looking for is a masonry grid. It's worth a google search.
What these packages do is calculate positions within a container on page load and resize. One example for react could be react-responsive-masonry
Example usage with react-responsive-masonry
import React from "react"
import Masonry, {ResponsiveMasonry} from "react-responsive-masonry"
// The number of columns change by resizing the window
class MyWrapper extends React.Component {
render() {
return (
<ResponsiveMasonry
columnsCountBreakPoints={{350: 1, 750: 2, 900: 3}}
>
<Masonry>
<ChildA />
<ChildB />
{/* Children */}
<ChildY />
<ChildZ />
</Masonry>
</ResponsiveMasonry>
)
}
}
// The number of columns don't change by resizing the window
class MyWrapper extends Component {
render() {
return (
<Masonry columnsCount={3}>
<ChildA />
<ChildB />
{/* Children */}
<ChildY />
<ChildZ />
</Masonry>
)
}
}
In case of the material ui you would basically replace the Grid and only render cards inside the Masonry.

Material-UI Grid does not hide when using display

I want to use MUI Grid and I wanted to hide one item Grid if the screen is small, so I found something called Display. My code looks like this:
function CRUDView() {
return (
<Grid
container
spacing={1}
direction="row"
justify="center"
alignItems="center"
>
<Grid item xs={12} lg={6}>
<span>XX</span>
</Grid>
<Grid item xs={6} display={{ xs: "none", lg: "block" }} >
<span>YY</span>
</Grid>
</Grid>
);
}
I don´t uderstand why it doesn't work (the text YY still appears) . Can't I use display with Grid maybe? If yes then why?
The style functions are not automatically supported by the Grid component.
The easiest way to leverage the style functions is to use the Box component. The Box component makes all of the style functions (such as display) available. The Box component has a component prop (which defaults to div) to support using Box to add style functions to another component.
The Grid component similarly has a component prop, so you can either have a Grid that delegates its rendering to a Box or a Box that delegates to a Grid.
The example below (based on your code) shows both ways of using Box and Grid together.
import React from "react";
import ReactDOM from "react-dom";
import Grid from "#material-ui/core/Grid";
import Box from "#material-ui/core/Box";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
gridItem: {
border: "1px solid red"
}
});
function App() {
const classes = useStyles();
return (
<Grid
container
spacing={1}
direction="row"
justify="center"
alignItems="center"
>
<Grid className={classes.gridItem} item xs={12} lg={6}>
<span>XX</span>
</Grid>
<Box
component={Grid}
className={classes.gridItem}
item
xs={3}
display={{ xs: "none", lg: "block" }}
>
<span>YY</span>
</Box>
<Grid
component={Box}
className={classes.gridItem}
item
xs={3}
display={{ xs: "none", lg: "block" }}
>
<span>ZZ</span>
</Grid>
</Grid>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
For MUI v5:
In MUI v5 the <Hidden> tag got deprecated in favor for sx.display property withing <Grid> and <Box> tags - display documentation.
For MUI v4 and earlier:
MUI exposes a <Hidden> component to achieve this. Just wrap component you want to hide for specific screen size:
<Hidden xsDown >
<p>Hide me on XS view port width.</p>
</Hidden>
You can find more examples in the hidden documentation.
In MUI v5, you can change the display value directly on Grid without having to use Box anymore:
<Grid
item
xs={3}
sx={{
display: { xs: "none", lg: "block" }
}}
>
<span>YY</span>
</Grid>
Grid Items just setup your layout.
They don't actually display anything. The MUI display option is for hiding specific elements.
Try this:
function CRUDView() {
return (
<Grid
container
spacing={1}
direction="row"
justify="center"
alignItems="center"
>
<Grid item xs={12} lg={6}>
<span>XX</span>
</Grid>
//removed from the below Grid Item
<Grid item xs={12} lg={6}>
<span display={{ xs: "none", lg: "block" }}>YY</span>
</Grid>
</Grid>
);
}
That will hide the individual span element even though the grid is still there.

How to make each Card the same size in my Material Grid

I learn React and following this tutorial but even I have the same code the result is not the same. From the tutorial I want to have a Grid like this:
Image from the Tutorial
But what I get is this:
Image from my code
import React, { Component } from 'react';
import { connect } from "react-redux";
import { withStyles } from '#material-ui/styles';
import { Grid, Paper, Typography } from "#material-ui/core";
import Card from "#material-ui/core/Card";
import CardActionArea from "#material-ui/core/CardActionArea";
import CardContent from "#material-ui/core/CardContent";
const images = require.context('../../public/images', true);
export class Posts extends Component {
constructor() {
super();
}
componentDidUpdate(prevProps) {
}
render() {
const { classes } = this.props;
return (
<div style={{ marginTop: 20, padding: 30 }}>
<Grid container spacing={40} justify="center">
{this.props.books.map(post => (
<Grid item key={post.title} Box width={1 / 4}>
<Card>
<CardActionArea>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{post.title}
</Typography>
<Typography component="p">{post.description}</Typography>
<Typography component="p">{post.author}</Typography>
<Typography component="p">{post.genre}</Typography>
<Typography component="p">{post.publish_date}</Typography>
<Typography component="p">{post.price}</Typography>
</CardContent>
</CardActionArea>
</Card>
</Grid>
))}
</Grid>
</div>
);
}
}
function mapStateToProps(state) {
return {
books: state.reducer.booksList
}
}
export default connect(mapStateToProps)(withStyles(styles)(Posts));
What am I doing wrong? I think it´s the text that forces the Card to be bigger but I have not read about how to constraint text if that is possible
You can apply style to the cards
var cardStyle = {
display: 'block',
width: '30vw',
transitionDuration: '0.3s',
height: '45vw'
}
And in your CardStyle you can apply the above styling by
<Card style={cardStyle}>
<CardHeader
title="URL Avatar"
subtitle="Subtitle"
avatar="https://placeimg.com/800/450/nature"
/>
Your post.titles are long. You can use a fluid grid. Remove Box width={1 / 4} from Grid item.
<Grid item key={post.title} xs={3}>
xs={3} to scale to 1/4 of the container.
You can also set noWrap property to show an ellipsis for long titles instead of a wrapping.
<Typography noWrap ...>
{post.title}
</Typography>

Resources