Mantine for React Native. 118 themeable, accessible components for iOS, Android and Web, with the theme system, variants and useForm API Mantine users already know.
Documentation · Try it in Expo Snack · Starter template · npm · Changelog · llms.txt
- Same mental model as Mantine on web. Colors, sizes, radius, shadows, variants (
filled,light,outline,subtle,gradient, ...) anduseFormfollow Mantine, so a team with a Mantine web app can share theme tokens and habits with its mobile app. - 118 components, not 40. Layout, inputs, overlays, navigation, feedback and data display, plus components most React Native kits skip:
Tree,TreeSelect,TransferList,Splitter,Timeline,Stepper,Marquee,RollingNumber,TableOfContents,RingProgress,SemiCircleProgress. - Works everywhere. iOS, Android and Web through React Native Web. Expo is a first-class target; bare React Native works too.
- Zero required native dependencies. Icons, gradients, clipboard and fonts are pluggable and optional. Bring
@expo/vector-iconsorreact-native-vector-icons, or neither. - Typed end to end. Written in TypeScript with documented props for every component.
- 118 React Native Components - Buttons, inputs, overlays, navigation, feedback and data display, all themeable
- Full Theme System - 14 color palettes with 10 shades each, aligned with Mantine, with light and dark modes
- 8 Component Variants - filled, light, outline, subtle, white, default, gradient and transparent
- TypeScript First - Comprehensive type definitions for every component and hook
- Accessibility Built-in - Components follow React Native accessibility best practices out of the box
- Expo Compatible - Works with Expo and bare React Native; native integrations are optional and pluggable
- Cross-platform - iOS, Android and Web (via React Native Web)
- Form Management -
useFormhook with validation, error handling and state management
react-native-mantine is used in production apps and is maintained as a stable library. What that means concretely:
| Supported React Native | 0.72 and newer, including the New Architecture (Fabric and TurboModules). The library is pure TypeScript with no native code, so there is nothing to link and nothing that breaks on architecture changes. The showcase runs on Expo SDK 54 with the New Architecture enabled. |
| Supported React | 18.2 and 19 |
| Expo | SDK 50 and newer, managed or bare. Expo is not required. |
| Web | React Native Web 0.19 and newer |
| Runtime dependencies | None. Every native integration (icons, gradients, clipboard, document picker, fonts) is an optional adapter you choose. |
| Package | ESM and CommonJS builds, sideEffects: false for tree shaking, TypeScript declarations for every export |
| Tests | 1,900+ tests across every component and hook, 99% statement and 85% branch coverage, with a 95% / 80% threshold enforced in CI; CI runs typecheck, lint, tests and the build on every commit and pull request |
| Accessibility | Interactive components ship accessibilityRole, accessibilityState, accessibilityValue and derived labels, and always let you override them |
| Versioning | Semantic versioning with Conventional Commits. Breaking changes only in a major release, announced in CHANGELOG.md with a migration note. Deprecated props keep working for at least one minor release and warn in development. |
| Security | Dependabot enabled, transitive advisories pinned, private reporting via SECURITY.md |
| License | MIT |
If you hit something that blocks a production rollout, open an issue. Blocking bugs are treated as the top priority.
npm install react-native-mantineOr with Yarn:
yarn add react-native-mantineOnly react and react-native are required. Everything else is optional and pluggable.
npm install react react-nativereact-native-mantine does not depend on any icon, gradient or SVG package. Pass the implementations you already use through Theme / ThemeProvider, or through configureMantine outside React. When nothing is passed, the library uses react-native-vector-icons, expo-linear-gradient, expo-clipboard, expo-document-picker, expo-font and react-native-svg if they happen to be installed, and otherwise degrades gracefully: icon names render as text, gradients render as a solid first color, and RingProgress draws its ring from Views instead of SVG arcs.
npx expo install @expo/vector-icons expo-linear-gradientimport FontAwesome from '@expo/vector-icons/FontAwesome';
import { LinearGradient } from 'expo-linear-gradient';
import { Theme, type MantineAdapters } from 'react-native-mantine';
const adapters: Partial<MantineAdapters> = {
Icon: FontAwesome as MantineAdapters['Icon'], // Expo types `name` as a glyph union
LinearGradient,
};
export default function App() {
return <Theme adapters={adapters}>{/* your app */}</Theme>;
}yarn add react-native-vector-icons react-native-linear-gradient
cd ios && pod installimport FontAwesome from 'react-native-vector-icons/FontAwesome';
import LinearGradient from 'react-native-linear-gradient';
import { Theme } from 'react-native-mantine';
export default function App() {
return <Theme adapters={{ Icon: FontAwesome, LinearGradient }}>{/* your app */}</Theme>;
}import { configureMantine } from 'react-native-mantine';
configureMantine({ Icon: FontAwesome, LinearGradient }); // e.g. in index.jsTheme adapters takes precedence over configureMantine.
| Adapter | Used by | Shape | Default fallback |
|---|---|---|---|
clipboard |
CopyButton |
{ setStringAsync(text) } |
expo-clipboard |
documentPicker |
FileButton, FileInput |
(opts) => Promise<{ canceled, assets }> (Expo shape) |
expo-document-picker |
loadFonts |
Theme |
(fonts) => Promise<void> |
expo-font |
svg |
RingProgress |
{ Svg, Circle } |
react-native-svg |
import Clipboard from '@react-native-clipboard/clipboard';
configureMantine({
clipboard: { setStringAsync: (text) => Clipboard.setString(text) },
});Wrap your application with ThemeProvider at the root level:
import { ThemeProvider, Button, Text, Stack, Paper } from 'react-native-mantine';
export default function App() {
return (
<ThemeProvider>
<Stack spacing="md">
<Paper padding="lg" shadow="sm">
<Text size="xl" weight={700}>
Welcome to React Native Mantine
</Text>
<Text color="dimmed">
Build beautiful mobile apps with ease
</Text>
</Paper>
<Button variant="filled" color="blue" onPress={() => console.log('Pressed!')}>
Get Started
</Button>
</Stack>
</ThemeProvider>
);
}React Native Mantine includes 110+ components organized by category:
- BoxView - Base layout component with theme-aware styling
- Container - Responsive container with max-width constraints
- Center - Centers children horizontally and vertically
- Flex - Flexbox layout with gap support
- Group - Horizontal layout with spacing
- Stack - Vertical layout with spacing
- Grid - Responsive grid system
- SimpleGrid - Equal-width grid columns
- Space - Add spacing between elements
- AspectRatio - Maintain aspect ratio for child elements
- MediaQuery - Responsive components based on screen size
- AppShell - Application shell with header, navbar, aside and footer
- Splitter - Resizable panes divided by draggable handles
- Text - Themeable text component with size variants
- Title - Heading component (h1-h6)
- Highlight - Highlight text segments
- Mark - Mark/highlight text with background color
- Code - Inline code display
- Blockquote - Styled quotation blocks
- Kbd - Keyboard key display
- Table - Data table component
- Typography - Applies consistent typography styles to nested content
- Button - Primary button with variants and loading states
- UnstyledButton - Unstyled pressable base
- ActionIcon - Icon button with variants
- CloseButton - Close/dismiss button
- CopyButton - Copy to clipboard button
- FileButton - Button that opens the document picker
- Burger - Animated hamburger menu button
- TextInput - Text input with variants and error states
- Textarea - Multiline text input
- PasswordInput - Password input with show/hide toggle
- NumberInput - Numeric input with increment/decrement
- PinInput - PIN code input
- Switch - Toggle switch
- Checkbox - Checkbox input
- Radio - Radio button input
- Chip - Selectable chip
- Slider - Range slider input
- Select - Dropdown select
- MultiSelect - Multiple selection dropdown
- Autocomplete - Autocomplete input
- NativeSelect - Native platform select
- Fieldset - Groups related inputs with a legend
- InputBase - Base input frame for building custom inputs
- JsonInput - JSON input with validation and formatting
- MaskInput - Input with masked value formatting
- ColorInput - Color input with picker bottom sheet
- ColorPicker - Color picker with saturation, hue and alpha controls
- FileInput - File picking input built on the document picker
- PillsInput - Input that renders pills inside its frame
- TagsInput - Input for entering multiple tags
- AngleSlider - Circular slider for selecting angles
- TreeSelect - Select input with hierarchical options
- Combobox - Building blocks for custom select components
- Paper - Card-like surface with shadow and padding
- Badge - Status badges with variants
- Avatar - User avatar with image/initials
- Card - Content card with sections
- Timeline - Timeline/stepper display
- List - Ordered/unordered lists
- Divider - Visual separator
- Progress - Progress bar
- RingProgress - Circular progress indicator
- Skeleton - Loading skeleton placeholder
- ColorSwatch - Color display component
- ThemeIcon - Icon with theme colors
- Indicator - Badge indicator overlay
- Breadcrumbs - Navigation breadcrumbs
- Pill - Removable tag/pill element
- NumberFormatter - Formats numbers with separators, prefix and suffix
- SemiCircleProgress - Semi-circular progress indicator
- RollingNumber - Animated rolling number display
- DataList - Key-value data list
- EmptyState - Placeholder for empty content areas
- Tree - Hierarchical tree view
- OverflowList - List that collapses overflowing items
- Overlay - Backdrop overlay
- Modal - Full-featured modal dialog
- Drawer - Slide-in drawer from edges
- Dialog - Simple dialog box
- Popover - Popover with positioning
- Menu - Dropdown menu
- Tooltip - Hover/press tooltip
- LoadingOverlay - Full-screen loading overlay
- HoverCard - Dropdown card opened from a target element
- Affix - Positions content at fixed screen coordinates
- Portal - Renders children into an overlay host
- FloatingWindow - Draggable floating window
- FloatingIndicator - Indicator that follows its target element
- Notification - Toast notification
- Alert - Alert banner with variants
- Loader - Loading spinner
- Tabs - Tab navigation
- Pagination - Page pagination
- Stepper - Multi-step navigation
- SegmentedControl - Segmented control buttons
- NavLink - Navigation link component
- Anchor - Link component
- TableOfContents - List of section links with depth offsets
- Menubar - Horizontal bar of menus
- Accordion - Collapsible content panels
- Collapse - Show/hide content with animation
- Spoiler - Show more/less content
- Rating - Star rating input
- TransferList - Dual list transfer
- Icon - Icon component wrapper
- Image - Image with fallback
- BackgroundImage - Background image container
- Gradient - Gradient background
- LinearGradient - Linear gradient component
- Transition - Animation transition wrapper
- VisuallyHidden - Hides content visually while keeping it accessible
- ScrollArea - Scrollable area with Mantine-compatible API
- Scroller - Horizontal scroller with controls and edge gradients
- Marquee - Continuously scrolling content
The default theme matches mantine.dev:
| Role | Font | Weight |
|---|---|---|
| Body text, inputs, buttons | Platform system font (San Francisco on iOS, Roboto on Android, Mantine's -apple-system stack on web) |
400, buttons 600 |
Headings (Title) |
Outfit, bundled with the library under the SIL Open Font License | 600 |
Monospace (Code, Kbd) |
Menlo on iOS, monospace on Android, Mantine's ui-monospace stack on web |
400 |
Theme registers the bundled Outfit files through expo-font or your loadFonts adapter. If neither is available, or when you use ThemeProvider directly, headings fall back to the bold system font. To use your own fonts, load them yourself and override fontFamily, fontFamilyBold, fontFamilySemiBold, fontFamilyInput, fontFamilyMonospace, or headings.fontFamily in the theme.
Use createTheme() to customize the default theme:
import { ThemeProvider, createTheme } from 'react-native-mantine';
const theme = createTheme({
primaryColor: 'teal',
primaryShade: { light: 6, dark: 8 },
fontFamily: 'Inter',
colors: {
brand: [
'#e6f7ff',
'#bae7ff',
'#91d5ff',
'#69c0ff',
'#40a9ff',
'#1890ff',
'#096dd9',
'#0050b3',
'#003a8c',
'#002766',
],
},
});
export default function App() {
return (
<ThemeProvider theme={theme}>
{/* Your app components */}
</ThemeProvider>
);
}const theme = createTheme({
// Primary color from available colors
primaryColor: 'blue',
// Primary shade for light and dark modes
primaryShade: { light: 6, dark: 8 },
// Typography
fontFamily: 'System',
fontFamilyMonospace: 'Courier',
// Custom colors (10 shades each)
colors: {
brand: [...], // Array of 10 color shades
},
// Spacing scale
spacing: {
xs: 10,
sm: 12,
md: 16,
lg: 20,
xl: 24,
},
// Border radius scale
radius: {
xs: 2,
sm: 4,
md: 8,
lg: 16,
xl: 32,
},
// Font sizes
fontSizes: {
xs: 12,
sm: 14,
md: 16,
lg: 18,
xl: 20,
},
// Headings configuration
headings: {
fontFamily: 'System',
sizes: {
h1: { fontSize: 34, lineHeight: 1.3 },
h2: { fontSize: 28, lineHeight: 1.35 },
h3: { fontSize: 22, lineHeight: 1.4 },
h4: { fontSize: 18, lineHeight: 1.45 },
h5: { fontSize: 16, lineHeight: 1.5 },
h6: { fontSize: 14, lineHeight: 1.5 },
},
},
});React Native Mantine includes 14 color palettes, each with 10 shades:
- dark - Grays and blacks
- gray - Gray shades
- red - Red spectrum
- pink - Pink spectrum
- grape - Purple/grape spectrum
- violet - Violet spectrum
- indigo - Indigo spectrum
- blue - Blue spectrum
- cyan - Cyan spectrum
- teal - Teal spectrum
- green - Green spectrum
- lime - Lime spectrum
- yellow - Yellow spectrum
- orange - Orange spectrum
Enable dark mode by setting forceMode prop or using the theme's toggleMode function:
// Force dark mode
<ThemeProvider forceMode="dark">
{children}
</ThemeProvider>
// Or toggle programmatically
import { useTheme } from 'react-native-mantine';
function MyComponent() {
const theme = useTheme();
return (
<Button onPress={theme.toggleMode}>
Toggle {theme.colorScheme === 'light' ? 'Dark' : 'Light'} Mode
</Button>
);
}React Native Mantine provides powerful hooks for form management and resource loading:
Comprehensive form state management with validation, error handling, and field tracking:
import { useForm } from 'react-native-mantine';
function LoginForm() {
const form = useForm({
initialValues: {
email: '',
password: '',
terms: false,
},
validate: {
email: (value) =>
/^\S+@\S+$/.test(value) ? null : 'Invalid email',
password: (value) =>
value.length >= 6 ? null : 'Password must be at least 6 characters',
terms: (value) =>
value ? null : 'You must accept terms and conditions',
},
validateInputOnChange: false,
validateInputOnBlur: true,
clearInputErrorOnChange: true,
});
return (
<Stack>
<TextInput
label="Email"
placeholder="your@email.com"
{...form.getInputProps('email')}
/>
<PasswordInput
label="Password"
placeholder="Your password"
{...form.getInputProps('password')}
/>
<Checkbox
label="I accept terms and conditions"
checked={form.values.terms}
onValueChange={(checked) => form.setFieldValue('terms', checked)}
error={form.errors.terms}
/>
<Button
onPress={form.onSubmit((values) => {
console.log('Form submitted:', values);
})}
>
Submit
</Button>
</Stack>
);
}Form State:
values- Current form valueserrors- Form validation errorstouched- Fields that have been focuseddirty- Fields that have been modified
Field Management:
setFieldValue(field, value)- Update a single fieldsetValues(values)- Update multiple fieldssetFieldError(field, error)- Set field errorsetErrors(errors)- Set multiple errorsclearFieldError(field)- Clear field errorclearErrors()- Clear all errors
Validation:
validateField(field)- Validate single fieldvalidate()- Validate entire formisValid(field?)- Check if field/form is validgetFieldStatus(field)- Get field status (error, touched, dirty)
Form Actions:
reset()- Reset form to initial valuesisDirty()- Check if form has been modifiedgetInputProps(field)- Get props for input componentonSubmit(handler)- Handle form submissionsetFieldTouched(field)- Mark field as touched
Access the current theme object:
import { useTheme } from 'react-native-mantine';
function MyComponent() {
const theme = useTheme();
return (
<View style={{ backgroundColor: theme.colors.blue[6] }}>
<Text style={{ color: theme.white }}>
Current mode: {theme.colorScheme}
</Text>
</View>
);
}Handles font loading and resource initialization (used internally by ThemeProvider).
React Native Mantine components are built with accessibility in mind:
- All interactive components include appropriate
accessibilityRoleprops - Form inputs support
accessibilityLabelandaccessibilityHint - Error states are announced to screen readers
- Touch targets meet minimum size requirements (44x44 points)
- Color contrast ratios meet WCAG AA standards
- Keyboard navigation support on web platform
React Native Mantine works in Expo (managed and bare) and in plain React Native projects. No Expo package is required. See Icons and native integrations for how to plug in @expo/vector-icons, expo-linear-gradient, expo-clipboard, expo-document-picker and expo-font, or their bare React Native equivalents.
- iOS - 13.0 and above
- Android - API 21 (Android 5.0) and above
- React Native - 0.70 and above
- Web (via React Native Web) - Latest versions of Chrome, Firefox, Safari, and Edge
We welcome contributions! Here's how you can help:
- Fork the repository and create your branch from
main - Install dependencies -
yarn install - Make your changes - Follow the existing code style
- Add tests - Ensure your code is tested
- Run tests -
yarn test - Check types -
yarn typecheck - Lint your code -
yarn lint - Submit a pull request
# Install dependencies
yarn install
# Run example app
yarn example start
yarn example ios
yarn example android
# Testing
yarn test # Run all tests
yarn typecheck # Type checking
yarn lint # Lint code
# Building
yarn prepare # Build library
yarn clean # Clean build artifactsreact-native-mantine/
├── src/
│ ├── components/ # Component implementations
│ ├── theme/ # Theme system
│ ├── hooks/ # Custom hooks
│ └── index.tsx # Main exports
├── example/ # Example app
└── lib/ # Build output
For more details, see CONTRIBUTING.md.
This library is inspired by the excellent Mantine project by Vitaly Rtishchev. Special thanks to the Mantine team for creating such a wonderful UI library that serves as the foundation for this React Native adaptation.
- GitHub Issues - Report bugs or request features
- GitHub Discussions - Ask questions and get community support
- Documentation - Full documentation and demos
MIT License - see the LICENSE file for details.
Made with care by Auronsan