mantine-react-component-dev

Mantine React Component Development Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "mantine-react-component-dev" with this command: npx skills add gfazioli/mantine-select-stepper/gfazioli-mantine-select-stepper-mantine-react-component-dev

Mantine React Component Development Skill

When to Use This Skill

Apply this skill when working on:

  • Component Development: Creating or editing React components built on Mantine's factory pattern

  • TypeScript Patterns: Implementing polymorphic components, type-safe props, and CSS variables

  • Styles API: Configuring component styling through Mantine's Styles API system (selectors, vars, modifiers)

  • Component Composition: Building compound components with static sub-components (e.g., Component.Target )

  • Context Management: Implementing safe context patterns for component state sharing

  • Accessibility: Ensuring ARIA compliance, keyboard navigation, and focus management

  • Code Review: Maintaining consistency with established patterns and conventions

  • Documentation: Writing component demos, MDX docs, and API references

Project Structure

Components are organized in a monorepo workspace structure:

/package/src/ : Main component source code

  • ComponentName.tsx : Main component implementation

  • ComponentName.module.css : Component-scoped styles

  • ComponentName.context.ts : Context providers (if needed)

  • ComponentName.errors.ts : Error messages

  • ComponentName.test.tsx : Jest + Testing Library tests

  • ComponentName.story.tsx : Storybook stories

  • SubComponent/SubComponent.tsx : Sub-components in their own folders

  • index.ts : Public exports

/docs/ : Next.js documentation site

  • demos/ComponentName.demo.*.tsx : Interactive demos

  • styles-api/ComponentName.styles-api.ts : Styles API metadata

  • docs.mdx : Main documentation page

Refer to existing components in ./package/src/ for implementation examples.

TypeScript Patterns

Component Factory Pattern

All components use Mantine's polymorphic factory pattern.

import { polymorphicFactory, PolymorphicFactory, useProps, useStyles, createVarsResolver } from '@mantine/core';

export type ComponentStylesNames = 'root' | 'element'; export type ComponentCssVariables = { root: '--custom-var' | '--another-var'; };

export interface ComponentProps extends BoxProps, StylesApiProps<ComponentFactory> { /** Prop description */ customProp?: string; }

export type ComponentFactory = PolymorphicFactory<{ props: ComponentProps; defaultComponent: 'div'; defaultRef: HTMLDivElement; stylesNames: ComponentStylesNames; vars: ComponentCssVariables; staticComponents: { SubComponent: typeof SubComponent; }; }>;

const defaultProps: Partial<ComponentProps> = { customProp: 'default', };

const varsResolver = createVarsResolver<ComponentFactory>((_, { customProp }) => ({ root: { '--custom-var': customProp, }, }));

export const Component = polymorphicFactory<ComponentFactory>((_props, ref) => { const props = useProps('Component', defaultProps, _props); const { classNames, className, style, styles, unstyled, vars, customProp, ...others } = props;

const getStyles = useStyles<ComponentFactory>({ name: 'Component', classes, props, className, style, classNames, styles, unstyled, vars, varsResolver, });

return ( <Box ref={ref} {...getStyles('root')} {...others}> {/* component content */} </Box> ); });

Component.displayName = '@your-scope/Component'; Component.SubComponent = SubComponent;

Key Requirements:

  • Use unknown for unconstrained generics; narrow with type guards

  • Avoid any ; use React.ReactNode for children

  • Define explicit type aliases for style names and CSS variables

  • Use useProps hook for default prop merging

  • Implement varsResolver for CSS custom properties

Context Pattern

For components requiring state sharing, use Mantine's safe context pattern.

import { createSafeContext } from '@mantine/core'; import { COMPONENT_ERRORS } from './Component.errors';

interface ComponentContext { state: boolean; setState: (value: boolean) => void; }

export const [ComponentContextProvider, useComponentContext] = createSafeContext<ComponentContext>( COMPONENT_ERRORS.context );

Error Definitions in Component.errors.ts :

export const COMPONENT_ERRORS = { context: 'Component was not found in the tree', validation: 'Specific validation message', };

Sub-Component Pattern

Sub-components access parent context and enforce constraints.

import { forwardRef, useProps, isElement, createEventHandler } from '@mantine/core'; import { useComponentContext } from '../Component.context';

