Material-UI: Prevent Accordion summary vertical movement - css

Created this accordion and will use it as a menu item.
However, when I click Main title, accordion summary moves vertically downward.
How can I keep Main tile fixed while opening?
sandbox
import React from "react";
import {
Typography,
Grid,
Accordion,
AccordionSummary,
AccordionDetails,
ListItem
} from "#material-ui/core";
import { createStyles, makeStyles, Theme } from "#material-ui/core/styles";
import ExpandMoreIcon from "#material-ui/icons/ExpandMore";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
panelSummary: {
flexDirection: "row-reverse",
paddingLeft: "0px"
},
heading: {
fontSize: theme.typography.pxToRem(15),
fontWeight: theme.typography.fontWeightRegular
},
innerMenuItem: {
paddingLeft: "32px"
},
expanded: {
padding: "0px"
}
})
);
export default function App() {
const classes = useStyles();
return (
<Accordion>
<AccordionSummary
className={classes.panelSummary}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography className={classes.heading}>Main title</Typography>
</AccordionSummary>
<AccordionDetails>
<Grid container direction="column">
<ListItem className={classes.innerMenuItem} button key={1}>
<Typography className={classes.heading}>Sub Item 1</Typography>
</ListItem>
<ListItem
className={classes.innerMenuItem}
button
key={2}>
<Typography className={classes.heading}>Sub Item 2</Typography>
</ListItem>
</Grid>
</AccordionDetails>
</Accordion>
);
}

You can just pass in disableGutters as true in version 5 of mui
<Accordion disableGutters>
// ....
</Accordion>

When expanded, the summary's vertical margin is set to some value, you need to reset it if you don't want to see the summary size changes during the expansion:
V5
<AccordionSummary
sx={{
"&.Mui-expanded": {
minHeight: 0
},
"& .MuiAccordionSummary-content.Mui-expanded": {
// margin from https://github.com/mui-org/material-ui/blob/cc0e2ab63e8be9ec4d51a49bfde17ef28fc77b9c/packages/mui-material/src/AccordionSummary/AccordionSummary.js#L64-L64
margin: "12px 0"
}
}}
>
V4
panelSummary: {
"&.Mui-expanded": {
minHeight: 0
},
"& .MuiAccordionSummary-content.Mui-expanded": {
margin: "auto"
}
},

Related

React JSX background position not placing image to center right in Material UI Grid item

I've just created a one page website portfolio and it is pretty much complete, but having issues with setting the background position of the home screen to center right. Here is my site:
https://berkley-portfolio.netlify.app/
My repo: https://github.com/Bolmstead/Portfolio
I just want the image of me to appear when resizing the window to mobile. I believe background-position would fix this right? The background size is cover, and I believe I am doing it correctly, but seem to be missing something. Below is my home component:
import React, { useEffect } from "react";
import Grid from "#material-ui/core/Grid";
import Typography from "#material-ui/core/Typography";
import { makeStyles } from "#material-ui/core/styles";
import Container from "#material-ui/core/Container";
const useStyles = makeStyles((theme) => ({
homeContainer: {
backgroundImage: `url(/images/home2.jpg)`,
height: "103vh",
backgroundSize: "cover",
backgoundPosition: "center right"
},
overlay: {
zIndex: 1,
height: "100%",
width: "100%",
backgroundSize: "cover",
background: "rgba(0, 0, 0, 0.5)",
},
firstName: {
fontWeight: "bold",
color: "white"
},
lastName: {
fontWeight: "bold",
color: "#FFC220"
},
caption: {
fontWeight: "bold",
color: "white"
},
}));
export default function Home() {
const classes = useStyles();
const [fadedIn, setFadedIn] = React.useState(false);
useEffect(() => {
async function fadeInHomeScreen() {
setFadedIn((prev) => !prev);
}
fadeInHomeScreen();
}, []);
return (
<Grid item xs={12} className={classes.homeContainer}>
<a id="Home">
<Grid
container
alignItems="center"
justify="center"
direction="row"
className={classes.overlay}
>
<Grid item xs={12} align="center" justify="center">
<Container maxWidth="md" align="center" justify="center" className={classes.container}>
<Typography
m={12}
variant="h2"
component="h2"
className={classes.firstName}
display="inline"
>
Berkley{" "}
</Typography>
<Typography
m={12}
variant="h2"
component="h2"
className={classes.lastName}
display="inline"
>
Olmstead
</Typography>
<Typography
m={12}
variant="h6"
component="h6"
className={classes.caption}
>
I'm a Full-Stack Developer
</Typography>
</Container>
</Grid>
</Grid>
</a>
</Grid>
);
}
You have a typo, backgoundPosition should be backgroundPosition
homeContainer: {
backgroundImage: `url(/images/home2.jpg)`,
height: "103vh",
backgroundSize: "cover",
backgroundPosition: "center right"
},

