Mantine Components
Mantine is a modern React component library with accessible, customizable components. It focuses on developer experience, theming, and responsive design. FormEngine includes Mantine components as an alternative to Material UI and React Suite in the component library.
Getting Started with Mantine Components
Installation
Mantine components are available in the @react-form-builder/components-mantine package:
npm install @react-form-builder/components-mantine
Peer dependencies (Mantine packages) must also be installed as required by your usage:
npm install @mantine/core @mantine/dates
# Optional: @mantine/dropzone @mantine/tiptap
Basic Mantine setup
Mantine styles must be imported manually. This is different from React Suite where the builder can use a style-loader helper
withCssLoader to inject styles automatically.
import {builderView, view} from '@react-form-builder/components-mantine'
import {FormBuilder} from '@react-form-builder/designer'
import {FormViewer} from '@react-form-builder/core'
import '@mantine/core/styles.css'
import '@mantine/dates/styles.css'
// Optional packages:
// import '@mantine/dropzone/styles.css'
// import '@mantine/tiptap/styles.css'
const getForm = () => JSON.stringify({
form: {
key: 'Screen',
type: 'Screen',
children: []
}
})
export const MantineBuilderBasic = () => <FormBuilder view={builderView} getForm={getForm}/>
export const MantineViewerBasic = () => <FormViewer view={view} getForm={getForm}/>
For setup details, see Mantine Getting Started.
Basic styling and theming
Mantine default color palettes (gray, grape, blue and others) follow the
Open Color scale in the default theme.
Show code
function App() { const [mode, setMode] = useState('vibrant') const previewRootRef = useRef(null) const colorByMode = {vibrant: 'cyan', contrast: 'grape', extreme: 'orange'} const themeMap = { vibrant: createTheme({ fontFamily: 'Open Sans, sans-serif', primaryColor: 'cyan', defaultRadius: 'md' }), contrast: createTheme({ fontFamily: 'Georgia, serif', primaryColor: 'grape', defaultRadius: 'xl' }), extreme: createTheme({ primaryColor: 'orange', primaryShade: {light: 7, dark: 4}, fontFamily: '"Impact", "Arial Black", sans-serif', defaultRadius: 'xs' }) } const form = useMemo(() => ({ form: { key: 'Screen', type: 'Screen', children: [ { key: 'title', type: 'MtTitle', props: { order: {value: 3}, color: {value: colorByMode[mode]}, children: {value: 'Sign up'} } }, { key: 'email', type: 'MtTextInput', props: { label: {value: 'Email'}, placeholder: {value: 'you@example.com'} } }, { key: 'age', type: 'MtSlider', props: { label: {value: 'Age'}, color: {value: colorByMode[mode]}, min: {value: 13}, max: {value: 100}, step: {value: 1} } }, { key: 'terms', type: 'MtCheckbox', props: { label: {value: 'I agree to terms and privacy policy'}, color: {value: colorByMode[mode]} } }, { key: 'submit', type: 'MtButton', props: { children: {value: 'Create account'}, color: {value: colorByMode[mode]}, fullWidth: {value: true} } } ] } }), [mode]) const getForm = useCallback(() => JSON.stringify(form), [form]) return ( <div id='mantine-live-root-theme' ref={previewRootRef} style={{display: 'grid', gap: 12}}> <label> Theme preset:{' '} <select value={mode} onChange={(event) => setMode(event.target.value)}> <option value='vibrant'>vibrant</option> <option value='contrast'>contrast</option> <option value='extreme'>extreme</option> </select> </label> <MantineProvider theme={themeMap[mode]} cssVariablesSelector='#mantine-live-root-theme' getRootElement={() => previewRootRef.current ?? undefined} withGlobalClasses={false} > <FormViewer view={mantineView} getForm={getForm}/> </MantineProvider> </div> ) } render(<App />)
For theme and provider options, see:
Light and dark theme handling
In Mantine's color scheme model, MantineProvider is the central manager. It controls light/dark/auto behavior with
defaultColorScheme, persists the selected value through the manager, and applies the resolved mode through the
data-mantine-color-scheme attribute used by component styles.
Use defaultColorScheme, forceColorScheme, and colorSchemeManager on MantineProvider for app-wide behavior. For system preference
awareness, use useColorScheme from @mantine/hooks.
import {localStorageColorSchemeManager, MantineProvider} from '@mantine/core'
import {view} from '@react-form-builder/components-mantine'
import {FormViewer} from '@react-form-builder/core'
import {useColorScheme} from '@mantine/hooks'
const colorSchemeManager = localStorageColorSchemeManager({
key: 'example-viewer-color-scheme'
})
const getForm = () => JSON.stringify({form: {key: 'Screen', type: 'Screen', children: []}})
export const AppWithColorScheme = () => {
const systemColorScheme = useColorScheme()
return (
<MantineProvider
colorSchemeManager={colorSchemeManager}
defaultColorScheme={systemColorScheme === 'dark' ? 'dark' : 'light'}
// Uncomment to force one mode:
// forceColorScheme='dark'
>
<FormViewer view={view} getForm={getForm}/>
</MantineProvider>
)
}
When you need immediate client-side color scheme detection (for non-SSR usage), pass getInitialValueInEffect: true:
import {useColorScheme} from '@mantine/hooks'
const colorScheme = useColorScheme('light', {getInitialValueInEffect: true})
Show code
function App() { const [forceColorScheme, setForceColorScheme] = useState('none') const colorSchemeManager = useMemo( () => localStorageColorSchemeManager({key: 'docs-mantine-scheme'}), [] ) const previewRootRef = useRef(null) const effectiveScheme = forceColorScheme === 'none' ? undefined : forceColorScheme const form = useMemo(() => ({ form: { key: 'Screen', type: 'Screen', children: [ { key: 'title', type: 'MtTitle', props: { order: {value: 3}, children: {value: 'Sign up (' + (effectiveScheme ?? 'default') + ' mode)'} } }, { key: 'email', type: 'MtTextInput', props: { label: {value: 'Email'}, placeholder: {value: 'you@example.com'} } }, { key: 'age', type: 'MtSlider', props: { label: {value: 'Age'}, min: {value: 13}, max: {value: 100}, step: {value: 1} } }, { key: 'terms', type: 'MtCheckbox', props: { label: {value: 'I agree to terms and privacy policy'} } } ] } }), [effectiveScheme]) const getForm = useCallback(() => JSON.stringify(form), [form]) return ( <div id='mantine-live-root-color' ref={previewRootRef} style={{ display: 'grid', gap: 12, padding: 12, borderRadius: 8, background: 'var(--mantine-color-body)', color: 'var(--mantine-color-text)', border: '1px solid var(--mantine-color-default-border)', transition: 'background-color 150ms ease, color 150ms ease, border-color 150ms ease' }} > <div style={{display: 'flex', gap: 12, flexWrap: 'wrap'}}> <label> forceColorScheme:{' '} <select value={forceColorScheme} onChange={(event) => setForceColorScheme(event.target.value)} > <option value='none'>none</option> <option value='light'>light</option> <option value='dark'>dark</option> </select> </label> </div> <MantineProvider colorSchemeManager={colorSchemeManager} forceColorScheme={effectiveScheme} cssVariablesSelector='#mantine-live-root-color' getRootElement={() => previewRootRef.current ?? undefined} withGlobalClasses={false} > <FormViewer view={mantineView} getForm={getForm}/> </MantineProvider> </div> ) } render(<App />)
For color scheme APIs, see:
BiDi support
Mantine supports BiDi setup in several ways:
- Wrap the app with
DirectionProvider. - Set
diron the root element (htmlin most apps). - Change direction at runtime with
useDirection. - Add RTL-specific CSS overrides with the
rtlmixin (when usingpostcss-preset-mantine). - Configure
DirectionProviderbehavior withinitialDirectionanddetectDirection.
DirectionProvider
import {DirectionProvider, MantineProvider} from '@mantine/core'
import {view} from '@react-form-builder/components-mantine'
import {FormViewer} from '@react-form-builder/core'
const getForm = () => JSON.stringify({form: {key: 'Screen', type: 'Screen', children: []}})
export const AppWithDirection = () => (
<DirectionProvider initialDirection='ltr'>
<MantineProvider>
<FormViewer view={view} getForm={getForm}/>
</MantineProvider>
</DirectionProvider>
)
Root dir attribute
<!doctype html>
<html dir="rtl">
<head></head>
<body></body>
</html>
Runtime direction switch with useDirection
import {Button, Group, useDirection} from '@mantine/core'
export const DirectionToggle = () => {
const {dir, setDirection, toggleDirection} = useDirection()
return (
<Group>
<Button variant='default' onClick={() => setDirection('ltr')}>LTR</Button>
<Button variant='default' onClick={() => setDirection('rtl')}>RTL</Button>
<Button onClick={toggleDirection}>Toggle ({dir})</Button>
</Group>
)
}
CSS RTL mixin
.demo {
text-align: left;
padding: var(--mantine-spacing-md);
@mixin rtl {
text-align: right;
}
}
For direction support, see RTL direction
Examples
Use these examples to run and inspect viewer and designer integrations:
Viewer example
Show code
function App() { const theme = createTheme({primaryColor: 'cyan'}) const getForm = useCallback(() => JSON.stringify({ form: { key: 'Screen', type: 'Screen', children: [ { key: 'title', type: 'MtTitle', props: { order: {value: 3}, children: {value: 'Viewer integration'} } }, { key: 'name', type: 'MtTextInput', props: { label: {value: 'Name'}, placeholder: {value: 'John Doe'} } }, { key: 'submit', type: 'MtButton', props: { children: {value: 'Submit'}, fullWidth: {value: true} } } ] } }), []) return ( <MantineProvider theme={theme}> <FormViewer view={mantineView} getForm={getForm}/> </MantineProvider> ) } render(<App />)
Designer example
For a full designer experience, check the public demo: https://demo.formengine.io/
import {builderView} from '@react-form-builder/components-mantine'
import {FormBuilder} from '@react-form-builder/designer'
import '@mantine/core/styles.css'
import '@mantine/dates/styles.css'
import '@mantine/dropzone/styles.css'
import '@mantine/tiptap/styles.css'
const getForm = () => JSON.stringify({form: {key: 'Screen', type: 'Screen', children: []}})
export const MantineBuilder = () => <FormBuilder view={builderView} getForm={getForm}/>
Component types
Inputs
These components are used for data entry and user input:
| Component | Description | Mantine Documentation |
|---|---|---|
| MtCheckbox | Checkbox for binary choices | Checkbox |
| MtCheckboxGroup | Group of checkboxes for multiple selection | Checkbox |
| MtChip | Chip for tags or filters | Chip |
| MtChipCheckboxGroup | Chip-based checkbox group | Chip |
| MtChipRadioGroup | Chip-based radio group | Chip |
| MtColorInput | Color picker input | ColorInput |
| MtColorPicker | Color picker with swatches | ColorPicker |
| MtFileInput | File input with drag-and-drop | FileInput |
| MtDropzone | File upload dropzone | Mantine Dropzone (optional package) |
| MtJsonInput | JSON editor input | JsonInput |
| MtLabel | Label component for form controls | Input (label) |
| MtNumberInput | Numeric input with optional stepper | NumberInput |
| MtPasswordInput | Password input with visibility toggle | PasswordInput |
| MtRadio | Single radio option | Radio |
| MtRadioGroup | Radio button group for single selection | Radio.Group |
| MtRangeSlider | Slider for selecting a range of values | RangeSlider |
| MtRating | Star or custom symbol rating input | Rating |
| MtSegmentedControl | Segmented control for mutually exclusive options | SegmentedControl |
| MtSlider | Slider for selecting a value from a range | Slider |
| MtSwitch | Toggle switch for on/off states | Switch |
| MtSwitchGroup | Group of switches with a shared label | Switch.Group |
| MtTextInput | Text input field for single-line text | TextInput |
| MtTextarea | Multi-line text input | Textarea |
Combobox and Select
Dropdown and selection components:
| Component | Description | Mantine Documentation |
|---|---|---|
| MtAutocomplete | Autocomplete with suggestions | Autocomplete |
| MtMultiSelect | Dropdown for multiple selection | MultiSelect |
| MtNativeSelect | Native HTML select styled with Mantine | NativeSelect |
| MtSelect | Dropdown for single selection | Select |
| MtTagsInput | Input for multiple tags | TagsInput |
Date and Time
Components for date and time selection (require @mantine/dates):
| Component | Description | Mantine Documentation |
|---|---|---|
| MtDateMultiplePicker | Date picker for selecting multiple dates | Mantine Dates |
| MtDateMultiplePickerInput | Date picker input for multiple dates | Mantine Dates |
| MtDatePicker | Date picker for a single date | Mantine Dates |
| MtDatePickerInput | Date picker with input field for a single date | Mantine Dates |
| MtDateRangePicker | Date picker for selecting a date range | Mantine Dates |
| MtDateRangePickerInput | Date picker input for a date range | Mantine Dates |
| MtDateTimePicker | Date and time picker | Mantine Dates |
| MtMonthMultiplePicker | Month picker for selecting multiple months | Mantine Dates |
| MtMonthMultiplePickerInput | Month picker input for multiple months | Mantine Dates |
| MtMonthPicker | Month picker for a single month | Mantine Dates |
| MtMonthPickerInput | Month picker with input field | Mantine Dates |
| MtMonthRangePicker | Month picker for selecting a range of months | Mantine Dates |
| MtMonthRangePickerInput | Month picker input for a range of months | Mantine Dates |
| MtTimeGrid | Time slot grid for scheduling | Mantine Dates |
| MtTimeInput | Time input field | Mantine Dates |
| MtTimePicker | Time picker | Mantine Dates |
| MtYearMultiplePicker | Year picker for selecting multiple years | Mantine Dates |
| MtYearMultiplePickerInput | Year picker input for multiple years | Mantine Dates |
| MtYearPicker | Year picker for a single year | Mantine Dates |
| MtYearPickerInput | Year picker with input field | Mantine Dates |
| MtYearRangePicker | Year picker for selecting a range of years | Mantine Dates |
| MtYearRangePickerInput | Year picker input for a range of years | Mantine Dates |
Layout
| Component | Description | Mantine Documentation |
|---|---|---|
| MtContainer | Container for centering and constraining content | Container |
Typography
| Component | Description | Mantine Documentation |
|---|---|---|
| MtText | Text component for body content | Text |
| MtTitle | Heading component | Title |
| MtTypography | Typography with preset text styles | Typography |
Miscellaneous
Miscellaneous utility components:
| Component | Description | Mantine Documentation |
|---|---|---|
| MtDivider | Visual divider | Divider |
| MtErrorWrapper | Error display wrapper | Custom component for error handling |
| MtViewerWrapper | Wrapper component for viewers | Custom component for viewer integration |
Other extensions
Additional Mantine-based extensions:
| Component | Description | Mantine Documentation |
|---|---|---|
| MtTiptap | Rich text editor | Mantine Tiptap (optional package) |
| MtDropzone | File upload dropzone | Mantine Dropzone (optional package) |
Overlays
| Component | Description | Mantine Documentation |
|---|---|---|
| MtTooltip | Tooltip for additional info | Tooltip |
Modal
| Component | Description | Mantine Documentation |
|---|---|---|
| MtDialog | Modal dialog container | Modal |
Buttons
| Component | Description | Mantine Documentation |
|---|---|---|
| MtButton | Button for user actions | Button |
Additional Resources
- Mantine official documentation
- Mantine Core Components
- Mantine Dates
- Mantine GitHub Repository
- Mantine Getting Started
Support
For issues with Mantine components in FormEngine:
- Check the FormEngine GitHub issues
- Refer to the Mantine documentation
- Join the FormEngine community discussions
Mantine components provide a modern, accessible, and themable way to build forms and interfaces in FormEngine applications, with strong TypeScript support and responsive design out of the box.