6.x → 7.x migration guide

This guide will help you migrate your project styles from 6.x to 7.x. It's not intended to be a comprehensive guide covering all changes in 7.x. For a complete overview, please see the 7.0.0 changelog.

Migration to @mantine/emotion

The @mantine/emotion package has been available since version 7.9. If you don't want to use CSS modules, have many styles created with createStyles, sx and styles props, or simply prefer CSS-in-JS syntax, you can migrate to @mantine/emotion. To view the full documentation for the @mantine/emotion package, visit this page.

createStyles and Global component

The createStyles function and Global component are no longer available in the @mantine/core package. Change imports to @mantine/emotion:

// 6.x
import { createStyles, Global } from '@mantine/core';

// 7.x
import { createStyles, Global } from '@mantine/emotion';

sx and styles props

sx and styles props are available in 7.x the same way as in 6.x after setup:

// 6.x and 7.x, no changes
import { Box, Button } from '@mantine/core';

function Demo() {
  return (
    <>
      <Box
        sx={(theme) => ({ backgroundColor: theme.colors.red[5] })}
      />
      <Button styles={{ root: { height: 50 } }} />
    </>
  );
}

theme.colorScheme

In v7, the color scheme value is managed by MantineProvider, and the theme object no longer includes the colorScheme property. Although it's still possible to access the color scheme value in components with the useMantineColorScheme hook, it's not recommended to base your styles on its value. Instead, use the light/dark utilities.

Example of 6.x createStyles with theme.colorScheme migration to 7.0:

// 6.x
import { createStyles } from '@mantine/core';

const useStyles = createStyles((theme) => ({
  root: {
    backgroundColor:
      theme.colorScheme === 'dark'
        ? theme.colors.dark[6]
        : theme.colors.gray[0],
    color: theme.colorScheme === 'dark' ? theme.white : theme.black,
  },
}));
// 7.x
import { createStyles } from '@mantine/emotion';

const useStyles = createStyles((theme, _, u) => ({
  root: {
    [u.dark] {
      backgroundColor: theme.colors.dark[6];
      color: theme.white;
    },

    [u.light]: {
      backgroundColor: theme.colors.gray[0];
      color: theme.black;
    },
  },
}));

Migration to CSS modules

Before getting started, we recommend going through the styles documentation. The most notable sections are:

Note that this guide assumes you have postcss-preset-mantine installed and configured in your project.

createStyles

The createStyles function is no longer available in 7.0. Use CSS Modules instead.

// 6.x
import { createStyles } from '@mantine/core';

const useStyles = createStyles((theme) => ({
  root: {
    backgroundColor: theme.colors.red[5],
  },
}));
/* 7.0 */
.root {
  background-color: var(--mantine-color-red-5);
}

sx prop

The sx prop is no longer available in 7.0. Use className or the style prop instead.

// 6.x
import { Box } from '@mantine/core';

function Demo() {
  return (
    <Box sx={(theme) => ({ backgroundColor: theme.colors.red[5] })} />
  );
}
// 7.0
import { Box } from '@mantine/core';

function Demo() {
  return (
    <Box style={{ backgroundColor: 'var(--mantine-color-red-5)' }} />
  );
}

Nested selectors are not supported in the style prop; use className instead:

// 6.x
import { Box } from '@mantine/core';

function Demo() {
  return <Box sx={{ '&:hover': { background: 'red' } }} />;
}
.box {
  &:hover {
    background: red;
  }
}

styles prop

The styles prop no longer supports nested selectors. Use classNames instead to apply styles to nested elements.

// 6.x – nested selectors
import { TextInput } from '@mantine/core';

function Demo() {
  return (
    <TextInput
      styles={{
        input: {
          '&:focus': {
            color: 'red',
          },
        },
      }}
    />
  );
}
/* 7.0 */
.input {
  &:focus {
    color: red;
  }
}

Regular selectors are still supported:

// Works both in 6.x and 7.x
import { TextInput } from '@mantine/core';

function Demo() {
  return (
    <TextInput
      styles={{
        input: {
          color: 'red',
        },
      }}
    />
  );
}

