How to split material-ui toolbar into left and right part. For example, this is my toolbar
let EnhancedTableToolbar = props => {
const { numSelected, classes ,deletefunc} = props;
return (
<Toolbar
className={classNames(classes.root, {
[classes.highlight]: numSelected > 0,
})}
>
<div className={classes.title}>
{numSelected > 0 ? (
<Typography color="inherit" variant="subtitle1">
{numSelected} selected
</Typography>
) : (
<Typography variant="h6" id="tableTitle">
User List
</Typography>
)}
</div>
<div className={classes.actions}>
{numSelected > 0 ? (
<div >
<div style={{ display: 'inline-block' }}>
<Tooltip title="Delete">
<IconButton aria-label="Delete">
<DeleteIcon onClick={() => { if (window.confirm('Are you sure you wish to delete '+numSelected +' item?')) {deletefunc()} } }>
</DeleteIcon>
</IconButton>
</Tooltip>
</div>
<div style={{ display: 'inline-block' }}>
<Tooltip title="Edit">
<IconButton aria-label="Edit">
<EditIcon>
</EditIcon>
</IconButton>
</Tooltip>
</div>
</div>
) : (
<Tooltip title="Filter list">
<IconButton aria-label="Filter list">
<FilterListIcon />
</IconButton>
</Tooltip>
)}
</div>
</Toolbar>
);
};
I want to show the numSelected in my left side of toolbar and the delete button and edit button at my right side of toolbar. However, my example output show the delete button and edit button just beside the numSelected. Anyone has any solution regarding this issue?
The solution is add
flex: '0 0 auto'
in my actions class and a
<div className={classes.spacer}>
between title class and action class.
This is how I setup spacer, title and action classes.
const toolbarStyles = theme => ({
root: {
paddingRight: theme.spacing.unit,
},
highlight:
theme.palette.type === 'light'
? {
color: theme.palette.secondary.main,
backgroundColor: lighten(theme.palette.secondary.light, 0.85),
}
: {
color: theme.palette.text.primary,
backgroundColor: theme.palette.secondary.dark,
},
spacer: {
flex: '1 1 100%',
},
actions: {
color: theme.palette.text.secondary,
flex: '0 0 auto',
},
title: {
flex: '0 0 auto',
},
});
Related
I'm currently trying to build a website using react for my web development class, which is my first foray into JS and React. I'm using a Material UI appbar for my header. I've used react router in one of my class examples so I've set that up and my app bar is displaying as intended. My question is, how do I set the buttons on the appbar/header to link to my pages? The default code (minus imports) provided by Material UI is below with my placeholder page names added.
const pages = ['Utility List', 'Register', 'Login'];
const settings = ['Profile', 'Account', 'Logout'];
const Header = () => {
const [anchorElNav, setAnchorElNav] = React.useState(null);
const [anchorElUser, setAnchorElUser] = React.useState(null);
const handleOpenNavMenu = (event) => {
setAnchorElNav(event.currentTarget);
};
const handleOpenUserMenu = (event) => {
setAnchorElUser(event.currentTarget);
};
const handleCloseNavMenu = () => {
setAnchorElNav(null);
};
const handleCloseUserMenu = () => {
setAnchorElUser(null);
};
return (
<AppBar position="static">
<Container maxWidth="xl">
<Toolbar disableGutters>
<Typography
variant="h6"
noWrap
component="div"
sx={{ mr: 2, display: { xs: 'none', md: 'flex' } }}
>
LOGO
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleOpenNavMenu}
color="inherit"
>
<MenuIcon />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorElNav}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
open={Boolean(anchorElNav)}
onClose={handleCloseNavMenu}
sx={{
display: { xs: 'block', md: 'none' },
}}
>
{pages.map((page) => (
<MenuItem key={page} onClick={handleCloseNavMenu}>
<Typography textAlign="center">{page}</Typography>
</MenuItem>
))}
</Menu>
</Box>
<Typography
variant="h6"
noWrap
component="div"
sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}
>
LOGO
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
{pages.map((page) => (
<Button
key={page}
onClick={handleCloseNavMenu}
sx={{ my: 2, color: 'white', display: 'block' }}
>
{page}
</Button>
))}
</Box>
<Box sx={{ flexGrow: 0 }}>
<Tooltip title="Open settings">
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
<Avatar alt="Remy Sharp" src="/static/images/avatar/2.jpg" />
</IconButton>
</Tooltip>
<Menu
sx={{ mt: '45px' }}
id="menu-appbar"
anchorEl={anchorElUser}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu}
>
{settings.map((setting) => (
<MenuItem key={setting} onClick={handleCloseUserMenu}>
<Typography textAlign="center">{setting}</Typography>
</MenuItem>
))}
</Menu>
</Box>
</Toolbar>
</Container>
</AppBar>
);
};
export default Header;
Find the place in your code where your navbar links are added to JSX. Wrap each link in Link component from react-router
const yourPages = [
{ text: 'Home', href: '/' },
{ text: 'About', href: '/about' }
]
// inside return statement
{yourPages.map((page) => (
<Link href={page.href}>{page.text}</Link
)}
...
Hello I want to know how do you change the zAxis of a paper from MUI
As you can see the carousel overlaps my menu and I would like my menu to be on top of everything.
This is how I have it wrapped:
<Box sx={{ background: '#272A31', flexGrow: 0, display: { xs: 'none', md: 'flex' } }}>
<StyledIconButton size="small" edge="start" color="inherit" aria-label="menu" sx={{ mr: 2 }} onClick={handleToggle} ref={anchorRef} >
<GamesIcon />
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}> GAMES </Typography>
<Popper open={open} anchorEl={anchorRef.current} role={undefined} placement="bottom-start" transition disablePortal >
{({ TransitionProps, placement }) => (
<Grow {...TransitionProps}
style={{
transformOrigin: placement === 'bottom-start' ? 'left top' : 'left bottom',
}}
>
<StyledPaper sx = {{zIndex: 1600}} >
<ClickAwayListener onClickAway={handleClose}>
<MenuList autoFocusItem={open} id="composition-menu" aria-labelledby="composition-button" onKeyDown={handleListKeyDown}>
<StyledMenuItem onClick={handleClose}>JUNGLE RAIDER</StyledMenuItem>
<StyledMenuItem onClick={handleClose}>MEGAMAN TEMPLATE</StyledMenuItem>
<StyledMenuItem onClick={handleClose}>TOWER DEFENSE</StyledMenuItem>
<StyledMenuItem onClick={handleClose}>BLADES AND DUNGEON</StyledMenuItem>
<StyledMenuItem onClick={handleClose}>FIXSPACE</StyledMenuItem>
</MenuList>
</ClickAwayListener>
</StyledPaper>
</Grow>
)}
</Popper>
</StyledIconButton>
</Box>
While my Carousel is wraped in the following way:
<Box mb = {2} mt = {2} sx={{display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: -1}}>
<Card sx={{ width: 1500, backgroundColor: "transparent"}} >
<Carousel fullHeightHover={false} navButtonsAlwaysVisible={true} duration={500} animation="slide"
navButtonsProps={{
style: {
backgroundColor: '#FF5917',
borderRadius: 0,
}
}} >
{items.map( (item, i) => <Item key={i} item={item} />)}
</Carousel>
</Card>
</Box>
Even though the paper is at z-(1600) and the carousel box at z-(-1) it still overlaps the paper for some reason
https://mui.com/customization/z-index/ check this link. tooptip has highest zindex value. you can add it to your popper
So, there is a similar question on Stack Overflow, but that's not what I need. I want to make a regular full width footer at the bottom of the page. Here is the code for it, borrowed straight from Material-UI Drawer. Whatever I try to add here, I can't make my footer to appear at all. Once I managed to make it appear but it still was under the drawer, so I could only see a part of it to the right of the drawer.
const drawerWidth = 240;
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: 'flex',
},
appBar: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
},
drawer: {
width: drawerWidth,
flexShrink: 0,
},
drawerPaper: {
width: drawerWidth,
},
// necessary for content to be below app bar
toolbar: theme.mixins.toolbar,
content: {
flexGrow: 1,
backgroundColor: theme.palette.background.default,
padding: theme.spacing(3),
},
}),
);
export default function PermanentDrawerLeft() {
const classes = useStyles();
return (
<div className={classes.root}>
<CssBaseline />
<AppBar position="fixed" className={classes.appBar}>
<Toolbar>
<Typography variant="h6" noWrap>
Permanent drawer
</Typography>
</Toolbar>
</AppBar>
<Drawer
className={classes.drawer}
variant="permanent"
classes={{
paper: classes.drawerPaper,
}}
anchor="left"
>
<div className={classes.toolbar} />
<Divider />
<List>
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{['All mail', 'Trash', 'Spam'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</Drawer>
<main className={classes.content}>
<div className={classes.toolbar} />
<Typography paragraph>
Text
</Typography>
<Typography paragraph>
Text
</Typography>
</main>
</div>
);
}
I'm stuck on writing out logic that will show more comments if user clicks show more comments.
How would i go about performing this logic that filters based on the following: initially there are 2 comments that show(out of 7 total comments). I want to break this down as user keeps clicking on show more. Should show 5 more comments, 3 more comments, 1 more comment, until there is no more comments.
I'm not too sure on what im doing.
CommentList.tsx
import React, { Fragment, useState } from "react";
import Grid from "#material-ui/core/Grid";
import List from "#material-ui/core/List";
import Typography from "#material-ui/core/Typography";
import CommentItem from "./../commentItem/CommentItem";
import moment from "moment";
import OurLink from "../../../common/OurLink";
import OurSecondaryButton from "../../../common/OurSecondaryButton";
import OurModal from "../../../common/OurModal";
const ourStyle = {
backgroundColor: "#FAFAFA",
border: "1px solid #f2f2f2",
borderRadius: "4px",
padding: "15px 20px",
margin: "15px",
};
function CommentList(props: any) {
const [showMore, setShowMore] = useState<Number>(2);
const [openModal, setOpenModal] = useState(false);
const [showLessFlag, setShowLessFlag] = useState<Boolean>(false);
const lastIndexOfComments = props.comments.length - 1;
const startIndex = 0;
console.log(lastIndexOfComments);
const showComments = (e) => {
e.preventDefault();
const subtract = props.comments.length - 2 ;
console.log("testing", subtract);
setShowMore(subtract);
// setShowLessFlag(true);
};
const handleClickOpen = () => {
setOpenModal(true);
};
const handleCloseModal = () => {
setOpenModal(false);
};
.....
const showMoreComments = () => {
return props.comments
.slice(startIndex, showMore)
.sort((a, b) => a.id - b.id)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ cursor: "pointer", fontSize: "12px", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
</span>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
));
};
const ourComments = props.comments;
console.log("before comments", ourComments);
console.log("fsfsfsftestingcomments", ourComments.slice(0, showMore));
return (
<Grid>
<Fragment>
<div style={{ margin: "30px 0px" }}>
<OurSecondaryButton onClick={(e) => showComments(e)} component="span" color="secondary">
View More Comments
</OurSecondaryButton>
</div>
</Fragment>
{showLessFlag === true ? (
// will show most recent comments below
showMoreComments()
) : (
<Fragment>
{/* filter based on first comment */}
{props.comments
.filter((item, i) => item)
.sort((a, b) => b.id - a.id)
.slice(startIndex, showMore)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ fontSize: "12px", cursor: "pointer", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</span>
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
))}
</Fragment>
)}
</Grid>
);
}
// prevents un-necesary re renders
export default React.memo(CommentList);
If you have all comments already fetched, you could simply set a limit and only show the comments with an index lower than the limit.
Check this out: https://stackoverflow.com/a/44071932/10955418
I'm using React and Material UI in order to show some mapped cards mapped. When I try to expand a card, all the cards are expanded at the same time. I figured out that I have to pass an index inside my "handleExpandClick" function, but still not working. Maybe I did it some kind of typo.
I found this question Expand one card on click that regards the same problem, but seems not to be applied to my situation.
Here my piece of code:
const useStyles = makeStyles(theme => ({
card: {
maxWidth: 345,
marginBottom: 15
},
media: {
height: 0,
paddingTop: "56.25%" // 16:9
},
expand: {
transform: "rotate(0deg)",
marginLeft: "auto",
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.shortest
})
},
expandOpen: {
transform: "rotate(180deg)"
},
avatar: {
width: 90
},
root: {
display: "flex",
justifyContent: "center",
flexWrap: "wrap",
"& > *": {
margin: theme.spacing(0.5)
}
},
list: {
width: 200
}
}));
const ItininerariesList = ({ itineraries, activities }) => {
const classes = useStyles();
const [expanded, setExpanded] = React.useState(false);
let path = window.location.pathname;
let currentId = path.substring(path.lastIndexOf("/") + 1);
const itinerariesPerCity = itineraries.filter(
itiner => itiner.city_id === currentId
);
const handleExpandClick = () => {
setExpanded(!expanded);
};
return (
<Fragment>
{itinerariesPerCity.map((itinerary, i) => (
<Card className={classes.card} key={itinerary._id}>
<CardHeader
avatar={
<Grid
container
direction="column"
justify="flex-start"
alignItems="center"
className={classes.avatar}
>
<Avatar
aria-label="user"
alt={itinerary.profile_name}
src={itinerary.profile_img}
>
<PersonIcon />
</Avatar>
<Typography variant="caption" component="p">
{itinerary.profile_name}
</Typography>
</Grid>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={itinerary.title}
subheader={itinerary.sub_title}
/>
<CardContent>
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<FavoriteIcon />
</IconButton>
<IconButton aria-label="share">
<ShareIcon />
</IconButton>
<IconButton
className={clsx(classes.expand, {
[classes.expandOpen]: expanded
})}
onClick={() => handleExpandClick()}
aria-expanded={expanded}
aria-label="show more"
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
<ActivitiesList
activities={activities}
itineraryId={itinerary._id}
/>
</CardContent>
</Collapse>
</Card>
))}
</Fragment>
);
};
export default ItininerariesList;
Any suggestions or guidance would be greatly appreciated. Thank you in advance.
In the expand handler you indeed have to pass the index. And also use it in the state.
Something like it:
const [expandedId, setExpandedId] = React.useState(-1);
...
const handleExpandClick = (i) => {
setExpandedId(expandedId === i ? -1 : i);
};
...
<CardContent />
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<FavoriteIcon />
</IconButton>
<IconButton aria-label="share">
<ShareIcon />
</IconButton>
<IconButton
onClick={() => handleExpandClick(i)}
aria-expanded={expandedId === i}
aria-label="show more"
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={expandedId === i} timeout="auto" unmountOnExit>
<CardContent>
<div>ActivitiesList</div>
</CardContent>
</Collapse>
Here is a working example: https://codesandbox.io/s/eloquent-sara-wswrn