关于 mantine-custom-components
面向使用 Mantine 9.x 构建自定义组件的开发者,涵盖组件结构、样式、变体和主题集成,并说明如何选择合适的 factory 模式。
主要功能
- 01Mantine 9.x 组件模板
- 02Styles API 属性与类名
- 03变体、尺寸与 CSS 变量
- 04主题颜色和尺寸辅助函数
- 05Factory 模式与组件类型
- 06主题扩展与属性预设
适用场景
- 01创建自定义 Mantine 组件
- 02添加变体和尺寸样式
- 03将组件默认值接入主题
- 04为多态或泛型属性选择 factory
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mantinedev/ skills --skill mantine-custom-components安装后在 Claude Code 中输入/mantine-custom-components确认已加载。
附带文件references/api.mdreferences/patterns.md
详细介绍
Mantine 自定义组件技能
适用于 Mantine 9.x。
组件模板
import {
Box, BoxProps, createVarsResolver, ElementProps,
factory, Factory, getRadius, MantineRadius,
StylesApiProps, useProps, useStyles,
} from '@mantine/core';
import classes from './MyComponent.module.css';
export type MyComponentStylesNames = 'root' | 'inner';
export type MyComponentVariant = 'filled' | 'outline';
export type MyComponentCssVariables = { root: '--my-radius' };
export interface MyComponentProps
extends BoxProps, StylesApiProps<MyComponentFactory>, ElementProps<'div'> {
radius?: MantineRadius;
}
export type MyComponentFactory = Factory<{
props: MyComponentProps;
ref: HTMLDivElement;
stylesNames: MyComponentStylesNames;
vars: MyComponentCssVariables;
variant: MyComponentVariant;
}>;
const defaultProps = {} satisfies Partial<MyComponentProps>;
const varsResolver = createVarsResolver<MyComponentFactory>((_theme, { radius }) => ({
// undefined leaves the variable unset, so the CSS fallback (theme default radius) applies
root: { '--my-radius': radius === undefined ? undefined : getRadius(radius) },
}));
export const MyComponent = factory<MyComponentFactory>((_props) => {
const props = useProps('MyComponent', defaultProps, _props);
const { classNames, className, style, styles, unstyled, vars, attributes, radius, ...others } = props;
const getStyles = useStyles<MyComponentFactory>({
name: 'MyComponent', classes, props,
className, style, classNames, styles, unstyled, vars, attributes, varsResolver,
});
return <Box {...getStyles('root')} {...others} />;
});
MyComponent.displayName = 'MyComponent';
MyComponent.classes = classes;
MyComponent.varsResolver = varsResolver;
/* MyComponent.module.css */
.root {
border-radius: var(--my-radius, var(--mantine-radius-default));
}
在 React 19 中,ref 是一个常规 prop:它会传入 props,并通过 ...others 传递到根元素。
无需额外编写代码即可获得:
- 使用
getStyles('selector')渲染的每个元素都会获得静态类mantine-MyComponent-selector。 classNames、styles、vars和attributesprops,以及主题中MyComponent.extend()的同名键。unstyled会移除 CSS 模块类。根元素上的静态类和 CSS 变量仍会保留。MyComponent.extend()和MyComponent.withProps()静态函数。withProps会在运行时预设 props,但不会更改类型:对 TypeScript 来说,必需的 prop 仍是必需的,因此应将你打算预设的 props 设为可选。
变体和尺寸
将 variant 和 size 传给 Box:它会设置 data-variant 和 data-size 属性,供 CSS 设置样式。
将 variant 传给 getStyles,还会应用 root--{variant} 类(前提是 CSS 模块定义了该类):
const { variant, size, ...others } = props;
<Box variant={variant} size={size} {...getStyles('root', { variant })} {...others} />
.root {
&[data-variant='outline'] { border: 1px solid var(--my-color); }
&[data-size='lg'] { height: 50px; }
}
由一个 size prop 控制的尺寸:在 CSS 中定义令牌值,并使用 getSize 选择其中一个。作为 size 传入的数字或任何 CSS 值都会按原样使用(getSize(60, 'x') 会返回 calc(3.75rem * var(--mantine-scale)))。
root: { '--card-padding': getSize(size, 'card-padding'), '--card-fz': getFontSize(size) },
.root {
--card-padding-sm: 12px;
--card-padding-md: 16px;
--card-padding-lg: 24px;
padding: var(--card-padding, var(--card-padding-md));
}
对于遵循主题的颜色,请在 vars 解析器中使用
theme.variantColorResolver({ color: color || theme.primaryColor, theme, variant: variant || 'filled', autoContrast })
解析颜色——它会返回 background、hover 和 color 颜色,以及作为完整 border 简写值的 border
(1px solid transparent)。它支持 filled、light、outline、subtle、transparent、white 和
default 这些变体;autoContrast: undefined 会回退为 theme.autoContrast。若只需一种颜色,请使用
getThemeColor(color, theme):它接受 'blue'、'teal.7' 和 CSS 颜色。
.root {
background-color: var(--my-bg);
color: var(--my-color);
border: var(--my-bd); /* the whole shorthand, not border-color */
}
由于解析器来自主题,应用可以添加自定义变体(variant="danger"),或在不修改组件的情况下重新着色现有变体。不要在 props 接口中重新声明 variant:StylesApiProps 已将其类型定义为你的变体及任意字符串。
Factory 变体——选择使用哪一种
| 场景 | Factory 函数 | 类型 |
|---|---|---|
| 标准组件 | factory() | Factory<{}> |
支持 component prop(多态) | polymorphicFactory() | PolymorphicFactory<{}> — 添加 defaultComponent 和 defaultRef |
props 根据泛型变化(例如 multiple) | genericFactory() | Factory<{ signature: ... }> |
谨慎使用 polymorphicFactory——它会增加 TypeScript 开销,并降低 IDE 自动补全的速度。
每个 Factory 组件也都接受 renderRoot={(props) => <a {...props} />},作为 component 的替代方案。
Factory 类型字段
Factory<{
props: MyComponentProps; // required
ref: HTMLDivElement; // element type for the forwarded ref
stylesNames: 'root' | 'inner'; // union of Styles API selectors
vars: { root: '--my-var' }; // CSS variable map per selector
variant: 'filled' | 'outline'; // accepted variant strings
staticComponents: { // sub-components (compound pattern)
Item: typeof MyComponentItem;
};
compound: true; // only for sub-components; disables theme classNames/styles/vars
ctx: { stepsCount: number }; // only if needed; passed to classNames/styles/vars functions as third arg
signature?: (...) => JSX.Element; // only for genericFactory
}>
主题集成
用户和主题可以通过 Component.extend() 覆盖默认值:
const theme = createTheme({
components: {
MyComponent: MyComponent.extend({
defaultProps: { radius: 'xl' },
classNames: { root: 'my-root' },
styles: { root: { color: 'red' } },
vars: (_theme, props) => ({ root: { '--my-radius': getRadius(props.radius) } }),
}),
},
});
在 theme.components 中注册子组件时,名称中不带点:MyCardSection: MyCard.Section.extend({ defaultProps })。
参考资料
编写代码前,请阅读与任务对应的部分:
references/patterns.md— 完整示例。对于带有子组件(Card.Section)的组件,请阅读“Compound component with context”;对于在内部渲染现有 Mantine 输入组件或其他组件、且必须向其传递classNames/styles的组件,请阅读“Wrapping a Mantine component”;对于共享主题配置的一组组件,请阅读“Components that share theme configuration”;对于迁移带有内联样式的forwardRef组件,请阅读“Converting an existing component”;对于component属性,请阅读“Polymorphic component”;对于属性依赖类型参数的组件,请阅读“Generic component”;对于extend和withProps,请阅读“Theme integration”references/api.md— 对于超出上述模板范围的组件,请阅读此文档:只有这里说明了getStyles选项(focusable)、mod属性、主题辅助函数的返回值、MantineThemeProvider以及主题函数接收的参数。涵盖的函数和类型包括:factory变体、useProps、useStyles和getStyles选项、createVarsResolver、createSafeContext、StylesApiProps、CompoundStylesApiProps、BoxProps(包括mod)、ElementProps、主题辅助函数(getSize、getRadius、getThemeColor……)
查找资料
如果参考资料中没有所需内容,请勿猜测:
- 如果已连接 Mantine MCP 服务(
@mantine/mcp-server),请使用search_docs、get_item_doc和get_api - 否则,请获取
https://mantine.dev/llms.txt,并打开 Styles API、variants and sizes 以及 custom components 页面