Global styles

The Global component and global styles on the theme are not available in 7.0. Instead, create a global stylesheet (.css file) and import it at your application entry point.

// 6.x
import { Global } from '@mantine/core';

function Demo() {
  return (
    <Global
      styles={(theme) => ({
        '*, *::before, *::after': {
          boxSizing: 'border-box',
        },

        body: {
          backgroundColor:
            theme.colorScheme === 'dark'
              ? theme.colors.dark[7]
              : theme.white,
          color:
            theme.colorScheme === 'dark'
              ? theme.colors.dark[0]
              : theme.black,
          lineHeight: theme.lineHeight,
        },

        '.your-class': {
          backgroundColor: 'red',
        },

        '#your-id > [data-active]': {
          backgroundColor: 'pink',
        },
      })}
    />
  );
}
/* 7.0 */
/* src/index.css */
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  background-color: light-dark(
    var(--mantine-color-white),
    var(--mantine-color-dark-7)
  );
  color: light-dark(
    var(--mantine-color-black),
    var(--mantine-color-white)
  );
  line-height: var(--mantine-line-height);
}

.your-class {
  background-color: red;
}

#your-id > [data-active] {
  background-color: pink;
}

theme referencing

All theme properties are now available as CSS variables. We recommend using CSS variables instead of referencing the theme object in styles.

// 6.x
import { Box } from '@mantine/core';

function Demo() {
  return (
    <Box
      sx={(theme) => ({
        backgroundColor: theme.colors.red[6],
        color: theme.white,
        padding: `calc(${theme.spacing.xl} * 2)`,
      })}
    />
  );
}
/* 7.0 */
.box {
  background-color: var(--mantine-color-red-6);
  color: var(--mantine-color-white);
  padding: calc(var(--mantine-spacing-xl) * 2);
}

theme.colorScheme

The color scheme value is managed by MantineProvider, and the theme object no longer includes the colorScheme property. Although it's still possible to access the color scheme value in components with the useMantineColorScheme hook, it's not recommended to base your styles on its value. Instead, use the light/dark mixins or the light-dark CSS function.

Example of 6.x createStyles with theme.colorScheme migration to 7.0:

// 6.x
import { createStyles } from '@mantine/core';

const useStyles = createStyles((theme) => ({
  root: {
    backgroundColor:
      theme.colorScheme === 'dark'
        ? theme.colors.dark[6]
        : theme.colors.gray[0],
    color: theme.colorScheme === 'dark' ? theme.white : theme.black,
  },
}));
/* 7.0 */

/* With light-dark function */
.root {
  background-color: light-dark(
    var(--mantine-color-gray-0),
    var(--mantine-color-dark-6)
  );
  color: light-dark(
    var(--mantine-color-black),
    var(--mantine-color-white)
  );
}

/* With light/dark mixins */
.root {
  background-color: var(--mantine-color-gray-0);
  color: var(--mantine-color-black);

  @mixin dark {
    background-color: var(--mantine-color-dark-6);
    color: var(--mantine-color-white);
  }
}

Note that if your application has server-side rendering, you should not render any elements based on its value (more info). Instead, use the light/dark mixins or the light-dark function to hide/show elements based on the color scheme value.

Color scheme toggle example:

import { ActionIcon, useMantineColorScheme, useComputedColorScheme } from '@mantine/core';
import { SunIcon, MoonIcon } from '@phosphor-icons/react';
import cx from 'clsx';
import classes from './Demo.module.css';

function Demo() {
  const { setColorScheme } = useMantineColorScheme();
  const computedColorScheme = useComputedColorScheme('light', { getInitialValueInEffect: true });

  return (
    <ActionIcon
      onClick={() => setColorScheme(computedColorScheme === 'light' ? 'dark' : 'light')}
      variant="default"
      size="xl"
      aria-label="Toggle color scheme"
    >
      <SunIcon className={cx(classes.icon, classes.light)} />
      <MoonIcon className={cx(classes.icon, classes.dark)} />
    </ActionIcon>
  );
}