How to move Icons in Material UI

How can I move my components on the image by using material UI ? I want to move my heart component to the top right corner of my image and ratings on the bottom of my image.
import image from "../../Assets/pic.jpg";
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
import CardActionArea from "#material-ui/core/CardActionArea";
import FavoriteBorderIcon from "#material-ui/icons/FavoriteBorder";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import Typography from "#material-ui/core/Typography";
import Grid from "#material-ui/core/Grid";
import styles from "./Cards.module.css";
import Stars from "../Stars/Stars";
const useStyles = makeStyles({
root: {
maxWidth: 345,
display: "flex",
},
text: {
textAlign: "center",
color: "#333333",
},
textCardBottom: {
display: "flex",
justifyContent: "center",
},
textPrice: { color: "#333333" },
textStrike: { margin: "0px 10px 0px 10px" },
textDiscount: { color: "#ff6a6a" },
stars: {
right: 9,
},
ratings: {},
});
const Cards = () => {
const [showComponent, setShowComponent] = useState(false);
const classes = useStyles();
const handleToggleHoverIn = (event) => {
event.preventDefault();
setShowComponent(true);
};
const handleToggleHoverOut = (event) => {
event.preventDefault();
setShowComponent(false);
};
console.log("The state showComponent value is ", showComponent);
return (
<Card
onMouseEnter={handleToggleHoverIn}
onMouseLeave={handleToggleHoverOut}
className={classes.root}
>
<CardActionArea>
<CardMedia
component="img"
alt=""
image={image}
title="Contemplative Reptile"
/>
{/* {showComponent ? ( */}
<Grid container>
<Stars right="40%" /> // want this rating component on the centre of my image
<FavoriteBorderIcon fontSize="large" /> // want this heart to the top right corner
</Grid>
{/* ) : null} */}
<CardContent>
<Typography
gutterBottom
variant="h5"
component="h2"
className={classes.text}
>
Printed round Neck
</Typography>
<Typography
variant="body2"
color="textSecondary"
component="div"
className={classes.textCardBottom}
>
<Typography
variant="body2"
color="textSecondary"
component="b"
className={classes.textPrice}
>
Rs. 454
</Typography>
<Typography
variant="body2"
color="textSecondary"
component="strike"
className={classes.textStrike}
>
Rs. 699
</Typography>
<Typography
variant="body2"
color="textSecondary"
component="span"
className={classes.textDiscount}
>
(35 % off)
</Typography>
{/* <p>
<b>Rs. 454</b>
<strike>Rs. 699</strike>
<span style={{ color: "#FF7F7F" }}> (35 % off) </span>
</p> */}
</Typography>
</CardContent>
</CardActionArea>
</Card>
);
};
export default Cards;
I tried to use the position property of material UI but I wasn't able to move the components. I tried the Material UI docs but couldn't find properties that could help me moving the components.
did you tried to add inline styles like this:
<FavoriteBorderIcon fontSize="large" style={{ position: "absolute", top: "5px", right: "5px" }}/>
<Stars right="40%" style={{ position: "absolute", bottom: "5px" }}/>
and perhaps you need also add some position to Grid as well
<Grid style={{ position: "relative" }}>

How to increase the vertical spacing between a Material UI FormLabel and Slider?

