更改禁用 Material UI 复选框颜色或背景颜色
Change disabled Material UI checkbox color or background color
禁用的未选中复选框看起来有点太微妙,我希望它们具有灰色背景并且光标类型为 not-allowed
.
不幸的是,我不知道如何使用 makeStyles
在复选框上应用这些样式。这就是我当前的代码:
const useStyles = makeStyles((theme) => ({
disabledCheckbox: {
cursor: 'not-allowed',
color: 'grey',
backgroundColor: 'grey',
},
}));
// ...
const App = () => {
const classes = useStyles();
return (
<div>
Disabled:
<Checkbox
disabled={true}
name="Disabled checkbox"
classes={{ disabled: classes.disabledCheckbox }}
/>
</div>
);
};
不幸的是,这没有任何作用,禁用的复选框看起来是一样的。这里有一个demo app to compare a disabled and enabled one.
我做错了什么?如何更改未选中的 MUI 禁用复选框的背景颜色:
有选项可以传递选中的图标和未选中的图标,按样式你需要先 select 图标然后你可以使用 'input:disabled ~ &': 改变禁用复选框的样式,你可以使用像这样的样式以下
const useStyles = makeStyles({
root: {
'&:hover': {
backgroundColor: 'transparent',
},
},
icon: {
borderRadius: 3,
width: 16,
height: 16,
boxShadow: 'inset 0 0 0 1px rgba(16,22,26,.2), inset 0 -1px 0 rgba(16,22,26,.1)',
backgroundColor: '#f5f8fa',
backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.8),hsla(0,0%,100%,0))',
'$root.Mui-focusVisible &': {
outline: '2px auto rgba(19,124,189,.6)',
outlineOffset: 2,
},
'input:hover ~ &': {
backgroundColor: '#ebf1f5',
},
'input:disabled ~ &': {
boxShadow: 'black',
background: 'rgba(0,0,0,0.5)',
},
},
checkedIcon: {
backgroundColor: '#137cbd',
backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))',
'&:before': {
display: 'block',
width: 16,
height: 16,
backgroundImage:
"url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" +
" fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " +
"1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")",
content: '""',
},
'input:hover ~ &': {
backgroundColor: '#106ba3',
},
},
});
参考下面的沙盒
单独使用禁用的 class 并不能提供足够的特异性来覆盖 default styles in IconButton。此外,您不想覆盖整个复选框的背景颜色,否则它会填充整个区域以获得复选框的悬停效果;相反,您只想定位复选框内的图标(即使这也比理想情况稍好——稍后会详细介绍)。
下面是一种定义样式的方法,具有足够的特异性以仅针对图标。覆盖光标需要一些额外的工作,因为默认情况下 Material-UI disables pointer events 在禁用按钮上(Checkbox 利用 SwitchBase,它使用 IconButton,而 IconButton 使用 ButtonBase)并且光标 CSS 没有当禁用指针事件时生效。下面的 CSS 重新打开指针事件,但是需要关闭之前通过 pointerEvents: 'none'
.
阻止的悬停效果
const useStyles = makeStyles((theme) => ({
backgroundColorOnWholeIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root': {
backgroundColor: '#eee',
},
},
},
}));
不幸的是,这仍然不能产生您可能想要的结果。复选框图标的框没有延伸到图标所在的 24px-x-24px 框的边缘,因此当您设置背景颜色时它会溢出框:
为了填充复选框的内部框而不改变该框外的几个像素的颜色,您需要创建一个自定义图标。
下面的代码创建了一个自定义图标,它与默认的未选中图标相同,除了它添加了第二个路径来复制复选框的内部框,没有任何填充,以便可以通过 CSS 定位。
import React from 'react';
import createSvgIcon from '@material-ui/icons/utils/createSvgIcon';
export default createSvgIcon(
<>
<path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" />
<path fill="none" class="innerBox" d="M19 5v14H5V5h14" />
</>,
'CustomUnchecked'
);
然后您可以按如下方式定位此内框:
const useStyles = makeStyles((theme) => ({
backgroundColorOnInnerBoxOfCustomIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root .innerBox': {
fill: '#eee',
},
},
}
}));
为了使其正常工作,您需要在复选框上指定自定义图标。如果您希望所有禁用的复选框看起来像这样,也可以通过主题完成所有这些操作。
下面是一个工作示例,演示了如何通过 makeStyles
和主题执行此操作。
import { Checkbox } from '@material-ui/core';
import {
makeStyles,
createMuiTheme,
ThemeProvider,
} from '@material-ui/core/styles';
import CustomUncheckedIcon from './CustomUnchecked';
import React from 'react';
const useStyles = makeStyles((theme) => ({
backgroundColorOnInnerBoxOfCustomIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root .innerBox': {
fill: '#eee',
},
},
},
backgroundColorOnWholeIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root': {
backgroundColor: '#eee',
},
},
},
}));
const defaultTheme = createMuiTheme();
const theme = createMuiTheme({
props: {
MuiCheckbox: {
icon: <CustomUncheckedIcon />,
},
},
overrides: {
MuiCheckbox: {
root: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
// This syntax is necessary (instead of just ".MuiSvgIcon-root") because of the nested theme causing the global class names to be suffixed)
'& [class*=MuiSvgIcon-root] .innerBox': {
fill: '#eee',
},
},
},
},
},
});
const App = () => {
const classes = useStyles();
return (
<ThemeProvider theme={defaultTheme}>
<div style={{ marginBottom: '16px' }}>
Styled via makeStyles
<br />
Disabled without custom icon:
<Checkbox
className={classes.backgroundColorOnWholeIcon}
disabled={true}
name="Disabled checkbox"
/>
<br />
Disabled:
<Checkbox
className={classes.backgroundColorOnInnerBoxOfCustomIcon}
disabled={true}
icon={<CustomUncheckedIcon />}
name="Disabled checkbox"
/>
Enabled:
<Checkbox
icon={<CustomUncheckedIcon />}
className={classes.backgroundColorOnInnerBoxOfCustomIcon}
name="Enabled checkbox"
/>
</div>
<ThemeProvider theme={theme}>
<div>
Styled via theme
<br />
Disabled:
<Checkbox disabled={true} name="Disabled checkbox" />
Enabled:
<Checkbox name="Enabled checkbox" />
</div>
</ThemeProvider>
</ThemeProvider>
);
};
export default App;
禁用的未选中复选框看起来有点太微妙,我希望它们具有灰色背景并且光标类型为 not-allowed
.
不幸的是,我不知道如何使用 makeStyles
在复选框上应用这些样式。这就是我当前的代码:
const useStyles = makeStyles((theme) => ({
disabledCheckbox: {
cursor: 'not-allowed',
color: 'grey',
backgroundColor: 'grey',
},
}));
// ...
const App = () => {
const classes = useStyles();
return (
<div>
Disabled:
<Checkbox
disabled={true}
name="Disabled checkbox"
classes={{ disabled: classes.disabledCheckbox }}
/>
</div>
);
};
不幸的是,这没有任何作用,禁用的复选框看起来是一样的。这里有一个demo app to compare a disabled and enabled one.
我做错了什么?如何更改未选中的 MUI 禁用复选框的背景颜色:
有选项可以传递选中的图标和未选中的图标,按样式你需要先 select 图标然后你可以使用 'input:disabled ~ &': 改变禁用复选框的样式,你可以使用像这样的样式以下
const useStyles = makeStyles({
root: {
'&:hover': {
backgroundColor: 'transparent',
},
},
icon: {
borderRadius: 3,
width: 16,
height: 16,
boxShadow: 'inset 0 0 0 1px rgba(16,22,26,.2), inset 0 -1px 0 rgba(16,22,26,.1)',
backgroundColor: '#f5f8fa',
backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.8),hsla(0,0%,100%,0))',
'$root.Mui-focusVisible &': {
outline: '2px auto rgba(19,124,189,.6)',
outlineOffset: 2,
},
'input:hover ~ &': {
backgroundColor: '#ebf1f5',
},
'input:disabled ~ &': {
boxShadow: 'black',
background: 'rgba(0,0,0,0.5)',
},
},
checkedIcon: {
backgroundColor: '#137cbd',
backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))',
'&:before': {
display: 'block',
width: 16,
height: 16,
backgroundImage:
"url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" +
" fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " +
"1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")",
content: '""',
},
'input:hover ~ &': {
backgroundColor: '#106ba3',
},
},
});
参考下面的沙盒
单独使用禁用的 class 并不能提供足够的特异性来覆盖 default styles in IconButton。此外,您不想覆盖整个复选框的背景颜色,否则它会填充整个区域以获得复选框的悬停效果;相反,您只想定位复选框内的图标(即使这也比理想情况稍好——稍后会详细介绍)。
下面是一种定义样式的方法,具有足够的特异性以仅针对图标。覆盖光标需要一些额外的工作,因为默认情况下 Material-UI disables pointer events 在禁用按钮上(Checkbox 利用 SwitchBase,它使用 IconButton,而 IconButton 使用 ButtonBase)并且光标 CSS 没有当禁用指针事件时生效。下面的 CSS 重新打开指针事件,但是需要关闭之前通过 pointerEvents: 'none'
.
const useStyles = makeStyles((theme) => ({
backgroundColorOnWholeIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root': {
backgroundColor: '#eee',
},
},
},
}));
不幸的是,这仍然不能产生您可能想要的结果。复选框图标的框没有延伸到图标所在的 24px-x-24px 框的边缘,因此当您设置背景颜色时它会溢出框:
为了填充复选框的内部框而不改变该框外的几个像素的颜色,您需要创建一个自定义图标。
下面的代码创建了一个自定义图标,它与默认的未选中图标相同,除了它添加了第二个路径来复制复选框的内部框,没有任何填充,以便可以通过 CSS 定位。
import React from 'react';
import createSvgIcon from '@material-ui/icons/utils/createSvgIcon';
export default createSvgIcon(
<>
<path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" />
<path fill="none" class="innerBox" d="M19 5v14H5V5h14" />
</>,
'CustomUnchecked'
);
然后您可以按如下方式定位此内框:
const useStyles = makeStyles((theme) => ({
backgroundColorOnInnerBoxOfCustomIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root .innerBox': {
fill: '#eee',
},
},
}
}));
为了使其正常工作,您需要在复选框上指定自定义图标。如果您希望所有禁用的复选框看起来像这样,也可以通过主题完成所有这些操作。
下面是一个工作示例,演示了如何通过 makeStyles
和主题执行此操作。
import { Checkbox } from '@material-ui/core';
import {
makeStyles,
createMuiTheme,
ThemeProvider,
} from '@material-ui/core/styles';
import CustomUncheckedIcon from './CustomUnchecked';
import React from 'react';
const useStyles = makeStyles((theme) => ({
backgroundColorOnInnerBoxOfCustomIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root .innerBox': {
fill: '#eee',
},
},
},
backgroundColorOnWholeIcon: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
'& .MuiSvgIcon-root': {
backgroundColor: '#eee',
},
},
},
}));
const defaultTheme = createMuiTheme();
const theme = createMuiTheme({
props: {
MuiCheckbox: {
icon: <CustomUncheckedIcon />,
},
},
overrides: {
MuiCheckbox: {
root: {
'&.Mui-disabled': {
pointerEvents: 'auto',
'&:hover': {
backgroundColor: 'transparent',
},
cursor: 'not-allowed',
// This syntax is necessary (instead of just ".MuiSvgIcon-root") because of the nested theme causing the global class names to be suffixed)
'& [class*=MuiSvgIcon-root] .innerBox': {
fill: '#eee',
},
},
},
},
},
});
const App = () => {
const classes = useStyles();
return (
<ThemeProvider theme={defaultTheme}>
<div style={{ marginBottom: '16px' }}>
Styled via makeStyles
<br />
Disabled without custom icon:
<Checkbox
className={classes.backgroundColorOnWholeIcon}
disabled={true}
name="Disabled checkbox"
/>
<br />
Disabled:
<Checkbox
className={classes.backgroundColorOnInnerBoxOfCustomIcon}
disabled={true}
icon={<CustomUncheckedIcon />}
name="Disabled checkbox"
/>
Enabled:
<Checkbox
icon={<CustomUncheckedIcon />}
className={classes.backgroundColorOnInnerBoxOfCustomIcon}
name="Enabled checkbox"
/>
</div>
<ThemeProvider theme={theme}>
<div>
Styled via theme
<br />
Disabled:
<Checkbox disabled={true} name="Disabled checkbox" />
Enabled:
<Checkbox name="Enabled checkbox" />
</div>
</ThemeProvider>
</ThemeProvider>
);
};
export default App;