Material UI - Grid CardContent force overflow y only - html

I have a project that builds a Dashboard using Material UI, the dashboard can have plots and different content inside a Material UI Card.
When there is enough y-space the content works just fine like this:
But when the vertical space is not enough the content overflow kinda breaks and places some items on the right instead of overflowing vertically.
The idea is that the plot will use any available space and the text will use just what it needs.
All the code for this is here: https://github.com/danielfrg/jupyter-flex/blob/main/js/src/Card/index.js
But I will put some pieces here to help.
This is the Card:
<Grid
item
container
className={`card ${cardsClsName} ${customClsNames}`}
direction="column"
alignItems="stretch"
xs={size}
>
{header ? <Grid item>{header}</Grid> : null}
<Grid
item
component={MaterialCard}
className={`${boxClsName} ${
verticalLayout == "scroll" ? classes.boxVLScroll : ""
}`}
variant="outlined"
xs
>
<Grid
item
container
direction="column"
component={CardContent}
className={cardContentClsName}
xs
>
{bodyComponents}
</Grid>
</Grid>
{footerComponents.length > 0 ? (
<Grid
item
container
component={CardActions}
className={classes.cardFooter}
>
{footerComponents}
</Grid>
) : null}
</Grid>
And the Material Styles that I apply to these:
const styles = (theme) => ({
card: {},
cardInColumn: {},
cardInRow: {},
cardInTabs: {
maxWidth: "100%",
height: "100%",
},
cardInSidebar: {
maxWidth: "100%",
height: "100%",
padding: 8,
},
cardHeader: {
padding: "6px 8px",
},
cardTitle: {
padding: "5px 0",
fontSize: "1.05em",
fontWeight: 600,
},
space: {
flexGrow: 1,
},
box: {},
boxVLScroll: {
flexBasis: "auto",
},
boxInSidebar: {
flexGrow: 1,
border: "none",
},
cardContent: {
maxWidth: "100%",
minHeight: "100%",
height: "100%",
overflow: "auto",
},
cardContentInSidebar: {
height: "100%",
display: "flex",
flex: "1 1 auto",
flexDirection: "column",
padding: "0 8px",
},
cardFooter: {
padding: "0 8px 8px",
},
empty: {
margin: "auto",
padding: theme.spacing(2),
textAlign: "center",
color: theme.palette.text.secondary,
},
});
I appreciate any pointers I am not the best when it comes to CSS.
Thanks!

Related

Why does my stretch attribute in mui flexbox not do anything?

So I want the boxes I have displayed in a parent box to completely stretch out. I followed the documentation on MUI for the flexbox, though after editing it a bit I do not understand why it does not work anymore :?
I have given the inner items a minimum for width and height, but even without this the items do not stretch.
Does the stretch attribute not mean that the parent container will be completely filled out?
Here's my code:
import "./styles.css";
import React from "react";
import Box, { BoxProps } from "#mui/material/Box";
import PropTypes from "prop-types";
function Item(props) {
const { sx, ...other } = props;
return (
<Box
sx={{
border: "1px solid pink",
borderRadius: 2,
fontSize: "0.875rem",
minHeight: "5rem",
minWidth: "5rem",
...sx
}}
{...other}
/>
);
}
Item.propTypes = {
sx: PropTypes.oneOfType([
PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])
),
PropTypes.func,
PropTypes.object
])
};
export default function App() {
const items = [
{
title: "Car",
color: "yellow"
},
{
title: "Plane",
color: "lightblue"
},
{
title: "Bicycle",
color: "lightgreen"
},
{
title: "Train",
color: "orange"
}
];
const movies = [
{
title: "Seven",
color: "red"
},
{
title: "Memento",
color: "white"
},
{
title: "Vivarium",
color: "lightgreen"
},
{
title: "Blue Velvet",
color: "lightblue"
}
];
return (
<>
<Box
className="Container Of Sub"
style={{
backgroundColor: "lightpink",
display: "flex",
alignItems: "center",
width: "100%",
height: "100%"
}}
>
<Box className="FirstSub" style={{ width: "50%" }}>
<Box
className="Header"
style={{
borderRadius: "10px",
paddingLeft: "10px",
boxShadow: "4px 4px 20px 0px rgba(0,0,0,0.25",
backgroundColor: "white"
}}
>
<h4>Subcategory 1</h4>
</Box>
<Box
className="Category Holder"
sx={{
display: "flex",
flexWrap: "wrap",
alignContent: "stretch",
borderRadius: 1
}}
>
{items.map((item) => (
<Item
sx={{
backgroundColor: item.color
}}
>
{item.title}
</Item>
))}
</Box>
</Box>
<Box
className="2ndSubCategory"
style={{
width: "50%",
marginLeft: "20px"
}}
>
<Box
className="Header"
style={{
borderRadius: "10px",
paddingLeft: "10px",
boxShadow: "4px 4px 20px 0px rgba(0,0,0,0.25",
backgroundColor: "white"
}}
>
<h4>Subcategory 2</h4>
</Box>
<Box
className="Category Holder"
sx={{
display: "flex",
flexWrap: "wrap",
alignContent: "stretch",
borderRadius: 1
}}
>
{movies.map((item) => (
<Item
sx={{
backgroundColor: item.color
}}
>
{item.title}
</Item>
))}
</Box>
</Box>
</Box>
</>
);
}

