6.x → 7.x migration guide

This guide is intended to help you migrate your project styles from 6.x to 7.x. It is not intended to be a comprehensive guide to all the changes in 7.x. For that, please see the 7.0.0 changelog.

Before getting started, it is recommended to go through styles documentation. Most notable parts:

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

createStyles

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

sx prop is no longer available in 7.0. Use className or 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 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

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

Global component and global styles on theme are not available in 7.0. Instead, create a global stylesheet (.css file) and import it in 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. It is recommended to use CSS variables instead of referencing 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

Color scheme value is managed by MantineProvider, theme object no longer includes colorScheme property. Although it is still possible to access color scheme value in components with useMantineColorScheme hook, it is not recommended to base your styles on its value. Instead, use light/dark mixins or 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 light/dark mixins or light-dark function to hide/display elements based on color scheme value.

Color scheme toggle example:

import { ActionIcon, useMantineColorScheme, useComputedColorScheme } from '@mantine/core';
import { IconSun, IconMoon } from '@tabler/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"
    >
      <IconSun className={cx(classes.icon, classes.light)} stroke={1.5} />
      <IconMoon className={cx(classes.icon, classes.dark)} stroke={1.5} />
    </ActionIcon>
  );
}