I'm working on a map with an image overlay that has adjustable opacity. Here is the component code:
import React from 'react'
import PropTypes from 'prop-types'
import { MapWithGroundOverlay } from './MapWithGroundOverlay'
import { withStyles } from '#material-ui/core/styles'
import Box from '#material-ui/core/Box'
import FormLabel from '#material-ui/core/FormLabel'
import Slider from '#material-ui/lab/Slider'
import Grid from '#material-ui/core/Grid'
import Paper from '#material-ui/core/Paper'
const styles = theme => ({
root: {
flexGrow: 1,
},
paper: {
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
},
label: {
padding: theme.spacing(3),
}
})
class AdjustableGroundoverlay extends React.PureComponent {
constructor(props, context) {
super(props, context)
this.state = {opacity: 0.5}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event, value) {
this.setState(state => ({
opacity: value
}));
}
render() {
return (
<Grid container className={this.props.classes.root} spacing={2}>
<Grid item xs={12}>
<MapWithGroundOverlay
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_API_KEY}&v=3.exp&libraries=geometry,drawing,places`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `600px` }} />}
mapElement={<div style={{ height: `100%` }} />}
opacity={this.state.opacity}
/>
</Grid>
<Grid item xs={6}>
<Paper className={this.props.classes.paper}>
<Box flexDirection="column">
<FormLabel className={this.props.classes.label}>Overlay opacity</FormLabel>
<Slider
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
</Box>
</Paper>
</Grid>
</Grid>
);
}
}
AdjustableGroundoverlay.propTypes = {
classes: PropTypes.object.isRequired,
}
export default withStyles(styles)(AdjustableGroundoverlay)
The problem is that the FormLabel and Slider are too close together. If I hover over them, I see that the Slider has a negative margin of -24px:
It seems like the content of the FormLabel therefore sits directly on top of it:
I've tried to change the styling of the Slider by adding these classes to the component in accordance with https://material-ui.com/api/slider/#css:
<Slider
classes={{container: {marginTop: -12}}}
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
but the spacing between the FormLabel and the Slider remains the same. Any idea what is wrong with this implementation?
Update
I've noticed in the console that there is this error:
I'm not sure why the key 'container' is not valid though since it is mentioned in https://material-ui.com/api/slider/#css.
I resolved this by putting the slider in a Box with mt set to 1:
<Paper className={this.props.classes.paper}>
<Box flexDirection="column">
<FormLabel className={this.props.classes.label}>Overlay opacity</FormLabel>
<Box mt={1}>
<Slider
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
</Box>
</Box>
</Paper>
Now there is more spacing between the label and the slider:

How to change the position of an Icon component, within a Tab component?

I'm using MaterialUI's tabs in my React project.
This is the JSX for the tabs:
<AppBar color="default" position="static">
<Tabs indicatorColor="primary" textColor="primary" value={tabIndex} onChange={this.handleChange}>
{instances.map(instance =>
<StyledTab
style={{ textTransform: 'initial' }}
onClick={() => { this.changeActiveInstance(instance.id) }}
label={this.getTabAddress(instance)}
icon={<ClearIcon ></ClearIcon>}
>
</StyledTab>
)}
</Tabs>
This is how i inject the css:
const StyledTab = withStyles({
root: {
textTransform: 'initial'
},
})(Tab);
The result is this:
I would like to position the "ClearIcon" elsewhere. I tried playing with the style injection a bit, with no success.
Can somebody point me to the right direction?
When trying to customize any Material-UI component, the starting point is the CSS portion of the API documentation. The most relevant classes that you may want to override in this case are wrapper, labelContainer, and label.
The best way to fully understand how these are used and how they are styled by default (and therefore what you may want to override) is to look at the source code.
Here are the most relevant portions of the styles from Tab.js:
/* Styles applied to the `icon` and `label`'s wrapper element. */
wrapper: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
flexDirection: 'column',
},
/* Styles applied to the label container element if `label` is provided. */
labelContainer: {
width: '100%', // Fix an IE 11 issue
boxSizing: 'border-box',
padding: '6px 12px',
[theme.breakpoints.up('md')]: {
padding: '6px 24px',
},
},
And here is the relevant code for understanding how these are used:
if (labelProp !== undefined) {
label = (
<span className={classes.labelContainer}>
<span
className={classNames(classes.label, {
[classes.labelWrapped]: this.state.labelWrapped,
})}
ref={ref => {
this.labelRef = ref;
}}
>
{labelProp}
</span>
</span>
);
}
<span className={classes.wrapper}>
{icon}
{label}
</span>
Below are some examples of possible ways to customize this.
import React from "react";
import PropTypes from "prop-types";
import Paper from "#material-ui/core/Paper";
import { withStyles } from "#material-ui/core/styles";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
import PhoneIcon from "#material-ui/icons/Phone";
import FavoriteIcon from "#material-ui/icons/Favorite";
import PersonPinIcon from "#material-ui/icons/PersonPin";
const styles = {
root: {
flexGrow: 1,
maxWidth: 700
},
firstIcon: {
paddingLeft: 70
},
labelContainer: {
width: "auto",
padding: 0
},
iconLabelWrapper: {
flexDirection: "row"
},
iconLabelWrapper2: {
flexDirection: "row-reverse"
}
};
class IconLabelTabs extends React.Component {
state = {
value: 0
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
return (
<Paper square className={classes.root}>
<Tabs
value={this.state.value}
onChange={this.handleChange}
variant="fullWidth"
indicatorColor="secondary"
textColor="secondary"
>
<Tab
icon={<PhoneIcon className={classes.firstIcon} />}
label="Class On Icon"
/>
<Tab
classes={{
wrapper: classes.iconLabelWrapper,
labelContainer: classes.labelContainer
}}
icon={<FavoriteIcon />}
label="Row"
/>
<Tab
classes={{
wrapper: classes.iconLabelWrapper2,
labelContainer: classes.labelContainer
}}
icon={<PersonPinIcon />}
label="Row-Reverse"
/>
<Tab icon={<PersonPinIcon />} label="Default" />
</Tabs>
</Paper>
);
}
}
IconLabelTabs.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(IconLabelTabs);
We have a inbuilt property to set the icon position of tab in material ui. Document link
iconPosition:'bottom' | 'end' | 'start' | 'top'

Material-UI Typography doesn't center in AppBar

I'm trying center the text in an AppBar. I've tried centering the text in Typography element, using align="center", textAlign="center", and style={{ align: "center" }}, among others:
class App extends React.Component {
render() {
return (
<div>
<AppBar>
<Toolbar>
<Typography
variant="h6"
color="inherit"
style={{ align: "center" }}
>
Header
</Typography>
</Toolbar>
</AppBar>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
... but is doesn't work unless I remove the Toolbar. But then I would have to manually change the height of the AppBar, which I've also not found a way to do. In addition, every instance I've seen of the AppBar uses the Toolbar. All the solutions that I've found that could address this are outdated and don't work (there's no such thing as a ToolbarGroup anymore).
I've also tried using a const styles and exporting the AppBar withStyles():
const styles = {
root: {
flexGrow: 1
},
typography: {
align: "center"
}
};
function Header(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar>
<Toolbar>
<Typography
variant="h6"
color="inherit"
className={classes.typography}
>
Header
</Typography>
</Toolbar>
</AppBar>
</div>
);
}
Header.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(Header);
but it also doesn't work. I'm thinking this should be simple, I'm not sure what I'm missing.
The AppBar component is styled to render its children as flex items.
CSS property like text-align is used for horizontal alignment of children that is displayed different from a flex item e.g. as a table cell, block or inline-block.
Flex items can be centered horizontally using the justify-content or align-self CSS Property or more other ones.
const styles = {
root: {
flexGrow: 1,
},
appbar: {
alignItems: 'center',
}
};
function Header(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar
className={classes.appbar}
color="default"
position="static"
>
<!--...-->
</AppBar>
</div>
);
}
const styles = {
root: {
flexGrow: 1
},
typography: {
flexGrow: 1,
align: "center"
}
};
function Header(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar>
<Toolbar>
<Typography
variant="h6"
color="inherit"
className={classes.typography}
>
Header
</Typography>
</Toolbar>
</AppBar>
</div>
);
}
Header.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(Header);
use flexGrow,
will do the trick and is responsive in mobile also
Adding the following helped me center my title on mobile:
<Box sx={{ flexGrow: 0 }}>
<Box style={{ width: '40px', height: '40px' }}></Box>
</Box>

Resources