Align-center for text and item not aligning?

I am trying to align the items in a div (that is within an MUI Select styled component):
const SelectStyle = styled(Select)(({ theme }) => ({
width: WIDTH,
border: `1px solid ${theme.palette.grey[400]}`,
borderRadius: 3,
fontSize: '1.2rem',
'&:hover': {
backgroundColor: theme.palette.grey[300],
border: `1px solid ${theme.palette.grey[500]}`,
},
'&:focus': {
backgroundColor: theme.palette.grey[700],
border: `1px solid ${theme.palette.grey[700]}`,
},
'& .MuiSelect-select': {
paddingTop: 5,
paddingBottom: 5,
fontSize: '1.2rem',
alignItems: 'center',
display: 'inline-flex'
},
}));
I can see that the effect has been applied to the parent div:
However, I still see that the text and the icon don't look center aligned ("Text" looks higher than the icon):
Is there a reason for this? And how do I make it more center aligned?

Inconsistent margins/spacing with Material UI Accordion

I'm using Material UI Accordion for creating a filter menu.
It looks like this on some devices whereas it looks likes this on other devices with different dimensions even though the margins between the items are the same and uses the same code. On resizing the dimensions of the screen, the inconsistency changes.
How to fix this inconsistency with the spacing between each filter item?
Here's my file FilterAccordion.tsx:
<Box className={classes.accordionRoot}>
<Accordion style={{ boxShadow: "none" }} defaultExpanded={true}>
<AccordionSummary
expandIcon={<ExpandMore style={{ fill: "#d3d3d3" }} />}>
<div className={classes.verticalrootcontainer}>
<Icon
onClick={(e) => e.stopPropagation()}
style={{
fill: "#d3d3d3",
width: "2rem",
marginRight: "1rem",
transform: "scale(3)",
zIndex: -1,
}}
/>
<Typography
variant="body1"
className={`titleAquire ${classes.title}`}>
{title}
</Typography>
</div>
</AccordionSummary>
<AccordionDetails>
<div className={classes.listRoot}>
{Object.keys(groupByPacks).map((item, index) => {
let checked = isChecked(item);
return (
<div
key={index}
className={`${classes.list} ${
checked ? classes.selected : ""
}`}
onClick={() => handleOnCheck(item)}>
<Typography variant="body1" className={classes.item}>
{item}
</Typography>
<Typography variant="body1" className={classes.item}>
{groupByFilteredPacks[item]
? groupByFilteredPacks[item]?.length
: 0}
</Typography>
</div>
);
})}
</div>
</AccordionDetails>
</Accordion>
</Box>
And the CSS file:
accordionRoot: {
"& .MuiAccordion-root": {
background: "transparent",
},
"& .MuiAccordionDetails-root": {
padding: "0px",
},
"& .MuiAccordionSummary-root": {
padding: "0px",
marginBottom: "-1rem",
},
"& .MuiCollapse-entered": {
marginTop: "1rem",
},
},
title: {
fontSize: "18px",
color: theme.on.dark,
},
verticalrootcontainer: {
display: "flex",
alignItems: "center",
},
list: {
display: "flex",
width: "100%",
alignItems: "center",
justifyContent: "space-between",
marginTop: "0.2rem",
padding: "0.2rem 0.5rem",
cursor: "pointer",
"&:first-child": {
marginTop: 0,
},
},
item: {
textTransform: "uppercase",
color: theme.on.dark,
opacity: "30%",
},
selected: {
background: theme.on.dark,
"& p": {
color: theme.darkMode.light,
opacity: "100%",
},
},
listRoot: {
width: "100%",
},

CSS Make siblings children same width and height (squares) in 100% width parent

