I'm building a webchat with React MUI. For the layout, I'd like to use the Flexbox because the chat input is set to auto grow, and I'd like the messages feed container to be able to auto adjust it's height.
However, I struggle to get the overflow scrollbar to work with flex layout.
- When I set message length at 20, the message feed overflows above the container, and I can't get the scrollbar even when I have
overflowY: "auto"
- When I set contacts length to 20, it pushes down the content down, even when I set the root container to
height: '100vh'
I've read answers from 'How can I combine flexbox and vertical scroll in a full-height app?', and 'Scrolling a flexbox with overflowing content', and 'How to make a scrollable container with dynamic height using Flexbox'. Using tricks like setting overflow: 'hidden'
on parents div, or setting minHeight: 0
to the list and feed container. I still can't get it to work. I'm struggle to get the proper scroll behaviour and don't know where I'm missing. Please help!
Here is the Codesandbox: https://codesandbox.io/s/mui-webchat-lsn3tm?file=/demo.js
// ----------------------------------------------------------
const contactLenghth = 10;
const messageLength = 20;
// ----------------------------------------------------------
export default function Chat() {
return (
<main
style={{
height: "100vh",
display: "flex",
flexDirection: "column"
}}
>
<AppBar position="sticky">
<Toolbar>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
LOGO
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
<Grid container direction="row" alignItems="stretch" sx={{ flexGrow: 1 }}>
<Grid
item
md={3}
sx={{
display: { xs: "none", sm: "flex" },
flexDirection: "column",
overflowY: "auto",
borderRight: "1px solid lightgrey"
}}
>
<Toolbar>
<Typography variant="h6"> Contacts </Typography>
</Toolbar>
<Divider />
<List>
{[...Array(contactLenghth)].map((n, i) => (
<ListItemButton key={i}>
<ListItem disablePadding>
<ListItemAvatar>
<Avatar />
</ListItemAvatar>
<ListItemText primary={`Contact ${i + 1}`} />
</ListItem>
</ListItemButton>
))}
</List>
</Grid>
<Grid
item
xs={12}
md={9}
sx={{ display: "flex", flexDirection: "column" }}
>
<Toolbar>
<Avatar sx={{ mr: 2 }} />
<ListItemText primary="John Doe" />
</Toolbar>
<Divider />
<Stack
direction="column"
spacing={1}
p={2}
justifyContent="flex-end"
sx={{ flexGrow: 1, overflowY: "auto", height: 0 }}
>
{[...Array(messageLength)].map((n, i) => (
<Stack
key={i}
direction="row-reverse"
spacing={2}
justifyContent="end"
>
<Box
sx={{
px: 2,
py: 1,
maxWidth: "60%",
borderRadius: 20,
bgcolor: "secondary.main",
color: "#fff"
}}
>
<Typography>Test message {i + 1}</Typography>
</Box>
</Stack>
))}
</Stack>
<Stack direction="row" p={2} alignItems="flex-end">
<TextField
placeholder="Message"
fullWidth
multiline
maxRows={5}
sx={{
flexGrow: 1,
borderRadius: 7,
"& fieldset": { borderRadius: 7 }
}}
/>
<Box p={1}>
<IconButton>
<SendIcon />
</IconButton>
</Box>
</Stack>
</Grid>
</Grid>
</main>
);
}