Grid Items aren't beside eachother Material UI - javascript

I am using the Grid component in material-ui. I am having trouble having the grid items stack beside each other. Right now they are stacking below each other. I am not sure what is making them stack below each other. I have made it so only on small screens the grid items will stack on top of each other, other wise each grid item should take up 4 columns. I am using react for the front-end. Here is my code:
GridItem:
const styles = theme => ({
image: {
maxWidth: "100%",
maxHeight: "100%"
},
});
render() {
const { post, auth, classes } = this.props;
<div className={classes.root}>
<Link to={`/post/${post._id}`}>
<Grid
item
key={post.key}
sm={12}
md={4}
lg={4}
>
<img src={post.productImage} className={classes.image} />
<Typography>
{post.name}
<br />
{post.size}
</Typography>
</Grid>
</Link>
</div>
PostFeed:
render() {
const { posts } = this.props;
return posts.map(post => <ListingPost key={post._id} post={post} />);
}
}
Grid:
const styles = theme => ({
root: {
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
overflow: "hidden",
backgroundColor: theme.palette.background.paper,
margin: 0
},
grid: {
margin: "auto",
width: "80%",
display: "inner-block"
},
paper: {
margin: "1%",
padding: "1%",
width: "80%"
},
});
render() {
const { classes } = this.props;
const { posts, loading } = this.props.post;
let postContent;
if (posts === null || loading) {
postContent = <div> loading</div>;
} else {
postContent = <PostFeed posts={posts} />;
}
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<Typography align="center" variant="display2">
Listings
</Typography>
<Grid container className={classes.grid} spacing={16}>
{postContent}
</Grid>
</Paper>
</div>
);
}
}

Like Yash Rahurikar said, remove the line flexWrap: "wrap" of the Grid style, and add wrap='nowrap' to your Grid container.

You can try to use
<Grid container direction={'row'}></Grid>
so you inner items may arrange themselves beside each other.
Hope that helps

<Grid
container
direction="row"
justify="flex-start"
alignItems="flex-start"
spacing={1}
>
//above 👆🏻 should be your main grid container
//wrap your grid item with the link using component prop
<Grid item key={post.key} component={Link} to={`/post/${post._id}`} >
// Your rest content #here
</Grid>
</Grid>

Try using align-items property.
<Grid container spacing={1} alignItems="flex-end">

Related

Getting Problem in Layout Upon Using Lottie Animation in Gatsby and Material UI

Getting Problem in Layout Upon Using Lottie Animation in Gatsby and Material UI. Heres the code
import React from "react"
import Grid from "#material-ui/core/Grid"
import Typography from "#material-ui/core/Typography"
import Lottie from "react-lottie"
import { makeStyles } from "#material-ui/core/styles"
import useMediaQuery from "#material-ui/core/useMediaQuery"
import data from "../../images/data.json"
const useStyles = makeStyles(theme => ({
textContainer: {
padding: "2rem",
[theme.breakpoints.down("xs")]: {
padding: "1rem",
},
},
heading: {
[theme.breakpoints.down("xs")]: {
fontSize: "3.5rem",
},
},
}))
export default function HeroBlock() {
const animationData = JSON.parse(JSON.stringify(data))
const classes = useStyles()
const matchesLG = useMediaQuery(theme => theme.breakpoints.down("lg"))
const matchesMD = useMediaQuery(theme => theme.breakpoints.down("md"))
const matchesXS = useMediaQuery(theme => theme.breakpoints.down("xs"))
const defaultOptions = {
loop: true,
autoplay: false,
animationData,
}
return (
<Grid container justifyContent="space-around" alignItems="center">
<Grid item classes={{ root: classes.textContainer }}>
<Grid container direction="column">
<Grid item>
<Typography
align="center"
variant="h1"
classes={{ root: classes.heading }}
>
The Premier
<br />
Developer Clothing Line
</Typography>
</Grid>
<Grid item>
<Typography align="center" variant="h3">
high quality, custom-designed shirts, hats, and hoodies
</Typography>
</Grid>
</Grid>
</Grid>
<Grid item>
<Lottie
isStopped
options={defaultOptions}
width={
matchesXS
? "20rem"
: matchesMD
? "30rem"
: matchesLG
? "40rem"
: "50rem"
}
/>
</Grid>
</Grid>
)
}
Here is the SS of My Layout. The Animation Should be in column but it is stacked up.
Here is the SS of my Layout
And when i inspect in the console the Lottie animation generating new div with styles and in that div the lottie animation reside. Here is the div which i have inspected in console
<div style="width: 40rem; height: 100%; overflow: hidden; margin: 0px auto; outline: currentcolor none medium;">
Inside the div the Lottie animation is running.
</div>
So i think the main prbolem is with this div. How to solve this problem.

