I have a project, and in this project I have an interface that contains several fields in addition to two buttons, the first is “Create” and the second is “cancel”, and as it is clear in the picture the two buttons at the end, but I want the two buttons to be in the area in which there is writing in color red
How can I do that?
And the file for the interface is large, so I only put the method of writing the two buttons
main.js:
<div className="p-16 sm:p-24 max-w-2xl ">
<div className={tabValue !== 0 ? "hidden" : ""}>
<ShippingTab />
</div>
</div>
shipping.js:
import React, { useState } from "react";
import InputAdornment from "@material-ui/core/InputAdornment";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";
import "date-fns";
import DateFnsUtils from "@date-io/date-fns";
import {
KeyboardDatePicker,
MuiPickersUtilsProvider,
DatePicker,
} from "@material-ui/pickers";
import { makeStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";
import CloudUploadIcon from "@material-ui/icons/CloudUpload";
import { addInvoice } from "../../../store/invoiceSlice";
import { motion } from "framer-motion";
import { useDispatch } from "react-redux";
import "react-datepicker/dist/react-datepicker.css";
import Slide from "@material-ui/core/Slide";
import { useSnackbar } from "notistack";
const useStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
},
},
input: {
display: "none",
},
button: {
margin: theme.spacing(1),
// padding: theme.spacing(4),
},
}));
function ShippingTab(props) {
const dispatch = useDispatch();
const classes = useStyles();
const [issueDate, setIssueDate] = useState(new Date());
const [dueDate, setDueDate] = useState(new Date());
const [netAmount, setNetAmount] = useState("");
const [taxNumber, setTaxNumber] = useState("");
const [grossAmount, setGrossAmount] = useState("");
const [file, setFile] = useState(null);
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
const handleUploadPDFFileMessageClick = () => {
enqueueSnackbar(
"PDF file has been uploaded successfully",
{ variant: "success" },
{
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
},
{ TransitionComponent: Slide }
);
};
const handleCreateInvoiceMessageClick = () => {
enqueueSnackbar(
"Invoice created successfully",
{ variant: "success" },
{
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
},
{ TransitionComponent: Slide }
);
};
const fileSelectedHandler = (event) => {
console.log(event.target.files[0]);
const file = event.target.files[0];
if (event.target && file) {
// formData.append("invoice", file);
setFile(file);
}
};
const uploadHandler = (event) => {
const formData = new FormData();
formData.append("grossAmount", grossAmount);
formData.append("taxNumber", taxNumber);
formData.append("netAmount", netAmount);
formData.append("issueDate", issueDate);
formData.append("dueDate", dueDate);
formData.append("invoice", file);
console.log(
" invoice grossAmount,taxNumber,netAmount,",
file,
grossAmount,
taxNumber,
netAmount
);
console.log("dueDate,issueDate: ", dueDate, issueDate);
// call api
dispatch(addInvoice(formData));
};
const handleissueDateChange = (date) => {
setIssueDate(date);
console.log("date issssssssss: ", date);
console.log("date issssssssss: ", issueDate);
};
const handleDueDateChange = (date) => {
setDueDate(date);
};
const handleNetAmountChange = (event) => {
setNetAmount(event.target.value);
};
const handleTaxAmountChange = (event) => {
setTaxNumber(event.target.value);
};
const handleGrossAmountChange = (event) => {
setGrossAmount(event.target.value);
};
return (
<>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<div className="flex -mx-4">
<KeyboardDatePicker
inputVariant="outlined"
className="mt-8 mb-16"
margin="normal"
id="date-picker-dialog"
label="issue Date"
format="MM/dd/yyyy"
KeyboardButtonProps={{
"aria-label": "change date",
}}
value={issueDate}
onChange={handleissueDateChange}
/>
<KeyboardDatePicker
inputVariant="outlined"
className="mt-8 mb-16 ml-6"
margin="normal"
id="date-picker-dialog"
label="Due Date"
format="MM/dd/yyyy"
KeyboardButtonProps={{
"aria-label": "change date",
}}
value={dueDate}
onChange={handleDueDateChange}
/>
</div>
</MuiPickersUtilsProvider>
<TextField
className="mt-8 mb-16"
label="Net Amount"
id="extraShippingFee"
variant="outlined"
InputProps={{
startAdornment: <InputAdornment position="start">$</InputAdornment>,
}}
value={netAmount}
onChange={handleNetAmountChange}
fullWidth
/>
<TextField
className="mt-8 mb-16"
label="Tax Number"
id="extraShippingFee"
variant="outlined"
InputProps={{
startAdornment: <InputAdornment position="start">$</InputAdornment>,
}}
value={taxNumber}
onChange={handleTaxAmountChange}
fullWidth
/>
<TextField
className="mt-8 mb-16"
label="Gross Amount"
id="extraShippingFee"
variant="outlined"
InputProps={{
startAdornment: <InputAdornment position="start">$</InputAdornment>,
}}
value={grossAmount}
onChange={handleGrossAmountChange}
fullWidth
/>
<div className={classes.root}>
<input
accept="application/pdf"
className={classes.input}
id="contained-button-file"
// multiple
type="file"
onChange={fileSelectedHandler}
/>
<label htmlFor="contained-button-file">
<Button
variant="contained"
color="primary"
size="large"
component="span"
className={classes.button}
startIcon={<CloudUploadIcon />}
>
{/* <Button variant="contained" color="primary" component="span"> */}{" "}
Upload
</Button>
{/* </Button> */}
</label>
</div>
<motion.div
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0, transition: { delay: 0.3 } }}
>
<Grid
container
direction="row-reverse"
justifyContent="flex-start"
alignItems="flex-end"
>
<Grid item>
<Button
className="whitespace-nowrap mx-4"
variant="contained"
color="secondary"
// onClick={handleRemoveProduct}
>
Cancel
</Button>
</Grid>
<Grid item>
<Button
className="whitespace-nowrap mx-4"
variant="contained"
color="secondary"
// disabled={_.isEmpty(dirtyFields) || !isValid}
onClick={(ev) => {
uploadHandler();
ev.stopPropagation();
handleCreateInvoiceMessageClick(ev);
}}
>
Create
</Button>
</Grid>
</Grid>
</motion.div>
</>
);
}
export default ShippingTab;
CodePudding user response:
You can align the two buttons to the left bottom using flex
and height: 100%
.
All the parents of the two buttons from the
motion.div
upwards includinghtml
andbody
need to have100%
height.The
grid
that contains the buttons andmotion.div
need to haveflex-grow:1
so that they occupy all the free space in their respective container.
html,
body {
height: 100%;
}
div.container {
height: 100%;
display: flex;
flex-direction: column;
}
section.red {
background: red;
padding: 5rem 0
}
section.blue {
background: blue;
padding: 5rem 0
}
section.green {
background: green;
flex-grow: 1;
display: flex;
}
section.green>div {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
}
section.left {
flex-grow: 1;
display: flex;
justify-content: flex-end;
align-items: flex-end;
}
button {
padding: 1rem 2rem;
}
<div >
<section ></section>
<section ></section>
<section >
<div>
<section >
<button>Right</button>
</section>
<section >
<button>One</button>
<button>TWO</button>
</section>
</div>
</section>
</div>
If ShippingTab
has too many parents, it is hard to set 100%
height on all of its parent. In that case, you may absolutely postion it either in the body
or in its nearest relative
container that has / can have 100%
height.
CodePudding user response:
<Grid
container
direction="row-reverse"
justifyContent="flex-start"
top: 100px;
position: relative;
>
...
</Grid>
CodePudding user response:
The parent is a flex element, so try margin-top: auto;
on the children (buttons or container thereof)