export interface SubComponentProps { children: React.ReactNode; refProp?: string; }

export const SubComponent = forwardRef<HTMLElement, SubComponentProps>((props, ref) => { const { children, ...others } = useProps('SubComponent', {}, props);

if (!isElement(children)) { throw new Error(COMPONENT_ERRORS.children); }

const ctx = useComponentContext(); const onClick = createEventHandler(children.props.onClick, () => ctx.toggle());

return cloneElement(children, { onClick, ref }); });

Styles API

Every component exposes a Styles API for customization. Define in ./docs/styles-api/Component.styles-api.ts :

import type { ComponentFactory } from '@your-scope/component'; import type { StylesApiData } from '../components/styles-api.types';

export const ComponentStylesApi: StylesApiData<ComponentFactory> = { selectors: { root: 'Root element', element: 'Specific child element', }, vars: { root: { '--custom-var': 'Controls custom behavior', '--another-var': 'Controls another aspect', }, }, modifiers: [ { modifier: 'data-active', selector: 'root', condition: 'active prop is set' } ], };

CSS Module (Component.module.css ):

.root { /* Use CSS custom properties from varsResolver */ property: var(--custom-var, fallback); }

.element { /* Scoped class name */ }

/* Data attribute modifiers / .root[data-active] { / Active state */ }

Component Guidelines

Controlled vs Uncontrolled State

Use @mantine/hooks useUncontrolled for dual-mode state:

import { useUncontrolled } from '@mantine/hooks';

const [value, setValue] = useUncontrolled({ value: props.value, defaultValue: props.defaultValue, finalValue: undefined, onChange: props.onChange, });

Lifecycle Hooks

Use useDidUpdate from @mantine/hooks for effect-on-update patterns:

import { useDidUpdate } from '@mantine/hooks';

useDidUpdate(() => { props.onStateChange?.(state); }, [state]);

Props Validation

Validate props at runtime when type system isn't enough:

if (React.Children.count(children) !== 2) { throw new Error('Component requires exactly two children'); }

Ref Forwarding

Always support ref forwarding for component composition:

export const Component = polymorphicFactory<ComponentFactory>((_props, ref) => { return <Box ref={ref} {...others} />; });

Coding Standards

Import Order

Prettier auto-sorts imports per ./.prettierrc.mjs :

  • CSS imports

  • React

  • Next.js (if applicable)

  • Built-in modules

  • Third-party modules

  • @mantine/* packages

  • Local imports (parent then sibling)

  • CSS modules last

Formatting

  • Print Width: 100 characters

  • Quotes: Single quotes

  • Trailing Commas: ES5-style

  • MDX: 70 character print width

Run npm run prettier:write before committing.

Linting

ESLint config extends eslint-config-mantine :

import mantine from 'eslint-config-mantine'; import tseslint from 'typescript-eslint';

export default tseslint.config(...mantine, { ignores: ['/.next/', '**/*.{mjs,cjs,js,d.ts,d.mts}'] });

Run npm run lint to check all rules.

TypeScript Configuration

Primary config (./tsconfig.json ):

  • Target: ES2015

  • Module: ESNext with Node resolution

  • JSX: React (classic runtime)

  • Strict: Enabled (via mantine config)

  • Skip Lib Check: true (for faster builds)

Build config (tsconfig.build.json ) isolates compilation scope.

Testing

Use @mantine-tests/core renderer with Testing Library.

import React from 'react'; import { render } from '@mantine-tests/core'; import { Component } from './Component';

describe('Component', () => { it('renders without crashing', () => { const { container } = render(<Component>Content</Component>); expect(container).toBeTruthy(); });

it('applies custom className', () => { const { container } = render(<Component className="custom" />); expect(container.querySelector('.custom')).toBeTruthy(); });

it('forwards ref', () => { const ref = React.createRef<HTMLDivElement>(); render(<Component ref={ref} />); expect(ref.current).toBeTruthy(); }); });

Run tests with npm run jest .

Documentation

Demos

Create interactive demos in ./docs/demos/ :

// Component.demo.basic.tsx import { Component } from '@your-scope/component'; import { MantineDemo } from '@docs/components';

const code = ` import { Component } from '@your-scope/component';

function Demo() { return <Component>Content</Component>; } `;

