mcpField
M
mantine-custom-components

mantine-custom-components

github.com/mantinedev开发643.7k 次安装3 周前更新
代码仓库

关于 mantine-custom-components

面向使用 Mantine 9.x 构建自定义组件的开发者,涵盖组件结构、样式、变体和主题集成,并说明如何选择合适的 factory 模式。

主要功能

  1. 01Mantine 9.x 组件模板
  2. 02Styles API 属性与类名
  3. 03变体、尺寸与 CSS 变量
  4. 04主题颜色和尺寸辅助函数
  5. 05Factory 模式与组件类型
  6. 06主题扩展与属性预设

适用场景

  1. 01创建自定义 Mantine 组件
  2. 02添加变体和尺寸样式
  3. 03将组件默认值接入主题
  4. 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 和 attributes props,以及主题中 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 页面

评论

支持 Markdown