如何配置Mui Accordion组件实现水平展开而非默认垂直展开?
MUI Accordion 水平展开实现方案
MUI 默认的 Accordion 组件本身没有直接配置展开方向为水平的属性,它的原生设计是垂直折叠面板。不过可以通过自定义样式改造,或者用其他组件模拟水平展开效果,以下是具体方案:
一、自定义样式实现水平展开的 Accordion
通过调整 Accordion、AccordionSummary 和 AccordionDetails 的布局样式,让展开的内容和标题在同一行显示:
import { Accordion, AccordionSummary, AccordionDetails, Typography } from '@mui/material'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; export default function HorizontalAccordion() { return ( <Accordion sx={{ display: 'flex', flexWrap: 'nowrap', overflow: 'hidden' }}> <AccordionSummary expandIcon={<ExpandMoreIcon />} sx={{ flexShrink: 0, minWidth: '200px', borderRight: '1px solid #e0e0e0' }} > <Typography>面板标题</Typography> </AccordionSummary> <AccordionDetails sx={{ display: ({ expanded }) => expanded ? 'flex' : 'none', flexGrow: 1, padding: '16px' }}> <Typography> 这里是水平展开的内容区域,和标题在同一行展示,收起时会隐藏。 </Typography> </AccordionDetails> </Accordion> ); }
关键调整点:
- 给
Accordion设置display: flex,让子元素横向排列 AccordionSummary设置固定宽度,避免被内容挤压- 通过
expanded状态控制AccordionDetails的显示/隐藏,展开时用flex布局占据剩余空间
二、替代方案:用 Drawer 模拟水平展开
如果需要侧边滑出的水平展开效果,MUI 的 Drawer 组件更适合,搭配按钮触发展开/收起:
import { useState } from 'react'; import { Drawer, Button, Typography } from '@mui/material'; export default function HorizontalDrawer() { const [isOpen, setIsOpen] = useState(false); const toggleDrawer = (status) => () => { setIsOpen(status); }; return ( <div style={{ display: 'flex', alignItems: 'center', height: '64px' }}> <Button onClick={toggleDrawer(true)} variant="outlined"> 展开侧边内容 </Button> <Drawer anchor="right" open={isOpen} onClose={toggleDrawer(false)} variant="persistent" sx={{ '& .MuiDrawer-paper': { width: '350px', boxSizing: 'border-box' } }} > <Typography sx={{ padding: '20px' }}> 这是侧边滑出的内容,完全模拟水平展开的交互逻辑,收起时会隐藏到侧边。 </Typography> </Drawer> </div> ); }
这种方案的优势是自带滑入滑出的过渡动画,交互体验更流畅,适合需要大面积水平展开内容的场景。
三、替代方案:用 Tabs 组件实现横向内容切换
如果是多个内容块需要横向切换展示,Tabs 组件可以直接实现类似水平“展开”的视觉效果,点击标签切换对应内容:
import { useState } from 'react'; import { Tabs, Tab, Box, Typography } from '@mui/material'; export default function HorizontalTabs() { const [activeTab, setActiveTab] = useState(0); const handleTabChange = (event, newValue) => { setActiveTab(newValue); }; return ( <Box sx={{ width: '100%' }}> <Tabs value={activeTab} onChange={handleTabChange} variant="scrollable" scrollButtons="auto"> <Tab label="面板1" /> <Tab label="面板2" /> <Tab label="面板3" /> </Tabs> <Box sx={{ padding: '20px' }}> {activeTab === 0 && <Typography>面板1的内容</Typography>} {activeTab === 1 && <Typography>面板2的内容</Typography>} {activeTab === 2 && <Typography>面板3的内容</Typography>} </Box> </Box> ); }
这种方案适合内容块较多的场景,用户可以快速切换不同内容,视觉上也是横向布局的交互。
内容的提问来源于stack exchange,提问作者user21302417
相关产品推荐
相关产品推荐