export const basic: MantineDemo = { type: 'code', component: Demo, code, };

Configurator demos use MantineDemo type 'configurator' with controls object.

MDX Pages

Main docs page at ./docs/docs.mdx :

import { InstallScript } from './components/InstallScript/InstallScript'; import * as demos from './demos';

Installation

<InstallScript packages="@your-scope/component" />

Usage

<Demo data={demos.basic} />

Props

<PropsTable component="Component" />

Styles API

<StylesApiTable component="Component" />

Refer to existing documentation structure in /docs for consistency.

Accessibility

ARIA Patterns

Keyboard Navigation

  • Ensure all interactive elements are keyboard-accessible

  • Use tabIndex={-1} for programmatic focus management

  • Implement arrow-key navigation for composite widgets

Focus Management

import { useFocusTrap } from '@mantine/hooks';

const focusTrapRef = useFocusTrap(active);

Data Attributes for State

Expose component state via data attributes for CSS and screen readers:

<div data-active={isActive} data-disabled={disabled} />

Security and Maintenance

No Hardcoded Secrets

  • Never commit API keys, tokens, or credentials

  • Use environment variables for sensitive configuration

  • Exclude .env files in .gitignore

Dependency Hygiene

  • Keep @mantine/core and @mantine/hooks versions in sync (see ./package/package.json )

  • Use peerDependencies for React and Mantine packages

  • Run npm run syncpack to verify version consistency

Least Privilege

  • Minimize scope of React Context providers

  • Avoid global state; prefer component-level state

  • Use createSafeContext to enforce provider boundaries

Edge Cases and Troubleshooting

Module Resolution

  • Ensure all imports use relative paths for local modules

  • Check package.json exports field for correct entry points

  • Verify tsconfig.json paths if using aliases

CSS Modules

  • Class names are auto-scoped via hash-css-selector (see ./rollup.config.mjs )

  • Import CSS modules as import classes from './Component.module.css'

  • Use getStyles helper for className merging

Polymorphic Components

  • Default component is div ; override with component prop

  • Ref type must match defaultRef in factory definition

  • Props are merged: BoxProps & ComponentProps & { component?: any }

Testing Library Queries

  • Prefer getByRole over getByTestId

  • Use screen for global queries or container for scoped

  • Mock window.matchMedia if needed (see ./jsdom.mocks.cjs )

Storybook Integration

  • Stories go in Component.story.tsx alongside component

  • Use CSF3 format with Meta and StoryObj types

  • Stories auto-generate docs from TypeScript types

File Organization

Maintain consistent file structure per component:

package/src/ ├── Component.tsx # Main component ├── Component.module.css # Scoped styles ├── Component.context.ts # Context (if needed) ├── Component.errors.ts # Error constants ├── Component.test.tsx # Tests ├── Component.story.tsx # Storybook ├── SubComponent/ │ └── SubComponent.tsx # Sub-component └── index.ts # Public API

Public API (index.ts ):

export { Component } from './Component'; export type { ComponentProps, ComponentFactory } from './Component';

Commit Hygiene

  • Run npm run test before committing (includes prettier, typecheck, lint, jest)

  • Write clear commit messages: fix: resolve prop merging issue or feat: add keyboard navigation

  • Avoid committing generated files (dist/ , .next/ , out/ )

  • Use .gitignore to exclude build artifacts

References

See ./references/ for indexed documentation pointers.

Related Files

  • ESLint Config

  • Prettier Config

  • TypeScript Config

  • Rollup Config

  • Package Source

  • Documentation

  • Contributing Guide

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

dokidoki

Control interactive BLE devices (scan/connect/playback/timeline) from terminal.

Registry SourceRecently Updated
Coding

code

Comprehensive code review assistant that analyzes code quality, identifies bugs, suggests improvements, and ensures adherence to best practices. Use when rev...

Registry SourceRecently Updated
Coding

Markdown Lint

Use this skill immediately when the user needs to: set up markdownlint-cli2 and pre-commit hooks in a repository, fix or batch-repair markdownlint errors lik...

Registry SourceRecently Updated
Coding

Google Seo Assistant

A client-facing SEO assistant grounded in Google's official SEO Starter Guide. Use this skill whenever a user mentions SEO, search rankings, Google visibilit...

Registry SourceRecently Updated
1301gco