Drawer MUI component persistent animation is super slow (sometimes) || React with MUI - reactjs

I'm building this app, and, as you can see, we have a left drawer and a main component in the right direction.
And when I close that drawer, the main component will move a little bit in order to occupy the rest of the space.
But, when there's too much data in the table, the animation is going to be super slow and it doesn't look nice.
This is the code, here, we have that left drawer and the main component
{/* Side panel */}
<LeftDrawer />
{/* Main content */}
<SinAsignarHero />
This is only the left drawer, that has an open prop that will receive a boolean from a redux reducer
<Drawer
sx={{
width: 260,
flexShrink: 0,
background: '#fafafa',
'& .MuiDrawer-paper': {
width: 260,
background: '#fafafa',
border: '0px',
boxShadow: '0px 8px 7px #0000003D',
boxSizing: 'border-box',
top: 'auto',
zIndex: 1,
},
}}
open={isOpen}
variant="persistent"
anchor="left"
>
{appOptions &&
appOptions.menus.map(({ id, nombre, sub_menu }) => {
return (
<Fragment key={id}>
<AppOptions nombre={nombre} sub_menu={sub_menu && sub_menu} />
</Fragment>
);
})}
</Drawer>
And the main component that will execute the animation to occupy the whole space with the same boolean from redux
const MainContent = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })<{
open?: boolean;
}>(({ theme, open }) => ({
background: '#fafafa',
height: '90.7vh',
overflowX: 'hidden',
flexGrow: 1,
padding: '40px 53px 0px 53px',
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
marginLeft: `-260px`,
...(open && {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: 0,
}),
}));
return (
<MainContent open={isDrawerOpen}>
<SinAsignarTitle setCount={setCount} setHasMore={setHasMore} />
<TableContainer component={Paper} sx={{ maxHeight: '73vh', borderRadius: '5px' }}>
{scrollData.length ? (
<>
<InfiniteScroll
dataLength={scrollData.length}
next={getMoreData}
hasMore={hasMore}
loader={<div></div>}
scrollableTarget="TableContainer"
>
<TableContainer
component={Paper}
sx={{ maxHeight: '73vh', borderRadius: '5px' }}
id="TableContainer"
>
<Table stickyHeader sx={{ minWidth: 800 }}>
{/* Table header */}
<SinAsignarHead setCount={setCount} setHasMore={setHasMore} />
{/* Hero content */}
<SinAsignarContent recogidas={scrollData} />
</Table>
</TableContainer>
</InfiniteScroll>
</>
) : (
<NotFound />
)}
</TableContainer>
</MainContent>
So, when there isn't that much data in the table, it is not that slow, but, I want the animation to be fast always.
This is pretty much what I would love to accomplish
https://mui.com/components/drawers/#persistent-drawer
If you go to the sandbox of that example, and you add too much text, the animation is still fine, I don't know if maybe there are too many things going on when there's too much data so it's harder for my left drawer and main component to make the animations as fast as possible. Is there something I can do in order to fix this ?¿

Try virtualized table.
Virtualization helps with performance issues.
https://mui.com/components/tables/#virtualized-table

Related

How to upgrade <Spring> to useSpring for scrolling?

I've been using an outdated version of react-spring to animate a programmatic scroll.
The code used to be:
import { Spring } from "react-spring/renderprops";
// (...)
<Spring from={{ top: 0 }} to={{ top: LINE_HEIGHT * (page.from - 1) }}>
{(props) => (
<List
width={1}
height={LINE_HEIGHT * limit}
rowCount={sortedGauges.length}
rowHeight={LINE_HEIGHT}
rowRenderer={rowRenderer}
containerStyle={{
width: "100%",
maxWidth: "100%",
}}
style={{
width: "100%",
overflow: "hidden",
}}
scrollTop={props.top}
/>
)}
</Spring>
So the Spring component was updating a child with props.top each time the user clicked a button to get a smooth scroll. But I can't reproduce this result with the new useSpring API. What is the correct syntax?

Making child element fill to the height of the parent container React MUI

I am trying to build a React Dashboard with MUI. Its with an AppBar and a drawer and the content area is a box (Please correct anything wrong box with specified spec is a perfect approach)..
But the problem I am facing is I cant make the container placeholder which is the Box itself to stretch its height to the full height of the page.
Here is my tsx
export default function RootContainer() {
const [open, setOpen] = React.useState(false);
const title="Manage Recipes";
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
justifyContent: 'flex-end',
}));
const drawerWidth = 240;
const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })<{
open?: boolean;
}>(({ theme, open }) => ({
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
marginLeft: `-${drawerWidth}px`,
...(open && {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: 0,
}),
}));
return (
<Box sx={{ display: 'flex', bgcolor:"silver",height:"100vh" }}>
<CssBaseline />
<AppBar open={open} onDrawerOpen={handleDrawerOpen} />
<Drawer open={open} onDrawerClose={handleDrawerClose} />
<Main open={open} >
<DrawerHeader />
<Container maxWidth="xl">
<h2>{title}</h2>
<Paper elevation={1} sx={{bgcolor:"#f7f9ff", height:"100%"}}>
<ManageRecipe />
</Paper>
</Container>
</Main>
</Box>
);
}
How can I achieve that to get full height (not full width)
*****Update Based on Answer
Based on the answer I have updated the page and the parent works fine now. It stretches to its full size without scroll.
But the two child elements causing some trouble as it still not full height.
So I updated the child container like this
<Container maxWidth="xl" sx={{margin:"20", bgcolor:"red", height:1}} >
<h2>{title}</h2>
<Paper elevation={1} sx={{bgcolor:"#f7f9ff", height:1/2}}>
<ManageRecipe />
</Paper>
</Container>
Now it looks like the child container bleeds out of the parent like this
I was expecting the Container stay within the parent box with a bottom padding of 20px. But it doesnt.. PLease help
In your global index.css, make your parent nodes stretch in y-axis, by having these styles:
body: { height: 100vh; }
html,
#root,
.App {
height: 100%;
}
Besides
flex-direction in react-apps is row by default,
so update your Box-styling to :
<Box
sx={{
display: 'flex',
flexDirection: 'column',
bgcolor: 'silver',
height: '100%', // <---here
}}
>
{/** ... */}
</Box>

