I am working on a React app using MaterialUI to create an Appbar and Drawer.
There is an extra space between the edge of the window and the Drawer.
The extra space is also covering up an IconButton I use to toggle opening and expanding the drawer. It looks like this:
Here's how I'm rendering the Appbar and Drawer:
render(){
const { classes,drawerOpen,theme } = this.props;
return(
<React.Fragment>
<AppBar
position="absolute"
className={classNames(classes.appBar,drawerOpen && classes.appBarShift)}
>
<Toolbar disableGutters={!this.state.open}>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={this.handleDrawerOpen}
className={classNames(classes.menuButton, drawerOpen && classes.hide)}
>
<ToggleLeft />
</IconButton>
<Typography variant="title" color="inherit" noWrap>
MYAPP
</Typography>
</Toolbar>
</AppBar>
<Drawer
variant="permanent"
classes={{
paper: classNames(classes.drawerPaper, !drawerOpen && classes.drawerPaperClose),
}}
open={this.state.open}
>
<div className={classes.toolbar}>
<IconButton onClick={this.handleDrawerClose}>
{theme.direction === 'rtl' ? <ToggleLeft />:<ToggleRight />}
</IconButton>
</div>
<Divider />
<List><SideAccountsList {...this.props}/></List>
</Drawer>
</React.Fragment>
)
}
Related
import React from "react";
import {
Card,
CardActions,
CardContent,
Button,
CardMedia,
Typography,
} from "#mui/material";
import ThumbUpAlt from "#mui/icons-material/ThumbUpAlt";
import Delete from "#mui/icons-material/Delete";
import MoreHoriz from "#mui/icons-material/MoreHoriz";
import moment from "moment";
import useStyles from "./styles";
const Post = ({ post }) => {
const classes = useStyles();
return (
<Card className={classes.card}>
<CardMedia
className={classes.media}
image={post.selectedFile}
title={post.title}
>
<div className={classes.overlay}>
<Typography variant="h6">{post.creator}</Typography>
<Typography variant="body2">
{moment(post.createdAt).fromNow()}
</Typography>
</div>
// till here the card is showing
<div className={classes.overlay2}>
<Button style={{ color: "white" }} size="small" onClick={() => {}}>
<MoreHoriz fontSize="default" />
</Button>
</div>
<div className={classes.details}>
<Typography variant="body2" color="textSecondary">
{post.tags.map((tag) => `#${tag}`)}
</Typography>
</div>
<CardContent>
<Typography className={classes.title} variant="h5" gutterBottom>
{post.message}
</Typography>
</CardContent>
<CardActions className={classes.cardActions}>
<Button size="small" color="primary" onClick={() => {}}>
<ThumbUpAlt fontSize="small" />
Like
{post.likeCount}
</Button>
<Button size="small" color="primary" onClick={() => {}}>
<Delete fontSize="small" />
Delete
</Button>
</CardActions>
</CardMedia>
</Card>
);
};
export default Post;
I'm passing data from parent to child as a prop.After this i'm mapping the prop in card.But the issue is card is only showing till classes.overlay afterwards nothing is showing.Also code is not showing in inspect.I don't know what the issue is as i'm new to MUI.
May i know what the issue is so that i can fix it
Is because you are wrapping your component inside the CardMedia tags, when it should be a self-closing tag, so your code should look like this:
const Post = ({ post }) => {
const classes = useStyles();
return (
<Card className={classes.card}>
<CardMedia
className={classes.media}
image={post.selectedFile}
title={post.title}
/> // <--- This is the change
<div className={classes.overlay}>
<Typography variant="h6">{post.creator}</Typography>
<Typography variant="body2">
{moment(post.createdAt).fromNow()}
</Typography>
</div>
<div className={classes.overlay2}>
<Button style={{ color: "white" }} size="small" onClick={() => {}}>
<MoreHoriz fontSize="default" />
</Button>
</div>
<div className={classes.details}>
<Typography variant="body2" color="textSecondary">
{post.tags.map((tag) => `#${tag}`)}
</Typography>
</div>
<CardContent>
<Typography className={classes.title} variant="h5" gutterBottom>
{post.message}
</Typography>
</CardContent>
<CardActions className={classes.cardActions}>
<Button size="small" color="primary" onClick={() => {}}>
<ThumbUpAlt fontSize="small" />
Like
{post.likeCount}
</Button>
<Button size="small" color="primary" onClick={() => {}}>
<Delete fontSize="small" />
Delete
</Button>
</CardActions>
</Card>
);
};
export default Post;
I am trying to write some classes for my code (typescript, material ui, react, electron).
In codeSandbox my code runs fine, however when I am trying to execute my code in the electron environment I get a white screen. Looking at the developer-tools I get the message:
"Uncaught TypeError: Cannot set property 'title' of undefined"
I am pretty sure that 'title' is defined (otherwise it wouldn't have worked on codeSandbox I guess).
Would be cool if someone could help me.
(if you need more of my code feel free to ask :))
...
export default function NestedGrid(this: any) {
...
class class_cards {
nameOfCard: string;
topic1: string;
content_topic1: string;
topic2: string;
content_topic2: string;
constructor(
nameOfCard: string,
topic1: string,
content_topic1: string,
topic2: string,
content_topic2: string
) {
this.nameOfCard = nameOfCard;
this.topic1 = topic1;
this.content_topic1 = content_topic1;
this.topic2 = topic2;
this.content_topic2 = content_topic2;}
public Cards()
{
//console.log(this); //ADD.L
return (
<Grid item xs={12}>
<Card className={classes.root} variant="outlined">
<CardContent>
<Typography
className={classes.title}
color="textSecondary"
gutterBottom
>
{/*!!! electron will only work properly if you write 'TITLE' instead of '{this.title}' !!! */}
{this.nameOfCard} {/* <----- 1st class element */}
</Typography>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography className={classes.root}>
Topic 1 {/* <----- 2nd class element |||||||||||| */}
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>Hello There</Typography> {/* |||||||| */}
</AccordionDetails>
</Accordion>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel2a-content"
id="panel2a-header"
>
<Typography className={classes.root}>
Topic 2 {/* |||||||| */}
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>1+1=2</Typography> {/* ||||||| */}
</AccordionDetails>
</Accordion>
</CardContent>
<CardActions>
<Button fullWidth={true}>
<IconButton size="small">
<Alert severity="info">LEARN MORE</Alert>
</IconButton>
</Button>
</CardActions>
{/*---------------------------------Full Screen----------------------------------*/}
<Button
variant="outlined"
color="primary"
onClick={handleClickOpen}
fullWidth={true}
>
Open full-screen
</Button>
<Dialog
fullScreen
open={open}
onClose={handleClickClose}
TransitionComponent={Transition}
>
<AppBar className={classes.appBar}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={handleClickClose}
aria-label="close"
>
<CloseIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
Title
</Typography>
</Toolbar>
</AppBar>
<List>
<ListItem button>
<ListItemText primary="Phone ringtone" secondary="Titania" />
</ListItem>
<Divider />
<ListItem button>
<ListItemText
primary="Default notification ringtone"
secondary="Tethys"
/>
</ListItem>
</List>
</Dialog>
{/*--------------------------------Full Screen-----------------------------------*/}
</Card>
</Grid>
);
}
}
//let crd = new class_cards('TITLE', 'TOPIC1', 'HELLO', 'TOPIC2', 'BYE');
// ? crd1 gets the same values as crd3 ?
const crd1 = new class_cards(this.nameOfCard='Card 1', this.topic1='TOPIC 1', this.content_topic1='HELLO', this.topic2='TOPIC 2', this.content_topic2='BYE');
const crd3 = new class_cards(this.nameOfCard='Card 3', this.topic1='TOPIC 1', this.content_topic1='HELLO', this.topic2='TOPIC 2', this.content_topic2='BYE');
return (
<div className={classes.root}>
...
<crd1.Cards />
<crd3.Cards />
...
electron will only work properly if you write 'TITLE' instead of '{this.title}
seems to me you may have to declare 'TITLE' in all caps
If I have an AppBar, how can I make it so one group of icons plus the logo is on the left, and another group of icons are on the right of it?
Ex:
Left: (from left to right) 1 menu icon, logo
Right: (from right to left) 1 menu icon, 1 save icon, 1 edit icon
AppBar component:
<AppBar
className={classNames(classes.appBar, {
[classes.appBarShift]: open,
[classes[`appBarShift-left`]]: open,
[classes[`appBarShift-right`]]: !tools,
})}
position='static'
>
<Toolbar className={classNames(classes.topBar)}>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={this.handleDrawerToggle}
className={classNames(classes.menuButton)}
>
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit" noWrap>React App</Typography>
<IconButton
color="inherit"
aria-label="open tool drawer"
onClick={this.handleToolDrawerToggle}
className={classNames(classes.menuButton)}
>
<MenuIcon />
</IconButton>
</Toolbar>
</AppBar>
You can use flexbox to control the alignment of elements in the toolbar...
One option is to add flex: 1 to the logo element. It will expand to fill the available space in container. All the elements after logo will be aligned to the right.
OR
Use margin-left: auto to align the second group of buttons to the right side of the flex container.
Here is a live example
const styles = {
// this group of buttons will be aligned to the right side
toolbarButtons: {
marginLeft: 'auto',
},
};
const Demo = ({ classes }) => (
<AppBar position="static">
<Toolbar>
<IconButton color="inherit">
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit">Title</Typography>
<div className={classes.toolbarButtons}>
<IconButton color="inherit"><EditIcon /></IconButton>
<IconButton color="inherit"><SaveIcon /></IconButton>
<IconButton color="inherit"><MoreVertIcon /></IconButton>
</div>
</Toolbar>
</AppBar>
);
I know it's been a while since you asked the question, I would like to provide an alternative solution. Add Box tag (similar to flexbox in CSS) around the components on the left and adjust the flexGrow attribute and it works for me:
import Box from '#material-ui/core/Box';
{/* BEFORE APPBAR*/}
<AppBar>
<Toolbar>
<Box display='flex' flexGrow={1}>
{/* whatever is on the left side */}
</Box>
{/* whatever is on the right side */}
</Toolbar>
</AppBar>
{/* AFTER APPBAR*/}
I tried using inline css inside Toolbar component itself, it worked for me;
<Toolbar style={{display:'flex', justifyContent:"space-between", width:'100%'}}>
In this menuAppBar the first item in the menu is selected by default. Where in this menu the first item is not selected by default, and that what I want is the same to be in the manuAppBar menu.
The first example is implemented with the material-ui Menu component and the second example is implemented using components from the react-popper library.
In the first example, the first item is highlighted because it has focus. This is because Menu sets focus if it is open when mounted or updated. Take a look at the source:
class Menu extends React.Component {
componentDidMount() {
if (this.props.open) {
this.focus();
}
}
componentDidUpdate(prevProps) {
if (!prevProps.open && this.props.open) {
// Needs to refocus as when a menu is rendered into another Modal,
// the first modal might change the focus to prevent any leak.
this.focus();
}
}
If you prefer react-popper and would like to use it in an AppBar, you can:
<AppBar position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="contrast" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography type="title" color="inherit" className={classes.flex}>
Title
</Typography>
{auth && (
<Manager>
<Target>
<IconButton
aria-owns={open ? 'menu-list' : null}
aria-haspopup="true"
onClick={this.handleMenu}
color="contrast"
>
<AccountCircle />
</IconButton>
</Target>
<Popper
placement="top-right"
eventsEnabled={open}
className={classNames({ [classes.popperClose]: !open })}
>
<ClickAwayListener onClickAway={this.handleClose}>
<Grow in={open} id="menu-list" style={{ transformOrigin: '0 0 0' }}>
<Paper>
<MenuList role="menu">
<MenuItem onClick={this.handleClose}>Profile</MenuItem>
<MenuItem onClick={this.handleClose}>My account</MenuItem>
<MenuItem onClick={this.handleClose}>Logout</MenuItem>
</MenuList>
</Paper>
</Grow>
</ClickAwayListener>
</Popper>
</Manager>
)}
</Toolbar>
</AppBar>
Here is a mashup of your two cited examples on codesandbox. It needs work and was only added here to illustrate react-popper as a possibility.
<AppBar title="My AppBar" showMenuIconButton={false} />
This Hides the Menu Icon in all devices.
I need to hide only in Desktop.
How Can I achieve this?
You can try this-
showMenuIconButton={window.screen.width.<600? true:false}
where 600 is 600 pixels.
You can subscribe to resize event listener:
import React, { useState, useEffect } from 'react'
const Events = () => {
const [windowWidth, setWindowWidth] = useState(window.innerWidth)
useEffect(() => {
function handleResize() {
setWindowWidth(window.innerWidth)
}
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
return (
<div>
<AppBar title="My AppBar" showMenuIconButton={windowWidth < 600} />
</div>
)
you can use sx prop attribute for responsive style.
sx={{ mr: 2, display: {sm: 'none'} }}
<IconButton
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2, display: {sm: 'none'} }}
>
<MenuIcon />
</IconButton>
AppBar should look like,
<Box sx={{display: 'flex'}}>
<CssBaseline />
<AppBar
position="fixed"
elevation={1}
>
<Toolbar variant="dense">
<IconButton
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2, display: {sm: 'none'} }}
onClick={this.handleDrawerToggle}>
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" component="div">
Logo
</Typography>
</Toolbar>
</AppBar>
<LeftSideBar
handleDrawerToggle={this.handleDrawerToggle}
mobileOpen={this.state.mobileOpen}
/>
</Box>