Displaying/hiding JSON info based on clicked item in React/MaterialUI

I'm creating an FAQ section based on a JSON file I have that has an array of objects with 'Question' and 'Answer.
It's set up to where when you click on the question on the left, it displays the corresponding answer to the right...which does work correctly. The problem is I want to hide the data when the user clicks on that question again and that part is not working. When I click on a question again it will change the icon but doesn't change the box on the right. I want the Answer box to completely disappear when the question is clicked on again.
I'm guessing it's something that I'm doing wrong with setting the state:
const [clickedIndex, setClickedIndex] = useState({});
const [displayAnswer, setDisplayAnswer] = useState();
const handleClick = (index) => () => {
setClickedIndex((state) => ({
[index]: !state[index],
}));
setDisplayAnswer(faqdata[index].Answer);
console.log(displayAnswer);
};
<Grid container spacing={3}>
<Grid item>
<List
style={{
maxHeight: 430,
width: 500,
overflow: 'auto',
border: '1px solid black',
}}
>
{faqdata.map((item, index) => (
<ListItem style={{ cursor: 'pointer' }}>
<ListItemIcon>
{clickedIndex[index] ? <RemoveIcon /> : <AddIcon />}
</ListItemIcon>
<ListItemText
primary={item.Question}
onClick={handleClick(index)}
/>
</ListItem>
))}
</List>
</Grid>
<Grid item>
<List
style={{
maxHeight: 430,
width: 500,
overflow: 'auto',
border: '1px solid black',
}}
>
<ListItem>{displayAnswer}</ListItem>
</List>
</Grid>
</Grid>
I would consider using a single state variable to store the currently open answer which can be:
null (meaning that no answer is open)
a number (meaning the answer to the question with that index is open)
const Container = () => {
const [openQuestion, setOpenQuestion] = useState(null);
const toggleOpenQuestion = (index) => {
if(openQuestion === index) {
setOpenQuestion(null)
}
setOpenQuestion(index)
}
return <UIComponents openQuestion={openQuestion} toggleOpenQuestion={toggleOpenQuestion}/>
}
Then in the UI you can work out what to display based on this value as follows:
<Grid container spacing={3}>
<Grid item>
<List
style={{
maxHeight: 430,
width: 500,
overflow: "auto",
border: "1px solid black",
}}
>
{faqdata.map((item, index) => (
<ListItem style={{ cursor: "pointer" }}>
<ListItemIcon>
{openQuestion === index ? <RemoveIcon /> : <AddIcon />}
</ListItemIcon>
<ListItemText primary={item.Question} onClick={() => toggleOpenQuestion(index)} />
</ListItem>
))}
</List>
</Grid>
<Grid item>
<List
style={{
maxHeight: 430,
width: 500,
overflow: "auto",
border: "1px solid black",
}}
>
<ListItem>{displayAnswer}</ListItem>
</List>
</Grid>
</Grid>;
Worth mentioning here that you should probably wrap the toggleOpenQuestion function in a useCallback to prevent uneccessary re-renders in the child component:
const toggleOpenQuestion = useCallback((index) => {
if(openQuestion === index) {
setOpenQuestion(null)
}
setOpenQuestion(index)
}, [openQuestion])

How to position content perfectly within the left center of Paper component and remain that way on smaller devices?