I have a parent view which width is "100%" (not screen width), and I want to have each children with the same width and height.
My codes is:
<View style={styles.container}>
<View style={styles.item} />
<View style={styles.item} />
<View style={styles.item} />
<View style={styles.item} />
</View>
const styles = StyleSheet.create({
container: {
width: "100%",
flexDirection: "row",
alignItems: "center",
},
item: {
width: 75,
height: 75,
marginRight: 10,
backgroundColor: "red",
},
});
But this is not responsive for all devices (in small sevices some of the children go out of screen)... Is there any other way to do that?
Thank you.
container: {
flexDirection: "row",
alignItems: "center",
},
item: {
flex: 1,
aspectRatio: 1,
backgroundColor: "red",
},
The trick for your situation is aspectRatio. Just make each child flex: 1, but with an aspect ratio of 1 to make them squared.
Percentage widths
There are likely many ways to do this, but the first one that comes to mind is setting the widths to percentages. This makes the item a percentage of the parent.
item: {
width: '30%',
height: 75,
marginRight: 10,
backgroundColor: "red",
}
If you need something more flexible, you may want to look into responsive design and setting breakpoints for different screen sizes.
Flex Wrap
If you want your content to stay a fixed size, you can have it wrap within your container. For different screen sizes, there may be more boxes in one row than another.
You'll likely need to change some styling, but wrapping would look something like this
<View style={styles.container}>
<View style={styles.item} />
<View style={styles.item} />
<View style={styles.item} />
<View style={styles.item} />
</View>
const styles = StyleSheet.create({
container: {
width: "100%",
justifyContent: 'space-between',
flexDirection: "row",
alignItems: "center",
flexWrap: 'wrap',
},
item: {
width: 75,
height: 75,
marginRight: 10,
backgroundColor: "red",
},
});
Grid
If you don't like a variable number of boxes per row, you could make a grid. You would have a container, rows, and, in each row, your boxes.
Again, you'll have to tweak some styles.
<Container style={styles.container}>
<Row style={styles.row}>
<Box />
<Box />
<Row />
<Row style={styles.row}>
<Box />
<Box />
<Row />
</Container>
const styles = StyleSheet.create({
container: {
width: "100%",
},
row: {
width: "100%",
justifyContent: 'space-between',
flexDirection: "row",
alignItems: "center",
},
item: {
width: 75,
height: 75,
marginRight: 10,
backgroundColor: "red",
},
});

How do I create a scrollable div that matches the height of my `iframe` using Material-UI?

I am creating a responsive Video Player with a playlist next to it. This is for Desktop and above screens sizes. The playlist can have hundreds of items.
My attempt is available at https://codesandbox.io/s/responsive-video-player-playlist-q3601
The problem that I am facing is when there are a lot of items, the playlist part is not scrollable and its height does not match with its sibling (video-player).
What I am looking for
- That the height of the player & playlist should be equal to the height of the video player.
- A large number of items in the playlist should be scrollable.
What have I tried?
The demo is available at https://codesandbox.io/s/responsive-video-player-playlist-q3601
Any help is greatly appreciated!
you need to use the same trick for the playlist and the player , a break point and position.
adding a class can help add a few more CSS rules :
https://codesandbox.io/s/responsive-video-player-playlist-i1msg
CSS part updated :
const useStyles = makeStyles(theme => ({
root: {
backgroundColor: "brown",
display: "flex"
},
playerContainer: {
position: "relative",
paddingTop: "37.25%",
height: 0,
overflow: "hidden",
maxWidth: "100%",
backgroundColor: "#000000",
[theme.breakpoints.down("sm")]: {
paddingTop: "56.25%"
}
},
iframe: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
border: "6px solid yellow"
},
playlist: {
position: "relative",
[theme.breakpoints.down("sm")]: {
position: "staic"
}
},
playlistContainer: {
backgroundColor: "lightgrey",
position: "absolute",
top: "0",
bottom: "0",
right: "0",
left: "0",
overflow: "auto",
[theme.breakpoints.down("sm")]: {
position: "relative"
}
}
}));
and structure :
<Grid container className={classes.root}>
<Grid item xs={12} md={8} className={classes.playerContainer}>
<iframe
title="video"
src="https://player.vimeo.com/video/66140585"
frameborder="0"
className={classes.iframe}
/>
</Grid>
<Grid item xs={12} md={4} className={classes.playlist}>
<Grid container className={classes.playlistContainer}>
<Grid item xs={12}>
{lines.map((line, key) => (
<div key={key}>{line}</div>
))}
</Grid>
</Grid>
</Grid>
</Grid>