Breaking changes

  • MediaQuery now requires passing styles object and does not hide child element by default
  • Styles API static selectors no longer use kebab case (was .mantine-text-input-root, now .mantine-TextInput-root)

Configure emotion with MantineProvider

You can now set emotion cache options via MantineProvider:

<MantineProvider emotionOptions={{ key: 'mantine', prepend: false }}>
<App />
</MantineProvider>

With these options you can change styles insertion point (from 3.1 styles are prepended to head) and configure stylis plugins. For example, you can use stylis-plugin-rtl to add rtl support:

import { MantineProvider } from '@mantine/core';
import rtlPlugin from 'stylis-plugin-rtl';
function Demo() {
return (
<MantineProvider emotionOptions={{ key: 'mantine', stylisPlugins: [rtlPlugin] }}>
<App />
</MantineProvider>
);
}

Styles API on MantineProvider

You can now add styles to components with MantineProvider. Styles will be added to every matching component rendered inside MantineProvider:

Dot badge
import { MantineProvider, Button, Badge, ButtonStylesParams } from '@mantine/core';
function Demo() {
return (
<MantineProvider
theme={{
components: {
Button: {
// Subscribe to theme and component params
styles: (theme, params: ButtonStylesParams) => ({
root: {
height: 42,
padding: '0 30px',
backgroundColor:
params.variant === 'filled'
? theme.colors[params.color || theme.primaryColor][9]
: undefined,
},
}),
},
Badge: {
// Use raw styles object if you do not need theme dependency
styles: {
root: { borderWidth: 2 },
},
},
},
}}
>
<Button variant="outline">Outline button</Button>
<Button variant="filled" color="cyan">Filled button</Button>
<Badge variant="dot">Dot badge</Badge>
</MantineProvider>
);
}

Inline styles with emotion

styles prop will no longer add inline styles, instead styles will be converted to emotion format. This means that you now can subscribe to theme and use nested selectors in styles:

<Button
styles={(theme) => ({
outline: {
'&:hover': {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.dark[0],
},
},
root: {
height: 56,
},
})}
>
My custom button
</Button>

sx prop

All components now support sx prop. You can add styles to root element and subscribe to theme with it:

<Button
sx={(theme) => ({
borderColor: theme.colors.blue[9],
'&:hover': {
backgroundColor: theme.colors.blue[9],
},
})}
>
Button with sx styles
</Button>

use-css hook

New use-css hook is a simpler alternative to createStyles function. Hook returns css and cx functions. css function accepts styles object and returns class name:

import { useCss, Button } from '@mantine/core';
function Demo({ active }) {
const { css, cx } = useCss();
return (
<Button
className={cx(css({ backgroundColor: 'red', opacity: 1 }), { [css({ opacity: 1 })]: active })}
>
Custom button
</Button>
);
}

New components and hooks

New AppShell component allows you create responsive app shell with fixed or static position:

Your application goes here
import { AppShell, Navbar, Header } from '@mantine/core';
function Demo() {
return (
<AppShell
padding="md"
navbar={<Navbar width={{ base: 300 }} height={500} p="xs">{/* Navbar content */}</Navbar>}
header={<Header height={60} p="xs">{/* Header content */}</Header>}
styles={(theme) => ({
main: { backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.gray[0] },
})}
>
{/* Your application here */}
</AppShell>
);
}

With Skeleton component you can create placeholders to indicate loading state:

import { Skeleton } from '@mantine/core';
function Demo() {
return (
<>
<Skeleton height={50} circle mb="xl" />
<Skeleton height={8} radius="xl" />
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={8} mt={6} width="70%" radius="xl" />
</>
);
}

New use-scroll-into-view hook lets you scroll given node into view within scrollable container or body element:

Scroll me into view
import { useScrollIntoView } from '@mantine/hooks';
import { Button, Paper } from '@mantine/core';
function Demo() {
const { scrollIntoView, targetRef, scrollableRef } = useScrollIntoView();
return (
<>
<Paper ref={scrollableRef} style={{ overflowY: 'scroll', height: 300, flex: 1 }}>
<Paper ref={targetRef}>Scroll me into view</Paper>
</Paper>
<Button onClick={() => scrollIntoView()}>Scroll to target</Button>
</>
);
}

Box component allows you to utilize new sx prop to style any component or element:

Box lets you add inline styles with sx prop
import { Box } from '@mantine/core';
function Demo() {
return (
<Box
sx={(theme) => ({
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
textAlign: 'center',
padding: theme.spacing.xl,
borderRadius: theme.radius.md,
cursor: 'pointer',
'&:hover': {
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[1],
},
})}
>
Box lets you add inline styles with sx prop
</Box>
);
}

New features

Collapse component now supports dynamic children – you can now use this feature in all components that are built with Collapse:

MediaQuery component now supports adding custom styles and subscribing to custom media queries:

(max-width: 1200px) and (min-width: 800px) breakpoints
import { MediaQuery, Text } from '@mantine/core';
function Demo() {
return (
<MediaQuery
query="(max-width: 1200px) and (min-width: 800px)"
styles={{ fontSize: 20, '&:hover': { backgroundColor: 'silver' } }}
>
<Text>(max-width: 1200px) and (min-width: 800px) breakpoints</Text>
</MediaQuery>
);
}

Other changes

  • use-list-state hook now has new applyWhere handler
  • use-form hook now supports values on validation rule
  • Slider and RangeSlider components were migrated to use-move hook and now supports showing label on hover (new default behavior)
  • Add better focus management to Popover – now focus will be returned to last active element (made with use-focus-return hook)
  • AvatarsGroup component now supports total prop to explicitly override the truncated length.
  • Add onDropdownOpen and onDropdownClose handlers support to Select, MultiSelect and Autocomplete components

Bug fixes

  • Fix incorrect focus handling in Menu, DatePicker and DateRangePicker which resulted in focus not being shifted to control/input when dropdown was closed
  • Fix incorrect MultiSelect creatable filtering logic when the same item can be created multiple times
  • Fix layout jumping on Windows and Linux when overlay components with scroll lock are opened (Modal and Drawer), see use-scroll-lock documentation to learn how to offset elements with fixed position
  • Fix DatePicker dropdown not updating position when used near bottom edge of viewport
  • Fix incorrect random ids generated during server side rendering in Next.js
  • Prevent page from rendering twice in @mantine/next package