React Material UI custom tooltip AND speed dial style

I'm trying to customize the tooltip appearance and the position of the speed dial but get an error when doing both.
const useStyles = makeStyles((theme) => ({
root: {
height: 380,
transform: "translateZ(0px)",
flexGrow: 1,
},
speedDial: {
position: "absolute",
bottom: theme.spacing(2),
right: theme.spacing(0),
},
tooltip: {
backgroundColor: "#37517e",
fontSize: "1.1em",
},
}));
<SpeedDial
ariaLabel="Tutor SpeedDial"
className={classes.speedDial}
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
onClose={handleClose}
onOpen={handleOpen}
open={open}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
TooltipClasses={classes}
onClick={handleClose}
/>
))}
</SpeedDial>
The code actually compiles and works but I get a console error
index.js:1 Material-UI: The key speedDial provided to the classes prop is not implemented in ForwardRef(Tooltip).
You can only override one of the following: popper,popperInteractive,popperArrow,tooltip,tooltipArrow,arrow,touch,tooltipPlacementLeft,tooltipPlacementRight,tooltipPlacementTop,tooltipPlacementBottom.
It's pretty clear that the issue is because ToolTipClasses cannot override the speedDial class but I'm not sure how else to do it.
Any guidance will be much appreciated
Thanks
I came up with solution by by creating a StyledSpeedDial instead so that I could remove the speeddial onbject from the classes style
const StyledSpeedDial = styled(SpeedDial)(({ theme }) => ({
position: "absolute",
"&.MuiSpeedDial-directionUp, &.MuiSpeedDial-directionLeft": {
bottom: theme.spacing(2),
right: theme.spacing(0),
},
}));
<StyledSpeedDial
ariaLabel="Tutor SpeedDial"
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
onClose={handleClose}
onOpen={handleOpen}
open={open}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
TooltipClasses={classes}
onClick={handleClose}
/>
))}
</StyledSpeedDial>

How can I disable multiline for autocomplete material-ui demo?

