主题化组件
了解如何在主题级别将自定义样式应用于组件。
组件标识符
如果您之前使用过 Material UI,您可能对这种技术很熟悉。要在主题中自定义特定组件,请在 components
节点内指定组件标识符 (Joy{ComponentImportName}
)。
- 使用
defaultProps
更改组件的默认 React props。 - 使用
styleOverrides
将样式应用于每个组件插槽。- 每个 Joy UI 组件都包含
root
插槽。
- 每个 Joy UI 组件都包含
访问 components.d.ts
文件以查看所有组件标识符。
import { CssVarsProvider, extendTheme } from '@mui/joy/styles';
const theme = extendTheme({
components: {
JoyChip: {
defaultProps: {
size: 'sm',
},
styleOverrides: {
root: {
borderRadius: '4px',
},
},
},
},
});
function App() {
return <CssVarsProvider theme={theme}>...</CssVarsProvider>;
}
主题默认 props
在主题中指定为 defaultProps
的值会影响组件的所有实例
extendTheme({
components: {
JoyIconButton: {
defaultProps: {
variant: 'outlined',
color: 'neutral',
},
},
},
});
// This is the same as:
// <IconButton variant="outlined" color="neutral">
<IconButton>...</IconButton>;
主题样式覆盖
根据 props 更改样式
要更改给定 prop 的样式,请使用回调作为样式覆盖的值。该参数包含 theme
和 ownerState
(props)。
extendTheme({
components: {
JoyChip: {
styleOverrides: {
// `ownerState` contains the component props and internal state
root: ({ ownerState, theme }) => ({
...(ownerState.size === 'sm' && {
borderRadius: theme.vars.radius.xs,
}),
}),
},
},
},
});
我们建议使用来自 theme.vars.*
的 CSS 变量,因为它具有更好的调试体验,并且在某些情况下性能更高。
样式还可以包含任何 CSS 选择器(支持嵌套选择器),如下所示
extendTheme({
components: {
JoyChip: {
styleOverrides: {
root: ({ ownerState, theme }) => ({
...(ownerState.variant === 'solid' &&
ownerState.clickable && {
color: 'rgba(255 255 255 / 0.72)',
'&:hover': {
color: '#fff',
},
}),
}),
},
},
},
});
根据状态更改样式
当 Joy UI 组件处于给定状态(例如 selected
、disabled
、focusVisible
等)时,它们会增加样式的 CSS 特异性。
要覆盖特定状态的样式,请使用组件的类选择器,方法是导入其名称(驼峰式)后跟 Classes
。
import { listItemButtonClasses } from '@mui/joy/ListItemButton';
extendTheme({
components: {
JoyListItemButton: {
styleOverrides: {
root: {
[`&.${listItemButtonClasses.selected}`]: {
color: 'rgba(255 255 255 / 0.7)',
},
},
},
},
},
});
可用的状态有:active
、checked
、completed
、disabled
、error
、expanded
、focused
、focusVisible
、readOnly
、required
、selected
。
扩展颜色
以下代码片段说明了如何为组件提供 primary
、success
、info
、danger
、neutral
和 warning
之外的其他颜色。
请注意,通过创建新颜色,您将自动选择退出全局变体功能,该功能使您可以精细地控制 CSS 属性,如 color
、background
和 border
。
下面的示例扩展了 Button 颜色以包括 secondary
值
extendTheme({
components: {
JoyButton: {
styleOverrides: {
root: ({ ownerState, theme }) => ({
...(ownerState.color === 'secondary' && {
color: theme.vars.palette.text.secondary,
backgroundColor: theme.vars.palette.background.level1,
}),
}),
},
},
},
});
一旦这些值如上所述定义,您就可以直接在 Button 组件的实例上使用它们
<Button color="secondary">Secondary color</Button>
<Button color="tertiary">Tertiary color</Button>
TypeScript
需要模块扩展才能将值传递给组件的 color
prop。
接口格式为 {ComponentName}PropsColorOverrides
,这对于所有 Joy UI 组件都是相同的
// This part could be declared in your theme file
declare module '@mui/joy/Button' {
interface ButtonPropsColorOverrides {
secondary: true;
tertiary: true;
}
}
// typed-safe
<Button color="secondary" />
<Button color="tertiary" />
扩展尺寸
以下代码片段说明了如何为组件提供 sm
、md
和 lg
之外的其他尺寸。我们建议遵循已建立的“T 恤尺寸”命名约定(例如 xs
、xl
、xxl
等),以保持与所有其他 props 的一致性。
下面的示例扩展了 Button 尺寸以包括 xs
和 xl
值
extendTheme({
components: {
JoyButton: {
styleOverrides: {
root: ({ ownerState, theme }) => ({
...(ownerState.size === 'xs' && {
'--Icon-fontSize': '1rem',
'--Button-gap': '0.25rem',
minHeight: 'var(--Button-minHeight, 1.75rem)',
fontSize: theme.vars.fontSize.xs,
paddingBlock: '2px',
paddingInline: '0.5rem',
}),
...(ownerState.size === 'xl' && {
'--Icon-fontSize': '2rem',
'--Button-gap': '1rem',
minHeight: 'var(--Button-minHeight, 4rem)',
fontSize: theme.vars.fontSize.xl,
paddingBlock: '0.5rem',
paddingInline: '2rem',
}),
}),
},
},
},
});
一旦这些值如上所述定义,您就可以直接在 Button 组件的实例上使用它们
<Button size="xs">Extra small</Button>
<Button size="xl">Extra large</Button>
用于扩展尺寸的属性应仅与组件的密度或尺寸有关。要了解如何扩展变体属性,请查看本文档中的扩展变体部分。
TypeScript
需要模块扩展才能将值传递给组件的 size
prop。
接口格式为 {ComponentName}PropsSizeOverrides
,这对于所有 Joy UI 组件都是相同的
// This part could be declared in your theme file
declare module '@mui/joy/Button' {
interface ButtonPropsSizeOverrides {
xs: true;
xl: true;
}
}
// typed-safe
<Button size="xs" />
<Button size="xl" />
扩展变体
以下代码片段显示了如何扩展颜色属性的组件变体。请注意,通过创建新变体,您将自动选择退出全局变体功能,该功能使您可以精细地控制 CSS 属性,如 color
、background
和 border
。
此示例扩展了 Sheet 变体以包括名为 glass
的自定义值
extendTheme({
components: {
JoySheet: {
styleOverrides: {
root: ({ ownerState, theme }) => ({
...(ownerState.variant === 'glass' && {
color: theme.vars.palette.text.primary,
background: 'rgba(255, 255, 255, 0.14)',
backdropFilter: 'blur(5px)',
border: '1px solid rgba(255, 255, 255, 0.3)',
boxShadow: '0 4px 30px rgba(0, 0, 0, 0.1)',
}),
}),
},
},
},
});
一旦值如上所述定义,您就可以直接在 Sheet 组件的实例上使用它
<Sheet variant="glass">Glassmorphism</Sheet>
TypeScript
需要模块扩展才能将值传递给组件的 variant
prop。
接口格式为 {ComponentName}PropsSizeOverrides
,这对于所有 Joy UI 组件都是相同的
// This part could be declared in your theme file
declare module '@mui/joy/Sheet' {
interface SheetPropsVariantOverrides {
glass: true;
}
}
// typed-safe
<Sheet variant="glass" />;
每种模式的不同样式
要为每种模式(浅色和深色)指定与默认主题中定义的值不同的值,请使用 CSS 属性选择器。
Joy UI 将带有当前配色方案的 data-*
属性附加到 DOM(默认情况下为 HTML)。您可以使用 theme.getColorSchemeSelector
实用程序来更改组件样式。
下面的示例说明了如何在浅色模式下更改 boxShadow
token 的强度,同时在深色模式下完全删除它
extendTheme({
components: {
JoyChip: {
styleOverrides: {
root: ({ ownerState, theme }) => ({
// for the default color scheme (light)
boxShadow: theme.vars.shadow.sm,
// the result is `[data-joy-color-scheme="dark"] &`
[theme.getColorSchemeSelector('dark')]: {
boxShadow: 'none',
},
}),
},
},
},
});
如果您定义了自定义配色方案,此方法也适用。但是,请注意,它会创建额外的 CSS 特异性,当父组件想要覆盖其子组件样式时,这可能会很麻烦。