I've got a MUI table with cells that link to another part of the app when clicked. Rather than wrap the entire row, I'm selectively wrapping certain cells. The link/routing is working - but I'm left with this annoying dead unclickable space due to some styling interactions.
In the picture below I've opened the 'inspect element' view on dev tools to show specifically the dead zone I'm dealing with in the first cell, and to show some mui styling details that might be relevant. Code with styles included further down.
Styles:
const useStyles = makeStyles(theme => ({
table: {
minWidth: 650,
position: 'relative',
fontSize: 10
},
largeIcon: {
width: 60,
height: 60
},
tableContainer: {
minHeight: 320
},
tableBodyContainer: {
minHeight: 265
},
tableHeadRow: {
'& .MuiTableCell-root': {
borderRight: `1px solid ${COLORS.WHITE}`,
borderBottom: `none`,
padding: '8px 5px 8px',
fontSize: 10,
cursor: 'pointer'
}
},
arrow: {
color: theme.palette.grey[500]
},
arrowActive: {
transform: 'rotate(-180deg)',
color: theme.palette.primary.main,
display: 'inline-block'
},
tableRow: {
'& .MuiTableCell-root': {
borderRight: `1px solid ${theme.palette.grey[200]}`,
borderBottom: 'none',
cursor: 'pointer',
padding: 5,
paddingTop: 8,
paddingBottom: 8,
minWidth: 25
},
'& .MuiTableCell-root:first-child': {
border: 'none'
}
},
selectedRow: {
backgroundColor: `${COLORS.SECONDARY} !important`,
'& .MuiTableCell-root': {
color: COLORS.WHITE
}
},
editIcon: {
backgroundImage: `url(${EditIcon})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
width: 18,
height: 18
}
}));
And the table:
return (
<div className={classes.tableContainer}>
<TableContainer className={classes.tableBodyContainer}>
<Table className={classes.table} size="small">
<TableHead>
<TableRow className={classes.tableHeadRow}>
<TableCell />
{tableHeadElements.map(e => (
<TableCell key={e.key} align="center">
{e.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{folders?.items.map((folder: IFolderDTO, index: number) => {
const { id, name, updatedAt } = folder;
return (
<TableRow
className={classes.tableRow}
classes={{ selected: classes.selectedRow }}
selected={selectedRow === id}
onClick={() => setSelectedRow(id)}
key={index}
>
<TableCell align="center" >
<Link to={APP_DASHBOARD_CHILD_FOLDER_CONTENTS_PATH(id)}>
<Box>
<IconButton color="default" size={'medium'}>
<FolderIcon fontSize="default" />
</IconButton>
</Box>
</Link>
</TableCell>
{[name, new Date(updatedAt)].map(cell => (
<TableCell key={index} align="center">
<Link to={APP_DASHBOARD_CHILD_FOLDER_CONTENTS_PATH(id)}>
<Box>{getCorrectFormat(cell)}</Box>
</Link>
</TableCell>
))}
<FolderActionsMenu
folderId={id}
onDeleteFolder={onDeleteFolder}
openDialogWithId={openDialogWithId}
/>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<FolderFormDialog />
</div>
Kill the dead unclickable space! (please)
Thanks
Related
import * as React from "react";
import {
Select,
MenuItem,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper
} from "#mui/material";
import KeyboardArrowDownIcon from "#mui/icons-material/KeyboardArrowDown";
function createData(name, mobile, access) {
return { name, mobile, access };
}
const rows = [
createData("Sam", 9865745159),
createData("Amily", 8723879237),
createData("Eva", 9432671262),
createData("Jack", 7898083305),
createData("Diana", 8973667356)
];
export default function DenseTable() {
const [access, setAccess] = React.useState(1);
const handleChange = (event, index, data) => {
setAccess(event.target.value);
};
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell align="center">Name</TableCell>
<TableCell align="center">Mobile</TableCell>
<TableCell align="center">Access</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow
key={row.name}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row" align="center">
{row.name}
</TableCell>
<TableCell align="center">{row.mobile}</TableCell>
<TableCell align="center">
<Select
value={access}
onChange={handleChange}
MenuProps={{
MenuListProps: { disablePadding: true }
}}
fullWidth
size="small"
IconComponent={() => (
<KeyboardArrowDownIcon
sx={{
position: "absolute",
right: 10,
width: "20px",
pointerEvents: "none"
}}
/>
)}
sx={{
fontSize: "14px",
width: "100px",
height: "28px"
}}
>
<MenuItem
value={1}
sx={{
fontSize: "14px",
height: "25px",
width: "100%"
}}
>
Allow
</MenuItem>
<MenuItem
value={2}
sx={{
fontSize: "14px",
height: "30px",
width: "100%"
}}
>
Decline
</MenuItem>
</Select>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
I am using ReactJs with Material UI table with dropdown in each row of the table cell. Whenever I am changing the dropdown option of one row then automatically changes to same option in dropdown of all rows.I have to handle each row separately. How to change dropdown in each row of mui table cell in a loop? file.
Move the dropdown to a new jsx component and manage the state there
function dropdownComponent (){
const [access, setAccess] = React.useState(1);
const handleChange = (event, index, data) => {
setAccess(event.target.value);
};
return
(<Select
value={access}
onChange={handleChange}
MenuProps={{
MenuListProps: { disablePadding: true }
}}
fullWidth
size="small"
IconComponent={() => (
<KeyboardArrowDownIcon
sx={{
position: "absolute",
right: 10,
width: "20px",
pointerEvents: "none"
}}
/>
)}
sx={{
fontSize: "14px",
width: "100px",
height: "28px"
}}
>
<MenuItem
value={1}
sx={{
fontSize: "14px",
height: "25px",
width: "100%"
}}
>
Allow
</MenuItem>
<MenuItem
value={2}
sx={{
fontSize: "14px",
height: "30px",
width: "100%"
}}
>
Decline
</MenuItem>
</Select>
)
}
Call it like this
<TableCell align="center">
<dropdownComponent />
I am using a MUI5 React table and have a hard time figuring out how to adjust the column and cell width. The table needs to span 100% but the fields have to stay together and not spread out automatically like they are doing now. Ideally, I need to set the width of the cell to the width of the content, or at least to a fixed width. Here are my components:
const StyledTableCell = styled(TableCell)(({ theme }) => ({
height: "44px",
padding: "5px 12px",
[`&.${tableCellClasses.head}`]: {
color: theme.palette.gray.main,
fontWeight: 700,
fontSize: "12px",
lineHeight: "14px",
height: "20px",
},
[`&.${tableCellClasses.body}`]: {
fontWeight: 400,
fontSize: "13px",
color: theme.palette.darkGray.main,
},
}));
const StyledTableRow = styled(TableRow)(({ theme }) => ({
"&:nth-of-type(even)": {
backgroundColor: theme.palette.action.hover,
},
border: 0,
}));
function DataTable({data}) {
function createData(fields) {
const res = { ...fields };
return res;
}
const rows = data.map((el) => {
return createData(el);
});
return (
<TableContainer sx={{ width: "100%", marginBottom: "25px" }}>
<Table
sx={{
[`& .${tableCellClasses.root}`]: {
borderBottom: "none",
},
}}
>
<TableHead>
<TableRow>
{SectionTitles.container.fields.map((field, index) => {
return (
<StyledTableCell key={index} align="left">
{field}
</StyledTableCell>
);
})}
</TableRow>
</TableHead>
<TableBody>
{rows.map((row, index) => (
<StyledTableRow key={index}>
{Object.keys(row).map((el, index) => {
return (
<StyledTableCell key={index} align="left">
{row[el]}
</StyledTableCell>
);
})}
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
I have tried setting the width in the styled components and tried to set it in sx as well but nothing is working, the columns still spread out. I have explored pretty much every solution I could find on SO and on google and nothing is making it change the width.
I have an e-commerce website and I added a cart icon in the navbar. When clicked, a MUI modal should open (and it does) but it doesn't close anymore. I also added an "X" button with close function, but still nothing. What is happening?
Also, the component Navbar (that you can see in the code), is rendered in all the other components (pages) of the app.
//imports
const Container=styled.div`
height:100px;
//background-color:#d1bda4;
${mobile({ height: "50px" })}
`
const Wrapper=styled.div`
padding:15px 20px;
display: flex;
justify-content:space-between;
text-align:center;
align-items: center;
${mobile({ padding: "10px 0px" })}
`
const Left=styled.div`
flex:1;
display:flex;
align-items:center;
${mobile({ flex: 2, justifyContent: "center" })}
`
const MenuItem=styled.span`
font-size:14;
cursor:pointer;
paddingLeft:20px;
flex:1;
${mobile({ fontSize: "12px", marginLeft: "10px" })}
`
const Center=styled.div`
flex:1;
${mobile({ fontSize: "12px", marginLeft: "10px" })}
`
const Brand=styled.h1`
font-weight:bold;
cursor:pointer;
${mobile({ fontSize: "24px" })}
`
const Right=styled.div`
flex:1;
display:flex;
align-items:center;
${mobile({ flex: 2, justifyContent: "center" })}
`
const MenuItemCart=styled.div`
paddingLeft:10px;
cursor:pointer;
`
const StyledLink = styled(Link)`
font-size:14;
cursor:pointer;
paddingLeft:20px;
flex:1;
text-decoration:none;
color:black;
${mobile({ fontSize: "12px", marginLeft: "10px" })}
`;
const MainContainer=styled.div`
display:flex;
flex-direction:column;
justify-content:space-between;
height:100%;
overflow-y: auto;
width:100%;
overflow-y:scroll;
`
const HeaderContainer=styled.div`
display: flex;
flex:0.1;
width:100%;
height:1%;
justify-content:space-between;
flex-direction:row;
padding:20px;
`
const LeftContainer=styled.div`
display: flex;
flex:0.5;
flex-direction:column;
width:100%;
margin-right:50px;
`
const Button=styled.button`
width:30px;
height:30px;
border:0px #dcd3ca;
border-radius: 50px;
cursor:pointer;
`
const DeleteButton=styled.button`
width:30px;
height:30px;
border:0px white;
border-radius: 50px;
background-color:white;
cursor:pointer;
`
export const Navbarr = ({items}) => {
const [user, error] = useAuthState(auth);
const [cartItems, setCartItems]=React.useState(0);
const [open, setOpen] = React.useState(false);
const [currentUserCart, setCurrentUserCart]=React.useState([]);
const [currentProducts, setCurrentProducts]=React.useState([]);
const [cartSubTotal, setCartSubtotal] = React.useState(0);
const handleOpen = () => {
fetchProducts();
setOpen(true);
};
const fetchProducts=async()=>{
let cart=[];
let subTotal=0;
let taxes=0;
const productsRef=collection(db, "carts");
const q=query(productsRef, where("userUID", "==", user?.uid));
const docs=await getDocs(q);
docs.forEach((doc)=>{
//cart.push(doc.data());
//subTotal+=doc.data().price;
console.log(doc.data());
cart=doc.data().products;
cart.forEach((product)=>{
subTotal+= product.quantity * product.price;
})
})
setCurrentProducts(cart);
setCartSubtotal(subTotal.toFixed(2));
}
const handleClose = (e) =>{
console.log('click');
setOpen(false);
};
const fetchUserCartItems=async()=>{
const q = query(collection(db, "carts"), where("userUID", "==", user?.uid));
const doc = await getDocs(q);
const data = doc.docs[0].data();
let cartItemsClone=data.cartItems;
setCartItems(cartItemsClone);
}
React.useEffect(() => {
fetchUserCartItems();
fetchProducts();
}, [user], []);
return (
<Container>
<Wrapper>
<Left>
<StyledLink to='/quiz'>QUIZ</StyledLink>
<StyledLink to='/products'>PRODUCTS</StyledLink>
<MenuItem>REVIEWS</MenuItem>
</Left>
<Center>
<Link to='/' style={{textDecoration:'none', color:'black'}}>
<Brand to="/">SKINCE</Brand>
</Link>
</Center>
<Right>
<MenuItem>ABOUT</MenuItem>
<StyledLink to='/login'>ACCOUNT</StyledLink>
<StyledLink to='/cart'>CART</StyledLink>
<MenuItemCart onClick={()=>handleOpen()}>
<Badge badgeContent={items} sx={{
"& .MuiBadge-badge": {
color: "#FFFFFF",
backgroundColor: "#D6C0B4"
}
}} ></Badge>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={{position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 700,
height: 700,
bgcolor: 'background.paper',
boxShadow: 24,
overflowY: 'initial !important',
p: 4,}}>
<button onClick={(e)=>handleClose(e)}>X</button>
<Typography id="modal-modal-title" variant="h6" component="h2" sx={{fontFamily:'Montserrat', textAlign:'center', paddingBottom:'10px'}}>
Your cart
</Typography>
{currentProducts.length==0 && (
<div style={{textAlign:'center', height:'50vh', paddingTop:'10%'}}>
<h2 > Your cart is empty! </h2>
<h2>Check our products and choose the right one for you.</h2>
</div>
)}
{currentProducts.length>0 && (
<MainContainer>
<LeftContainer>
<HeaderContainer>
{/* <h3>Your cart</h3> */}
<h5>{cartItems} items</h5>
</HeaderContainer>
<TableContainer sx={{paddingTop:'10px'}} >
<Table sx={{ minWidth: 700}} aria-label="simple table">
<TableBody>
{currentProducts.map((row, key)=>(
<TableRow sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
<TableCell sx={{width:'80px'}}>
<img src={row.img.url} style={{width:'100%', height:'100%'}} />
</TableCell>
<TableCell align='left' sx={{width:'80px', fontFamily:'Montserrat', fontSize:'12px'}}> {row.productName}
<h6>{row.productBrand}</h6></TableCell>
<TableCell align='right' sx={{fontFamily:'Montserrat', fontSize:'12px'}}>{row.size}</TableCell>
<TableCell align='center' sx={{fontFamily:'Montserrat'}}>
<Button>-</Button>
</TableCell>
<TableCell align='center' sx={{fontFamily:'Montserrat', fontSize:'12px'}}> {row.quantity}</TableCell>
<TableCell align='left' sx={{fontFamily:'Montserrat'}}>
<Button>+</Button>
</TableCell>
<TableCell align='right' sx={{fontFamily:'Montserrat', fontSize:'12px'}}>{row.price} €</TableCell>
<TableCell align='right' sx={{fontFamily:'Montserrat'}}>
<DeleteButton>X</DeleteButton>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</LeftContainer>
<Divider orientation="horizontal" flexItem/>
<HeaderContainer>
<h5>Subtotal</h5>
<h5 style={{paddingRight:'70px'}}>{cartSubTotal} € </h5>
</HeaderContainer>
</MainContainer>
)}
)
</Box>
</Modal>
<ShoppingCartOutlinedIcon/>
</MenuItemCart>
</Right>
</Wrapper>
</Container>
);
}
The video loader overrides the fixed bottom element, thus makes it quite unpleasant. I'am streaming the videos online and player used for it is React HLS player. What would be the best solution to prevent the overriding of loader. Following is the code reference
React HLS Player
<ReactHlsPlayer
url={video_url}
autoplay={false}
controls={true}
width="100%"
height="auto"
config={{
file: {
forceHLS: true,
}
}}
/>
Bottom Navbar Code
const useStyles = makeStyles({
root: {
width: "100%",
bottom: "0px",
position: "sticky"
},
gridList: {
flexWrap: "nowrap",
position: "fixed",
bottom: "0px",
background: "white",
border: "1px solid grey",
width: "100%"
}
});
<GridList className={classes.gridList}>
{itemList.map((tile, index) => {
return (
<GridListTile
key={tile.icon}
style={{ height: "70px", width: "25%" }}
>
<ListItem button key={tile.text}
onClick={(tile.text == "DirectLine") ? directLineFunc : ''}
>
<NavLink
exact
to={tile.link}
key={tile.key}
activeClassName="main-nav-active"
style={{ textAlign: "center" }}
isActive={(match, location) => {
match && setNewActiveLink(index)
return match;
}}
>
<ListItemText
disableTypography
primary={
<Typography
style={{
fontSize: "10px",
fontWeight: "bold",
fontFamily: "Nunito"
}}
>
{tile.text}
</Typography>
}
/>
</NavLink>
</ListItem>
</GridListTile>
);
})}
</GridList>
See the image below
And this the codesandbox link: https://codesandbox.io/s/react-material-forked-dtx6w
Finally I was able to sort out by adding 'zIndex:999' to gridList of BottomNavbar with the following changes in useStyles as:
const useStyles = makeStyles({
root: {
width: "100%",
bottom: "0px",
position: "sticky"
},
gridList: {
flexWrap: "nowrap",
position: "fixed",
bottom: "0px",
background: "white",
border: "1px solid grey",
width: "100%",
zIndex: 999 {/* <-- Here I added this and issue solved */}
}
});
I added a style={{marginBottom: "100px"}} property in the <ReactHlsPlayer /> and it seems to fix your problem
I'm using react-select autocomplete component for my react js web site. I just copied the example code in this link inside to a table cell, but it is not working properly as shown in the below image.
However, it individually works fine. Please help me with this issue. Here is the code.
Autocomplete.jsx has the same code as in the above link.
...
import Autocomplete from './Autocomplete.jsx';
...
const useStyles = makeStyles(theme => ({
textField: {
padding: theme.spacing(),
width: '100%',
},
}));
...
export default function Mapping(props) {
const classes = useStyles();
...
return (
<TableRow>
<TableCell>
<TextField
required
id='outlined-required'
label='URL pattern'
variant='outlined'
value={name}
onChange={event => setName(event.target.value)}
className={classes.textField}
/>
</TableCell>
<TableCell>
<Autocomplete arn={arn} setArn={setArn} />
</TableCell>
{resource.editable ?
<TableCell>
<Button onClick={saveResource}>Save</Button>
<Button onClick={cancel}>Cancel</Button>
</TableCell>
:
<TableCell>
<Button onClick={addResource}>Add</Button>
</TableCell>
}
</TableRow>
);
}
=========================================================================
...
import Mapping from './Mapping.jsx';
...
const useStyles = makeStyles(theme => ({
root: {
paddingBottom: theme.spacing(),
paddingTop: theme.spacing(),
width: '100%',
marginTop: theme.spacing(),
},
mappingsWrapper: {
padding: theme.spacing(),
borderRight: '#c4c4c4',
borderRightStyle: 'solid',
borderRightWidth: 'thin',
},
mappingsHeading: {
display: 'flex',
alignItems: 'center',
},
mappingsTitle: {
paddingLeft: theme.spacing(),
fontSize: '1rem',
paddingTop: theme.spacing(),
paddingBottom: theme.spacing(),
},
}));
...
export default function Mappings() {
const classes = useStyles();
...
return (
<Paper className={classes.root}>
<Grid container item xs={12}>
<Grid xs className={classes.mappingsWrapper}>
<div className={classes.mappingsHeading}>
<Typography className={classes.mappingsTitle}>
Mappings
</Typography>
</div>
<Table stickyHeader>
<TableHead>
<TableRow>
{columns.map(column => (
<TableCell
key={column.id}
align={column.align}
style={{ minWidth: column.minWidth }}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{resources.map((resource) => {
if (resource.editable) {
return (
<Mapping
resource={resource}
resources={resources}
setResources={setResources}
/>
);
} else {
return (
<TableRow>
<TableCell>{resource.name}</TableCell>
<TableCell>{resource.arn}</TableCell>
<TableCell>
<Button onClick={() => editResource(resource)}>Edit</Button>
<Button onClick={() => deleteResource(resource)}>Delete</Button>
</TableCell>
</TableRow>
);
}
})}
<Mapping
resource={{ name: '', arn: '', editable: false }}
resources={resources}
setResources={setResources}
/>
</TableBody>
</Table>
</Grid>
</Grid>
</Paper>
);
}