material-ui
material-ui copied to clipboard
[material-ui][Accordion] Content should be scrolled into view when expanded
Steps to reproduce
Link to live example: (required)
Steps:
- Accordion's huge content will extend beyond the viewport when it is present.
- The following is an example link: https://codesandbox.io/s/distracted-sanne-rre74j?file=/demo.js 3.To expand the accordion, click the first item.
- Now, scroll to the bottom and select the second to enlarge.
- Take note of how the screen remains at the bottom of the accordion rather from being raised to the top.
Present actions At the end of the extended accordion, the screen remains
Anticipated conduct Priority should be given to the larger section's content.
Current behavior
Screen stays at end of the expanded accordion
Expected behavior
Focus should be on top of the content on the expanded section
Context
No response
Your environment
npx @mui/envinfo
Don't forget to mention which browser you used.
Output from `npx @mui/envinfo` goes here.
Search keywords: accordion scrolling to down
Hey @rishav001own, thanks for the report!
I agree this would be a good enhancement. Here's the current behavior:
https://github.com/mui/material-ui/assets/16889233/4e88711f-a774-4bbc-ac5b-912f38836669
I added the waiting for upvotes
label so the community can vote for this.
Workaround
There's a workaround using scrollIntoView
and slotProps.transition.onEntered
: https://codesandbox.io/p/sandbox/40625-workaround-1-4pxmn6. Here's the workaround in action:
https://github.com/mui/material-ui/assets/16889233/79d6d67a-5237-4179-a76b-d0ae650bf126
is there any update??
@rishav001own does the proposed workaround work for you?
Regarding implementing this behavior on Material UI's side, we'll have to wait for more upvotes.
Upd?
upd?
fix please
Hey everyone! If you wish to upvote this issue, please add a 👍🏼 (thumbs up) reaction to the description. Thanks!
upd?
'use client';
import React, { useState, useRef } from 'react';
const scrollToRef = useRef<(HTMLDivElement | null)[]>([]);
const executeScroll = (index: number) => {
scrollToRef.current[index]?.scrollIntoView({
behavior: 'smooth',
block: 'nearest'
});
};
<Box
mt={4}
sx={{
maxHeight: '70vh',
overflowY: 'auto'
}}
>
{courses.map((course, index) => (
<Accordion
key={course.id}
onChange={() => {
window.setTimeout(() => executeScroll(index), 500);
}}
>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%'
}}
>
<Box sx={{ flexBasis: '70%' }}>
<Typography variant="h3" sx={{ fontWeight: 'bold' }}>
{course.name}
</Typography>
<Typography variant="body1" sx={{ mt: 1 }}>
{course.description}
</Typography>
</Box>
<Box sx={{ flexBasis: '10%', textAlign: 'left' }}>
{course.dates &&
course.locations &&
course.dates.map((date, index) => (
<Chip
key={index}
label={`${date} - ${
(course.locations && course.locations[index]) || ''
}`}
sx={{ mr: 1, mb: 1 }}
/>
))}
{course.link && (
<Box sx={{ textAlign: 'center' }}>
<MuiLink
href={`https://xxxxx.com${course.link}`}
target="_blank"
rel="noopener"
sx={{ textDecoration: 'none' }}
>
Tilmeld
</MuiLink>
</Box>
)}
</Box>
</Box>
</AccordionSummary>
<AccordionDetails>
<div
ref={(el) => {
if (el) {
scrollToRef.current[index] = el;
}
}}
>
{course.image && (
<Box
sx={{
position: 'relative',
width: '100%',
height: '300px',
mb: 2
}}
>
<Image
src={course.image || '/images/aktuel.webp'}
alt={course.name || 'Kursusbillede'}
quality={100}
fill
sizes="(max-width: 768px) 100vw, 33vw"
style={{ objectFit: 'cover' }}
/>
</Box>
)}
{course.course_description && (
<Box>
{isCourseDescriptionData(
course.course_description as string
) ? (
(
course.course_description as unknown as CourseJsonB
).sections.map((section, index) => (
<Box key={index} mt={2}>
<Typography variant="h4" gutterBottom>
{section.subheader}
</Typography>
<ul>
{section.checkmarks.map(
(checkmark, checkmarkIndex) => (
<li key={checkmarkIndex}>{checkmark}</li>
)
)}
</ul>
</Box>
))
) : (
<Typography>Invalid course description data</Typography>
)}
</Box>
)}
</div>
</AccordionDetails>
</Accordion>
))}
</Box>
I implemented it like this here and seems to work fine :)
This issue reminds me of #22152. The solution looks straightforward: overflow-anchor: auto
, which is the default behavior of the platform. See https://css-tricks.com/almanac/properties/o/overflow-anchor/#aa-demo
I can't reproduce the issue in #22152 in the latest version of Chrome, so we might want to revert #22292 to close this issue.
My solution:
const handleChange = (event: SyntheticEvent<Element, Event>, expanded: boolean) => {
onChange?.(event, expanded);
if (expanded) {
setTimeout(() => {
accordionRef.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}, theme.transitions.duration.standard);
}
};
Any simple resolution for current now? @oliviertassinari
@tjx666 have you tried the workaround in this comment?
@DiegoAndai works, thanks
This issue is duplicate of #34379