Country select of
autocomplete demo at material-ui
uses react-select and material-ui controls,
shows multiline text, select control changes it's dimensions when country doesn't fit in one line.
I see this behaviour at CodeSandbox when I decrease width of web browser.
How can I modify demo so that country will always fit in one line,
select control will not change it's dimensions?
TextField has props multiline, rows and rowsMax props that can be changed.
If that isn't what you need then you could add the following css to the text in the TextField so the text does not wrap:
overflow: hidden;
white-space: nowrap;
I managed this by mixing a few different things:
First create a class like so:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
closed: {
flexWrap: "nowrap",
overflowX: "hidden",
},
// Add a linear gradient behind the buttons and over the Chips (if applies)
endAdornment: {
background:
"linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.6) 22%, rgba(255,255,255,1) 60%)",
bottom: 0,
display: "flex",
alignItems: "center",
right: "0 !important",
paddingRight: 9,
paddingLeft: theme.spacing(2),
top: 0,
},
})
);
Then in your static function add this :
const onOpenChange = (open: boolean | null) => {
setIsOpen(open);
};
const inputStyle = clsx({
[classes.closed]: !isOpen, //only when isOpen === false
});
Finally on the Autocomplete component itself use:
classes={{ inputRoot: inputStyle, endAdornment: classes.endAdornment }}
onOpen={() => onOpenChange(true)}
onClose={() => onOpenChange(false)}
If you are wondering how to make each option be displayed in just one line with ellipsis, you can do the follow:
<Autocomplete
...
getOptionLabel={(option: any) => `${option.label} (${option.code})`}
renderOption={(option) => (
<React.Fragment>
<div style={{ textOverflow: 'ellipsis', overflow: "hidden", whiteSpace: "nowrap" }}>
{option.label} ({option.code})
</div>
</React.Fragment>
)}
...
/>
For the Country Demo example, you can check what I did here: https://codesandbox.io/s/autocomplete-with-ellipsis-i8hnw

Material UI Drawer overflow causing scrollbar on body

I'm using a clipped under the app bar drawer with a canvas as the primary content. I have three collapsible cards in the drawer and when all set to be open by default, it shows a vertical scrollbar on the body and white space below the html element with the body element. If you close all three of the cards the scroll goes away. If you reopen the cards, the scroll doesn't appear. The issue only seems to occur when the page is loaded with all three cards open.
Our short term solution is to load the page with only two cards open, but I want to note even with two open, the drawer content extends below the window with no scroll. The CSS for the drawer shouldn't be the issue either. Anyone else experience this issue?
drawerPaper: {
position: 'relative',
width: 400,
overflowX: 'hidden',
overflowY: 'hidden',
'&:hover': {
overflowY: 'auto',
},
'&::-webkit-scrollbar': {
display: 'none',
},
},
<MuiThemeProvider theme={this.state.useDarkTheme ? darkTheme : lightTheme}>
<div className={classes.root}>
<AppBar position="absolute" className={classes.appBar}>
<Toolbar>
<div className={classes.flex}>
<Typography className={classes.headerTextColor} variant="title">
Title
</Typography>
{sealedBy}
</div>
<HeaderTools />
<Tooltip id="toggle-icon" title="Toggle light/dark theme">
<IconButton className={classes.headerTextColor} onClick={this.toggleTheme}>
<BrightnessMediumIcon />
</IconButton>
</Tooltip>
</Toolbar>
{spinner}
</AppBar>
<Drawer
variant="permanent"
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.fixedWidth}>
<div className={classes.toolbar} />
<DocumentTools />
<SealingTools />
<AnnotationTools />
</div>
</Drawer>
<main className={classes.content}>
<div className={classes.toolbar} />
<DrawingCanvas />
</main>
</div>
</MuiThemeProvider>
You need to add height: 100% css property on some container components, and to styles to drawerPaper need add too.
I have setup here, its working, but probably depends on container components:
drawerPaper: {
width: 250,
overflow: "auto",
height: "100%",
[theme.breakpoints.up("md")]: {
overflow: "auto",
width: drawerWidth,
position: "relative",
height: "100%"
}
}

Resources