I'm using Material UI Grid to make an image grid and I'm trying to get rid of the empty spaces between some grid items. I've tried changing the alignitems and justify values of the container, but it didn't work.
See image.
return <Grid container alignItems="flex-start" justify="center" className="img-container" spacing={2}>
{/* All images */}
{docs && docs
.map(image => (
// In a grid item
<Grid className="img-item" item key={image.id} xs={12} md={6} lg={4}>
{/* all accounts */}
{docs2 && docs2
.filter((user) => image.userID === user.userID)
.map(user => (
<div key={image.id} className="div">
<img src={image.url} alt="uploaded pic" />
<Typography variant="subtitle1"> By {user.userName}
{/* Delete button only renders if currentUser.uid === image.userID*/}
{handleButton(image.userID) &&
<IconButton
color="secondary" aria-label="delete image"
onClick={() => handleDeleteImage(image.id,
image.userID, image.name)}
component="span" >
<DeleteForever />
</IconButton>}
</Typography>
</div>
))}
</Grid>
))}
</Grid>
}
The problem is the Grid container, Grid item takes the size of its content in that case its image, but the Grid container takes the size of the Larger Grid item in your case the first Grid item that's why the following Grids have spaces below.
In your case, dealing with list of images you should use GridList component not Grid.
Follow this link for more details about it https://material-ui.com/components/grid-list/
Related
I'm trying to do a products carousel with Slick and Bootstrap, but slick is removing Bootstrap nature of equalling heights as you can see in the screenshots:
https://imgur.com/QuzSIys ( without slick )
https://imgur.com/9P3sIJO ( with slick carousel )
Already tried a solution with JQuery and calcs but didn't work as expected, as shown in the next screenshots. ( I'm talking about this solution: Equal Height Bootstrap Cards within Slick Carousel )
https://imgur.com/RnlTaJr ( The height is so long and not in the bigger content max )
CAROUSEL CODE:
<Container className={'mt-2 mb-3'}>
<h3>{props.category}</h3>
<Row>
<Slider {...carouselSettings}>
{
products.map((product)=>{
return(
<Col className="col text-center">
<ProductCard title={product.title} description={product.description} image={product.image} />
</Col>
)
})
}
</Slider>
</Row>
</Container>
CARD COMPONENT CODE:
<Card className={'mh-100 h-100'}>
<div className={'wrapper'}>
<Card.Img className="img-fluid mh-100" variant="top" src={props.image} />
</div>
<Card.Body >
<Card.Title>{props.title}</Card.Title>
<Card.Text>
{props.description}
</Card.Text>
<Button variant="outline-primary" style={{marginRight: '10px'}}>Ver Mais</Button>
<Button variant="outline-success">Carrinho</Button>
</Card.Body>
</Card>
HOME CODE:
<>
<Header/>
<div className={'container mt-2'} style={{minHeight: 'calc(100vh - 380px)'}}>
<OffersCarousel/>
<ProductsCarousel category={'Lançamentos'}/>
</div>
<Footer/>
</>
Please any suggestion or fix to this or something that is not clear on this question tell me!
For my project I'm tasked to use material-ui. Is there a way to reduce the width height of the div containing "Sign In With" text as shown in pic to bring the buttons closer to the text?
From this:
To this:
The code:
<div className={classes.root}>
<Grid
container
direction="row"
spacing={0}
>
<React.Fragment>
<Grid item xs={6} container direction="row">
<Grid item xs={12}>
<h1>Sign In With</h1>
</Grid>
<Grid item xs={12} container>
<Grid item xs={3}>
<Button
className={classes.buttonGoogle}
onClick={() => {
if (props.onSelectGoogle !== undefined)
props.onSelectGoogle('google');
}}
>
Google
</Button>
</Grid>
<Grid item xs={3}>
<Button
className={classes.buttonLinkedIn}
onClick={() => {
if (props.onSelectLinkedIn !== undefined)
props.onSelectLinkedIn('linkedin');
}}
>
LinkedIn
</Button>
</Grid>
</Grid>
</Grid>
<Grid item xs={6}>
<div className={classes.LoginImage}></div>
</Grid>
</React.Fragment>
</Grid>
</div>
The First layer Grid is enough, the inside one just complicates stuff.
I removed the inside grid (the one containing title and buttons).
You can add some styles to title and buttonsContainer
<div className={classes.root}>
<Grid container direction="row" spacing={0} >
<Grid item xs={6} >
<h1 className={classes.title} >Sign In With</h1>
<div className={classes.buttonsContainer} >
<Button
className={classes.buttonGoogle}
onClick={() => {
if (props.onSelectGoogle !== undefined)
props.onSelectGoogle('google');
}}
>Google</Button>
<Button
className={classes.buttonLinkedIn}
onClick={() => {
if (props.onSelectLinkedIn !== undefined)
props.onSelectLinkedIn('linkedin');
}}
>LinkedIn</Button>
</div>
</Grid>
<Grid item xs={6}>
<div className={classes.LoginImage}></div>
</Grid>
</Grid>
</div>
I need to disable a button in reactjs depending on a value taken from a different component.
In below component (main.js), I need to disable the Button. But This has to be disabled depending on a value taken from a value another component (upload.js)
export default function HorizontalLabelPositionBelowStepper() {
.
.
.
return (
<Grid container>
<Grid item lg="12" md="12" xs="12">
<div className={classes.root}>
<div>
<Grid container justify="center">
<Grid item md="1">
<Button // button I need to disable
variant="contained"
color="secondary"
onClick={handleNext}
endIcon={<NavigateNext />}
>
{activeStep === steps.length - 1 ? "Finish" : "Next"}
</Button>
</Grid>
</Grid>
</div>
</div>
</Grid>
</Grid>
);
}
And this is the upload.js
// imports...
.
.
.
export default function ElevateAppBar(props) {
const [file, setFile] = useState('');
const [filename, setFileName] = useState('eg: employees.csv'); // this filename value should be passed to the component `main.js`
return (
<Grid container justify="flex-start">
<Grid container item lg="12" md="12">
<Grid item lg="4" md="4" xs="4">
<Form>
<Form.File id="custom-file" label={filename} custom />
</Form>
</Grid>
</Grid>
<Grid container justify="center">
<Button variant="contained" style={{backgroundColor: "lightgreen"}} endIcon={<CloudUpload />}>
Upload
</Button>
</Grid>
</Grid>
);
}
In the upload.js I have a variable with the name filename. I need to pass this value to the first component - that is main.js
so the logic could be like something (this is not reactjs syntaxes, this is just to give the idea on what I need to do):
if(filename_taken_from_upload_js == "eg: employees.csv"){
// disable the button
}else{
// enable the button
}
Can someone help, Please?
This could be a case for lifting state up : https://reactjs.org/docs/lifting-state-up.html#lifting-state-up
If this value could be used by other unrelated components, you should consider putting it in a global state, using Redux or Context API.
https://redux.js.org/faq/react-redux#react-redux
https://reactjs.org/docs/context.html#when-to-use-context
i have a cards.js which has the following function. Now the calling method passes three values . header1, header2 and Link (this is the *.js page that has to be called)
export default function Cards(props) {
const classes = useStyles();
return (
<div className="App">
<Card className={classes.card} variant="outlined">
<CardContent>
<Typography
variant={"h5"}
gutterBottom
>
{props.header1}
</Typography>
<Typography
variant={"caption"} >
{props.header2}
</Typography>
<Divider className={classes.divider} light />
<Button variant="contained" color="secondary" onClick={()=> (call either link1.js or link2.js )}>
Lets goooooo!
</Button>
</CardContent>
</Card>
</div>
);
}```
calling method
class UIM extends Component {
render() {
return (
<div className="text-page">
<Grid container alignItems="center" justify="space-evenly" >
<Grid ><Cards header1="card 1 for a task1" header2="click text2" link="link1"/></Grid>
<Grid ><Cards header1=" card 2 for task 2" header2=" click text 2" link="link2"/></Grid>
</Grid>
</div>
)
}
}
I am new to react and learning right now, so wondering if such a thing is possible or should i use router to route to different pages (ie. call either link1.js or link2.js ) ??
I found out by by adding pathname:props.link i can get the button to link to multiple locations within the material ui button.
<Card className={classes.card} variant="outlined">
<CardContent>
<Typography
variant={"h5"}
gutterBottom
>
{props.header1}
</Typography>
<Typography
variant={"caption"} >
{props.header2}
</Typography>
<Divider className={classes.divider} light />
<Button variant="contained" color="secondary">
<NavLink to={{pathname:props.link}}>Lets goooooo!</NavLink>
</Button>
</CardContent>
</Card>
I’m having an issue with React and using the material-ui library. My cards are getting rendered vertically instead of side by side horizontally. I tried messing around with the react grid component but it didn’t help.
Output:
Expected:
Here is the original code that perfectly renders cards side by side: https://github.com/acm-uic/roll-call/blob/feature/home-page/src/App.tsx
return (
<React.Fragment>
<CssBaseline />
<AppBar position="relative">
<Toolbar>
<Typography variant="h6" color="inherit" noWrap>
ACM Roll Call
</Typography>
</Toolbar>
</AppBar>
<main>
{/* Hero unit */}
<div className={classes.heroContent}>
<Container maxWidth="sm">
<Typography component="h1" variant="h2" align="center" color="textPrimary" gutterBottom>
ACM Roll Call
</Typography>
<Typography variant="h5" align="center" color="textSecondary" paragraph>
The Association for Computing Machinery Student Chapter at the University of Illinois at Chicago (ACM#UIC) is a community for all UIC students interested in computing, computing machinery and related technologies.
</Typography>
</Container>
</div>
<Container className={classes.cardGrid} maxWidth="md">
{/* End hero unit */}
<Grid container spacing={4}>
{cards.map(card => (
<Grid item key={card} xs={12} sm={6} md={4}>
<Card className={classes.card} raised>
<CardMedia
className={classes.cardMedia}
image="https://avatars3.githubusercontent.com/u/20177515?s=280&v=4"
title="Image title"
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant="h5" component="h2">
Event Name
</Typography>
<Typography>
This is a media card. You can use this section to describe the content.
</Typography>
</CardContent>
<CardActions>
<Button size="small" color="primary">
View
</Button>
<Button size="small" color="primary">
Edit
</Button>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Container>
</main>
{/* Footer */}
<footer className={classes.footer}>
<Typography variant="h6" align="center" gutterBottom>
ACM Roll Call
</Typography>
<Typography variant="subtitle1" align="center" color="textSecondary" component="p">
Attendance tracking for events and meetings
</Typography>
</footer>
{/* End footer */}
</React.Fragment>
);
I modified the original code since I had to fetch data for the cards. Here is the modified version in two separate files (Event.tsx & Events.tsx): https://github.com/acm-uic/roll-call/tree/feature/printEvents/src/components
return (
<React.Fragment>
<CssBaseline />
<Container className={classes.cardGrid} maxWidth="md">
{/* End hero unit */}
<Grid container spacing={4}>
{cards.map(card => (
<Grid item key={card} xs={12} sm={6} md={4}>
<Card className={classes.card} raised>
<CardMedia
className={classes.cardMedia}
image="https://avatars3.githubusercontent.com/u/20177515?s=280&v=4"
title="Image title"
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant="h5" component="h2">
{summary ? summary : 'Busy'}
</Typography>
<Typography>
<div>
{start ? (start.dateTime ? start.dateTime : start.date) : <></>} | {end ? (end.dateTime ? end.dateTime : end.date) : <></>} | {location}
</div>
</Typography>
</CardContent>
<CardActions>
<Button size="small" color="primary">
View
</Button>
<Button size="small" color="primary">
Edit
</Button>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Container>
</React.Fragment>
);
You can use MUI's autolayout feature on the Grid to help you customize your card rendering.
import React from 'react';
import { Grid } from '#material-ui/core';
import CardData from 'path to get your data'; // Data must be an array
export default const Main = props => {
return (
<Grid container direction="row" justify="center" alignItems="center" spacing={3}>
{
CardData.map(data => (
<Grid item xs sm md lg key={data.key}>
<CustomCard data={data} />
</Grid>
))
}
</Grid>
);
}
By just providing the property xs, md, sm, lg and xl without the numbering, MUI will do the stacking for you as equally as possible within the same row. So all you need to do is adjusting the size of your card content to allow for several card placement within the same row.
I downloaded your repo and ran it on my machine. It only rendered AppBar so please let me know how to get the data to be displayed. However, I also looked at the code and I noticed one thing.
We are looping through the events and rendering component like so:
{(this.state.events && this.state.events.items)
? this.state.events.items.map((ev, key) =>
(<Event key={key} ev={ev} />)) //render material card for each event
: (<></>)}
But the <Container /> and <Grid /> components are being rendered from <Event /> component. It means that event cards will be contained in its own container and Grid. In my opinion, this is what could be causing the issue.
If we pull container and Grid out of Event.tsx and put in inside Events.tsx then it might fix it.
e.g.,
<Container>
<Grid ..>
this.state.events.items.map((ev, key) =>
(<Event key={key} ev={ev} />)) //render material card for each event
: (<></>)}
</Grid .. />
<Container />