在Next.js中使用Material UI:如何禁用Accordion但保留默认样式?
禁用Material UI Accordion但保留默认样式(无灰色禁用外观)
我在Next.js项目中使用Material UI,需要在song?.lyrics不存在时禁用Accordion组件,但不想让它显示灰色的禁用样式,保持正常状态的外观。当前代码设置了disabled={!song?.lyrics},但会触发MUI默认的禁用态样式,尝试过className、sx、createTheme等方式都没解决。
方案1:全局Theme覆盖禁用态样式
MUI的Accordion禁用时会自动添加.Mui-disabled类,我们需要在全局主题中覆盖这个类的样式,同时还要处理子组件(AccordionSummary、AccordionDetails)的禁用态样式——因为它们会继承父组件的禁用样式。
修正后的createTheme代码:
import { createTheme, ThemeProvider } from '@mui/material/styles'; const theme = createTheme({ components: { MuiAccordion: { styleOverrides: { root: { '&.Mui-disabled': { // 重置为正常状态的背景色(比如默认透明/白色) backgroundColor: 'transparent', // 移除禁用态的透明度 opacity: 1, cursor: 'default', }, }, }, }, MuiAccordionSummary: { styleOverrides: { root: { '&.Mui-disabled': { color: 'inherit', // 继承正常文本颜色 '& .MuiAccordionSummary-content': { opacity: 1 }, '& .MuiIconButton-root': { opacity: 1 }, // 重置图标的透明度 }, }, }, }, MuiAccordionDetails: { styleOverrides: { root: { '&.Mui-disabled': { color: 'inherit', opacity: 1, }, }, }, }, }, }); // 在项目根组件中用ThemeProvider包裹 function MyApp({ Component, pageProps }) { return ( <ThemeProvider theme={theme}> <Component {...pageProps} /> </ThemeProvider> ); } export default MyApp;
配置完成后,禁用的Accordion会保持正常外观,同时具备禁用的交互特性(无法展开)。
方案2:手动控制交互,不使用disabled属性
如果不想修改全局主题,可以跳过disabled属性,通过逻辑控制展开状态和点击事件,避免触发禁用态样式:
import { useState } from 'react'; import { Accordion, AccordionSummary, AccordionDetails } from '@mui/material'; import MdLyrics from '@mui/icons-material/Lyrics'; function ShowLyrics({ song }: Readonly<{ song: song }>) { const [expanded, setExpanded] = useState(false); const handleToggle = () => { // 仅当歌词存在时允许切换展开状态 if (song?.lyrics) setExpanded(!expanded); }; return ( <Accordion expanded={expanded}> <AccordionSummary expandIcon={song?.lyrics ? <MdLyrics className='text-black' /> : null} onClick={handleToggle} sx={{ cursor: song?.lyrics ? 'pointer' : 'default' }} > {song.name} </AccordionSummary> <AccordionDetails> {song?.lyrics ? song.lyrics : 'Paroles non disponibles'} </AccordionDetails> </Accordion> ); }
这种方式下组件不会进入禁用状态,自然不会应用MUI的灰色禁用样式,同时通过逻辑实现了“无歌词时无法展开”的需求。
方案3:局部sx属性覆盖样式
如果只想针对当前组件修改,不影响全局,可以直接在Accordion上用sx属性覆盖禁用态样式:
<Accordion disabled={!song?.lyrics} sx={{ '&.Mui-disabled': { backgroundColor: 'transparent', opacity: 1, '& .MuiAccordionSummary-root': { color: 'inherit', '& .MuiAccordionSummary-content': { opacity: 1 }, }, '& .MuiAccordionDetails-root': { color: 'inherit', opacity: 1, }, }, }} > <AccordionSummary expandIcon={song?.lyrics ? <MdLyrics className='text-black' /> : null} > {song.name} </AccordionSummary> <AccordionDetails> {song?.lyrics ? song.lyrics : 'Paroles non disponibles'} </AccordionDetails> </Accordion>
这种方式灵活度高,仅对当前Accordion生效。
内容的提问来源于stack exchange,提问作者Balansoire
相关产品推荐
相关产品推荐

