Mantine Custom Components Skill
Written for Mantine 9.x.
Component template
ref is a regular prop in React 19: it arrives in props and reaches the root element through ...others.
What you get without extra code:
- Every element rendered with
getStyles('selector')gets the static classmantine-MyComponent-selector. classNames,styles,varsandattributesprops, and the same keys inMyComponent.extend()in the theme.unstyledremoves the CSS module classes. Static classes and the CSS variables on the root stay.MyComponent.extend()andMyComponent.withProps()static functions.withPropspresets props at runtime but does not change types: a required prop stays required for TypeScript, so make props you intend to preset optional.
Variants and sizes
Pass variant and size to Box: it sets data-variant and data-size attributes to style in CSS.
Passing variant to getStyles additionally applies the root--{variant} class when the CSS module defines one:
Sizes driven by one size prop: define the token values in CSS and select one with getSize. A
number or any CSS value passed as size is used as is (getSize(60, 'x') returns calc(3.75rem * var(--mantine-scale))).
For colors that follow the theme, resolve them in the vars resolver with
theme.variantColorResolver({ color: color || theme.primaryColor, theme, variant: variant || 'filled', autoContrast })
— it returns background, hover and color as colors and border as a full border shorthand value
(1px solid transparent). It knows the variants filled, light, outline, subtle, transparent, white and
default; autoContrast: undefined falls back to theme.autoContrast. For a single color use
getThemeColor(color, theme): it accepts 'blue', 'teal.7' and CSS colors.
Because the resolver comes from the theme, an app can add its own variant (variant="danger") or
recolor an existing one without touching the component. Do not redeclare variant in your props
interface: StylesApiProps already types it as your variants plus any string.
Factory variant — which to use
Use polymorphicFactory sparingly — it adds TypeScript overhead and slows IDE autocomplete.
Every factory component also accepts renderRoot={(props) => <a {...props} />} as an alternative to component.
Factory type fields
Theme integration
Users and the theme can override defaults via Component.extend():
In theme.components, sub-components are registered without the dot: MyCardSection: MyCard.Section.extend({ defaultProps }).
References
Read the part that matches the task before writing code:
references/patterns.md[blocked] — complete examples. Read "Compound component with context" for components with sub-components (Card.Section), "Wrapping a Mantine component" when the component renders an existing Mantine input or component inside and must forwardclassNames/stylesto it, "Components that share theme configuration" for a family of components with a common base, "Converting an existing component" when migrating aforwardRefcomponent with inline styles, "Polymorphic component" for acomponentprop, "Generic component" for props that depend on a type parameter, "Theme integration" forextendandwithPropsreferences/api.md[blocked] — read it for any component beyond the template above: it is the only place that documentsgetStylesoptions (focusable), themodprop, theme helper outputs,MantineThemeProviderand what theme functions receive. Every function and type:factoryvariants,useProps,useStylesandgetStylesoptions,createVarsResolver,createSafeContext,StylesApiProps,CompoundStylesApiProps,BoxProps(includingmod),ElementProps, theme helpers (getSize,getRadius,getThemeColor...)
Looking things up
If the references do not cover what you need, do not guess:
- If the Mantine MCP server (
@mantine/mcp-server) is connected, usesearch_docs,get_item_docandget_api - Otherwise fetch
https://mantine.dev/llms.txtand open the Styles API, variants and sizes, and custom components pages


