React Material UI Accordion能否修改展开方向实现横向展开
MUI Accordion 横向展开实现方案
官方原生Accordion组件未提供直接配置展开方向的direction参数,你可以通过样式覆盖结合布局调整的方式实现横向展开效果,具体方案如下:
核心实现逻辑
- 调整Accordion容器的flex布局方向,将默认纵向排列改为横向排列
- 把组件默认的高度过渡动画替换为宽度过渡动画
- 调整AccordionSummary的文字、展开图标旋转角度,适配横向布局的交互习惯
完整实现代码
你可以通过MUI的styled能力封装自定义横向Accordion组件,直接复用原有组件的交互逻辑:
import * as React from 'react'; import { styled } from '@mui/material/styles'; import MuiAccordion from '@mui/material/Accordion'; import MuiAccordionSummary from '@mui/material/AccordionSummary'; import MuiAccordionDetails from '@mui/material/AccordionDetails'; import Typography from '@mui/material/Typography'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; // 横向Accordion容器 const HorizontalAccordion = styled(MuiAccordion)(({ theme }) => ({ flexDirection: 'row', minWidth: '64px', height: '300px', // 可自定义整体高度 '&.Mui-expanded': { margin: theme.spacing(0, 1), } })); // 横向折叠头部 const HorizontalAccordionSummary = styled(MuiAccordionSummary)(({ theme }) => ({ width: '64px', padding: theme.spacing(0, 2), display: 'flex', justifyContent: 'center', alignItems: 'center', '& .MuiAccordionSummary-content': { transform: 'rotate(90deg)', // 标题文字竖排 whiteSpace: 'nowrap', }, '& .MuiAccordionSummary-expandIconWrapper': { transform: 'rotate(-90deg)', // 适配展开图标方向 '&.Mui-expanded': { transform: 'rotate(0deg)', } } })); // 横向展开内容区 const HorizontalAccordionDetails = styled(MuiAccordionDetails)(({ theme }) => ({ width: 0, padding: theme.spacing(2), overflow: 'hidden', transition: theme.transitions.create('width', { duration: theme.transitions.duration.standard, }), '.Mui-expanded &': { width: '400px', // 可自定义展开宽度,也可设置为flex:1自适应剩余空间 } })); // 组件使用示例 export default function HorizontalAccordionDemo() { const [expanded, setExpanded] = React.useState<string | false>('panel1'); const handleChange = (panel: string) => (_: React.SyntheticEvent, isExpanded: boolean) => { setExpanded(isExpanded ? panel : false); }; return ( <div style={{ display: 'flex', gap: '8px' }}> <HorizontalAccordion expanded={expanded === 'panel1'} onChange={handleChange('panel1')}> <HorizontalAccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls="panel1-content" id="panel1-header" > <Typography>面板1</Typography> </HorizontalAccordionSummary> <HorizontalAccordionDetails> <Typography> 这是面板1的横向展开内容,支持插入任意自定义组件。 </Typography> </HorizontalAccordionDetails> </HorizontalAccordion> <HorizontalAccordion expanded={expanded === 'panel2'} onChange={handleChange('panel2')}> <HorizontalAccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls="panel2-content" id="panel2-header" > <Typography>面板2</Typography> </HorizontalAccordionSummary> <HorizontalAccordionDetails> <Typography> 这是面板2的横向展开内容,展开宽度和整体高度都可以按需调整。 </Typography> </HorizontalAccordionDetails> </HorizontalAccordion> </div> ); }
注意事项
- 若需要自适应宽度,可将展开内容区的
width: '400px'改为flex: 1,实现展开面板自动填充剩余空间 - 折叠状态的宽度需要和AccordionSummary的宽度保持一致,避免出现样式错位
- 无障碍属性可根据实际业务场景补充调整,保证交互可用性
内容的提问来源于stack exchange,提问作者Deniss M.
相关产品推荐
相关产品推荐