I am putting together a component for my Goal Sharing social media app. This is what I have so far:
I'm trying to position the Avatar component as well as the two typography components beneath the Avatar component within the center of the left section of this Paper component. I have tried doing this by altering marginLeft and marginTop as you can see in the code below, but the issue when I do this is the components in this Goal component jumble on top of each other when I switch over to smaller devices. So, what's the best way to position these components in the center of the left section, and to ensure they remain that way on smaller devices?
This is the parent component file:
import React, { useEffect } from "react";
import Moment from "react-moment";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { getGoals } from "../../actions/goal";
import Spinner from "../layout/Spinner";
import Navbar from "../dashboard/Navbar";
import ThumbUpAltIcon from "#material-ui/icons/ThumbUpAlt";
import ThumbDownAltIcon from "#material-ui/icons/ThumbDownAlt";
import ChatIcon from "#material-ui/icons/Chat";
import DeleteIcon from "#material-ui/icons/Delete";
import DoneIcon from "#material-ui/icons/Done";
import {
Typography,
Container,
CssBaseline,
makeStyles,
Grid,
Card,
Avatar,
CardContent,
CardActions
} from "#material-ui/core";
const useStyles = makeStyles(theme => ({
paper: {
marginTop: theme.spacing(8),
display: "flex",
flexDirection: "column",
alignItems: "center"
},
submit: {
margin: theme.spacing(2, 0, 2)
},
form: {
marginTop: theme.spacing(5)
},
cardGrid: {
paddingTop: theme.spacing(4),
paddingBottom: theme.spacing(4)
},
card: {
height: "100%",
display: "flex",
flexDirection: "column",
alignItems: "center"
},
cardContent: {
flexGrow: 1
},
profileHeader: {
textAlign: "center",
marginBottom: 10
},
avatar: {
width: theme.spacing(10),
height: theme.spacing(10),
marginLeft: "2.5vw",
marginTop: "5vh"
},
name: {
textAlign: "center",
marginLeft: "2vw"
},
goalText: {
marginTop: "5vh",
marginLeft: "3vw"
},
postedOn: {
marginLeft: "2vw"
}
}));
const Goals = ({ getGoals, auth, goal: { goals, user, loading } }) => {
useEffect(() => {
getGoals();
}, [getGoals]);
const classes = useStyles();
return loading ? (
<>
<Navbar />
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Spinner />
</div>
</Container>
</>
) : (
<>
<CssBaseline />
<Navbar />
<main>
<Container className={classes.cardGrid} maxWidth="md">
<Typography variant="h2" className={classes.profileHeader}>
Goals
</Typography>
<Grid container spacing={4}>
{goals.map(singleGoal => (
<Grid item key={singleGoal._id} xs={12}>
<Card fullwidth="true" className={classes.card}>
<Grid container spacing={2}>
<Grid item>
<Avatar
className={classes.avatar}
src={singleGoal.avatar}
/>
<Typography variant="subtitle2" className={classes.name}>
{singleGoal.first_name} {singleGoal.last_name}
</Typography>
<Typography
variant="caption"
className={classes.postedOn}
>
Posted on{" "}
<Moment format="MM/DD/YYYY">{singleGoal.date}</Moment>
</Typography>
</Grid>
<Grid item xs={12} sm container>
<Grid item xs container direction="column" spacing={2}>
<Grid item xs>
<Typography
className={classes.goalText}
variant="body1"
gutterBottom
>
{singleGoal.text}
</Typography>
<Typography variant="h5"></Typography>
</Grid>
</Grid>
</Grid>
</Grid>
<CardContent className={classes.cardContent}></CardContent>
<CardActions>
<ThumbUpAltIcon />
<Typography variant="caption">
{singleGoal.likes.length}
</Typography>
<ThumbDownAltIcon />
<Link to={`/goal/${singleGoal.user}`}>
<ChatIcon />
</Link>
<Typography variant="caption">
{singleGoal.comments.length}
</Typography>
{!auth.loading && singleGoal.user === auth.user._id && (
<DoneIcon />
)}
{!auth.loading && singleGoal.user === auth.user._id && (
<DeleteIcon />
)}
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Container>
</main>
</>
);
};
Goals.propTypes = {
getGoals: PropTypes.func.isRequired,
goal: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
goal: state.goal,
auth: state.auth
});
export default connect(mapStateToProps, { getGoals })(Goals);
Try this
card: {
height: "100%",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center"
},

Grid Items are in a column instead of a row Material-UI

I am trying to have a grid that has 3 items in a row. However the grid in my code continues vertically and there is only one item per row. There is an image in each grid item as well. How can I change it so there is 3 grid items in a row. Here's my code:
Grid.js:
const styles = theme => ({
root: {
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
overflow: "hidden",
backgroundColor: theme.palette.background.paper,
margin: 0
},
paper: {
margin: "1%",
padding: "1%",
width: "80%"
},
});
class GridListings extends Component {
componentDidMount() {
this.props.getPosts();
}
render() {
const { classes } = this.props;
const { posts, loading } = this.props.post;
let postContent;
if (posts === null || loading) {
postContent = <div> loading</div>;
} else {
postContent = <PostFeed posts={posts} />;
}
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<Typography align="center" variant="display2">
Sneaker Listings
</Typography>
{postContent}
</Paper>
</div>
);
}
}
postfeed.js:
class PostFeed extends Component {
render() {
const { posts } = this.props;
return posts.map(post => <ListingPost key={post._id} post={post} />);
}
}
ListingPost.js:
const styles = theme => ({
root: {
flexGrow: 1,
maxWidth: "30%",
padding: theme.spacing.unit * 2
},
image: {
maxWidth: "100%",
maxHeight: "100%"
},
img: {
margin: "auto",
display: "block",
maxWidth: "100%",
maxHeight: "100%"
}
});
class ListingPost extends Component {
onDeleteClick(id) {
console.log(id);
}
render() {
const { post, auth, classes } = this.props;
return (
<Paper className={classes.root}>
<Grid container spacing={16} direction="row">
<Grid item>
<ButtonBase className={classes.image}>
<img
className={classes.img}
alt="complex"
src={post.productImage}
/>
</ButtonBase>
</Grid>
<Grid item xs={12} sm container direction="row">
<Grid item xs container spacing={16}>
<Grid item xs>
<Typography gutterBottom variant="subheading">
Shoes
</Typography>
<Typography gutterBottom>Size:12</Typography>
<Typography color="textSecondary">Brand New</Typography>
</Grid>
<Grid item>
<Typography style={{ cursor: "pointer" }}>Remove</Typography>
</Grid>
</Grid>
<Grid item>
<Typography variant="subheading">$19.00</Typography>
</Grid>
</Grid>
</Grid>
</Paper>
);
}
}
Any help is appreciated.
You have to use the bootstrap class row in below component. Try below code
PostFeed.js
class PostFeed extends Component {
render() {
const { posts } = this.props;
let postss= [];
posts.map(post => {
postss.push(<ListingPost key={post._id} post={post} />);
});
return (
<div className="row">
{postss}
</div>
);
}
}
OR
In your grid.js just add div with className row
<Paper className={classes.paper}>
<Typography align="center" variant="display2">
Sneaker Listings
</Typography>
<div className="row">
{postContent}
</div>
</Paper>

Material-UI: Full width List inside of Grid

Using material-ui I am trying to make a <List /> inside of a <Grid /> column. I want the list to scroll on overflow but also take up the width of the grid it is in. I can get both of these to work but not at the same time. the first section with the <Grid /> is the overflowY functioning properly but without the full width of the <ListItem />:
const styles = theme => ({
root: {
flexGrow: 1,
},
list: {
flexGrow: 1,
position: 'absolute',
overflow: 'auto',
bottom: '1em',
top: '1em',
},
})
...
<Grid item xs>
<List classes={{ root: classes.list }}>
{genereateData(35).map(item => (
<ListItem button>
<ListItemText primary={item} />
</ListItem>
))}
</List>
</Grid>
...
<List classes={{ root: classes.root }}>
but if I switch the line to the last little bit of code above the full width part works. So why would the flexGrow: 1 work in the root prop but not the list prop, and is there a way to get both? I assume it has to do with position: absolute but I cannot get rid of that. Just looking for a way to get both.
Here is a codesandbox!

Categories

Resources