Version v7.0.0

Migration to native CSS

Mantine no longer depends on Emotion for styles generation. All @mantine/* packages are now shipped with native CSS files which can be imported from @mantine/{package}/styles.css, for example:

import '@mantine/core/styles.css';

This change improves performance, reduces bundle size of the library and allows using Mantine in environments where CSS-in-JS is not supported (or supported with limitations), for example, Next.js app directory.

Important breaking changes:

  • createStyles function is no longer available, use CSS modules or any other styling solution of your choice instead
  • Components no longer support sx prop. You can use className or style props instead.
  • styles prop no longer supports nested selectors

It is now recommended to use CSS modules to style Mantine components. To update your project to CSS modules, follow the 6.x → 7.x migration guide.

Vanilla extract integration

If you prefer CSS-in-JS syntax for styling, you can use Vanilla extract as a TypeScript CSS preprocessor. You will be able to use most of Mantine styling features with Vanilla extract.

System color scheme support

All components now support system color scheme – when colorScheme value is auto, components will use prefers-color-scheme media query to determine if the user prefers light or dark color scheme.

Note that auto is not the default value. You need to set it manually to enable system color scheme support both on MantineProvider and in ColorSchemeScript:

import { MantineProvider, ColorSchemeScript } from '@mantine/core';

function Demo() {
  return (
    <>
      <ColorSchemeScript defaultColorScheme="auto" />
      <MantineProvider defaultColorScheme="auto">
        <App />
      </MantineProvider>
    </>
  );
}

Built-in color scheme manager

MantineProvider now comes with a built-in color scheme manager. It is no longer required to use any other components to set up color scheme logic. Color scheme can be changed with useMantineColorScheme hook:

import { useMantineColorScheme, Button, Group } from '@mantine/core';

function Demo() {
  const { setColorScheme, clearColorScheme } = useMantineColorScheme();

  return (
    <Group>
      <Button onClick={() => setColorScheme('light')}>Light</Button>
      <Button onClick={() => setColorScheme('dark')}>Dark</Button>
      <Button onClick={() => setColorScheme('auto')}>Auto</Button>
      <Button onClick={clearColorScheme}>Clear</Button>
    </Group>
  );
}

CSS modules and PostCSS preset

CSS modules is now the recommended way to style Mantine components, although it is not required – you can choose any other styling solution of your choice.

It is also recommended to use postcss-preset-mantine. It includes mixins and functions to simplify styling of Mantine components. postcss-preset-mantine is included in all templates.

Global styles

Mantine no longer includes normalize.css. Instead, it uses a bare minimum set of global styles. These styles are part of the @mantine/core package and are applied automatically when you import @mantine/core/styles.css in your application. Note that these styles cannot be decoupled from the rest of the library.

Mantine as a headless UI library

You can now use Mantine as a headless library. To achieve that, just do not import @mantine/*/styles.css in your application. Then you will be able to apply styles with Styles API.

createTheme function

createTheme function is a replacement for MantineThemeOverride type. Use it to create a theme override, it will give you autocomplete for all theme properties:

import { createTheme, MantineProvider } from '@mantine/core';

const theme = createTheme({
  fontFamily: 'sans-serif',
  primaryColor: 'orange',
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <App />
    </MantineProvider>
  );
}

Components extend functions

All components that support default props or Styles API now have a static extend function which allows getting autocomplete when customizing defaultProps, classNames and styles of the component on theme:

import { useState } from 'react';
import { TextInput, MantineProvider, createTheme } from '@mantine/core';
import classes from './Demo.module.css';

const theme = createTheme({
  components: {
    TextInput: TextInput.extends({
      styles: (theme, props) => ({
        input: {
          fontSize: props.size === 'compact' ? theme.fontSizes.sm : undefined,
        }
      })
      classNames: {
        root: classes.root,
        input: classes.input,
        label: classes.label,
      },

      defaultProps: {
        size: 'compact',
      },
    }),
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <App />
    </MantineProvider>
  );
}

classNames based on component props

You can now get component props in classNames and styles to conditionally apply styles. This feature is a more powerful replacement for styles params.

import cx from 'clsx';
import { MantineProvider, createTheme, TextInput } from '@mantine/core';
import classes from './Demo.module.css';

const theme = createTheme({
  components: {
    TextInput: TextInput.extend({
      classNames: (_theme, props) => ({
        label: cx({ [classes.labelRequired]: props.required }),
        input: cx({ [classes.inputError]: props.error }),
      }),
    }),
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <TextInput required label="Required input" placeholder="Required input" />
      <TextInput error label="Input with error" placeholder="Input with error" mt="md" />
    </MantineProvider>
  );
}

Components CSS variables

You can now customize components CSS variables to change component styles based on its props. For example, it can be used to add new sizes:

import { Button, rem, Group, MantineProvider, createTheme } from '@mantine/core';

const theme = createTheme({
  components: {
    Button: Button.extend({
      vars: (theme, props) => {
        if (props.size === 'xxl') {
          return {
            root: {
              '--button-height': rem(60),
              '--button-padding-x': rem(30),
              '--button-fz': rem(24),
            },
          };
        }

        if (props.size === 'xxs') {
          return {
            root: {
              '--button-height': rem(24),
              '--button-padding-x': rem(10),
              '--button-fz': rem(10),
            },
          };
        }

        return { root: {} };
      },
    }),
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <Group>
        <Button size="xxl">XXL Button</Button>
        <Button size="xxs">XXS Button</Button>
      </Group>
    </MantineProvider>
  );
}

New variants system

All components now have data-variant attribute on the root element, even if the component does not have any predefined variants. You can use it to apply styles to all components of the same type on theme:

import { Input, MantineProvider, createTheme } from '@mantine/core';
import classes from './Demo.module.css';

// It is better to add new variants in theme.components
// This way you will be able to use them in anywhere in the app
const theme = createTheme({
  components: {
    Input: Input.extend({ classNames: classes }),
  }
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <Input variant="underline" placeholder="Underline input" />
      <Input variant="filled" placeholder="Filled input" mt="md" />
    </MantineProvider>
  );
}

New sizes system

There are multiple ways to customize component sizes:

Example of customizing Button size with data-size attribute:

import { Input, createTheme, MantineProvider } from '@mantine/core';
import classes from './Demo.module.css';

const theme = createTheme({
  components: {
    Input: Input.extend({ classNames: classes }),
  },
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <Input placeholder="Size XXL" size="xxl" />
      <Input placeholder="Size XXS" size="xxs" mt="md" />
    </MantineProvider>
  );
}

theme.variantColorResolver

Button, Badge, ActionIcon, ThemeIcon and other components now support custom variants with variantColorResolver – it supports both changing colors of existing variants and adding new variants.

import {
  Button,
  Group,
  MantineProvider,
  defaultVariantColorsResolver,
  VariantColorsResolver,
  parseThemeColor,
  rem,
  rgba,
  darken,
} from '@mantine/core';

const variantColorResolver: VariantColorsResolver = (input) => {
  const defaultResolvedColors = defaultVariantColorsResolver(input);
  const parsedColor = parseThemeColor({
    color: input.color || input.theme.primaryColor,
    theme: input.theme,
  });

  // Override some properties for variant
  if (parsedColor.isThemeColor && parsedColor.color === 'lime' && input.variant === 'filled') {
    return { ...defaultResolvedColors, color: 'var(--mantine-color-black)' };
  }

  // Completely override variant
  if (input.variant === 'light') {
    return {
      background: rgba(parsedColor.value, 0.1),
      hover: rgba(parsedColor.value, 0.15),
      border: `${rem(1)} solid ${parsedColor.value}`,
      color: darken(parsedColor.value, 0.1),
    };
  }

  // Add new variants support
  if (input.variant === 'danger') {
    return {
      background: 'var(--mantine-color-red-9)',
      hover: 'var(--mantine-color-red-8)',
      color: 'var(--mantine-color-white)',
      border: 'none',
    };
  }

  return defaultResolvedColors;
};

function Demo() {
  return (
    <MantineProvider theme={{ variantColorResolver }}>
      <Group>
        <Button color="lime.4" variant="filled">
          Lime filled button
        </Button>

        <Button color="orange" variant="light">
          Orange light button
        </Button>

        <Button variant="danger">Danger button</Button>
      </Group>
    </MantineProvider>
  );
}

rem units scaling

It is now possible to scale rem units. It is useful when you want to change font-size of html/:root element and preserve Mantine components sizes. For example, if you would like to set html font-size to 10px and scale Mantine components accordingly, you need to set scale to 1 / (10 / 16) (16 – default font-size) = 1 / 0.625 = 1.6:

:root {
  font-size: 10px;
}
import { MantineProvider, createTheme } from '@mantine/core';

const theme = createTheme({
  scale: 1.6,
});

function Demo() {
  return (
    <MantineProvider theme={theme}>
      <App />
    </MantineProvider>
  );
}

color prop improvements

All components that support color prop now support the following color values:

  • Key of theme.colors, for example, blue
  • theme.colors index reference, for example, blue.5
  • Any valid CSS color value, for example, #fff, rgba(0, 0, 0, 0.5), hsl(0, 0%, 100%)

Filled variant

Light variant

Outline variant

import { Group, Button, Text } from '@mantine/core';

function Demo() {
  return (
    <>
      <Text size="sm" mb={5} fw={500}>
        Filled variant
      </Text>
      <Group>
        <Button color="cyan">Theme color</Button>
        <Button color="#1D72FE">Hex color</Button>
      </Group>

      <Text size="sm" mb={5} mt="md" fw={500}>
        Light variant
      </Text>
      <Group>
        <Button variant="light" color="cyan">
          Theme color
        </Button>
        <Button variant="light" color="#1D72FE">
          Hex color
        </Button>
      </Group>

      <Text size="sm" mb={5} mt="md" fw={500}>
        Outline variant
      </Text>
      <Group>
        <Button variant="outline" color="cyan">
          Theme color
        </Button>
        <Button variant="outline" color="#1D72FE">
          Hex color
        </Button>
      </Group>
    </>
  );
}

Components classes

Classes of each component are now available in Component.classes object. For example, you can find Button classes in Button.classes:

KeyClass
rootm-77c9d27d
innerm-80f1301b
labelm-811560b9
sectionm-a74036a
loaderm-a25b86ee
groupm-80d6d844

You can use these classes to create components with the same styles as Mantine components:

import { Button } from '@mantine/core';

function Demo() {
  return <button type="button" className={Button.classes.root} />;
}

Theme object changes

  • theme.lineHeight is now theme.lineHeights – it is now possible to specify multiple line heights. theme.lineHeights values are used in the Text component.
  • theme.colorScheme is no longer available, use useMantineColorScheme to get color scheme value
  • theme.dir is no longer needed, direction is now managed by DirectionProvider
  • theme.loader was removed, you can now configure default loader with default props of Loader component
  • theme.transitionTimingFunction was removed
  • theme.focusRingStyles was replaced with theme.focusClassName
  • theme.activeStyles was replaced with theme.activeClassName
  • theme.globalStyles was removed
  • theme.fn functions were removed, some of the functions are available as standalone utilities
  • New theme.scale property controls rem units scaling
  • New theme.fontSmoothing property determines whether font smoothing styles should be applied to the body element
  • New theme.variantColorResolver property allows customizing component colors per variant

Colors generator

New @mantine/colors-generator package is now available to generate color palettes based on single color value. It is also available as online tool. Note that it is usually better to generate colors in advance to avoid contrast issues.

import { MantineProvider } from '@mantine/core';
import { generateColors } from '@mantine/colors-generator';

function Demo() {
  return (
    <MantineProvider
      theme={{
        colors: {
          'pale-blue': generateColors('#375EAC'),
        },
      }}
    >
      <App />
    </MantineProvider>
  );
}

New setup for RTL

@mantine/core package now exports DirectionProvider component, which should be used to configure the direction of the application. useDirection hook can be used to toggle direction. All components now include RTL styles by default, it is no longer required to set up additional plugins. See RTL documentation to learn more.

React 18+ only

Starting from version 7.0 Mantine no longer supports older React versions. The minimum supported version is now React 18. It is required because Mantine components now use useId and useSyncExternalStore hooks, which are available only in React 18.

left and right section

Components that previously had rightSection and icon props, now use leftSection instead of icon. Example of Button sections:

import { Button } from '@mantine/core';

function Demo() {
  return (
    <Button leftSection="left" rightSection="right">
      Label
    </Button>
  );
}

NumberInput changes

NumberInput was migrated to react-number-format. It now supports more features and has improvements in cursor position management. Due to migration, some of the props were renamed – follow the documentation to learn about the changes.

import { NumberInput } from '@mantine/core';

function Demo() {
  return (
    <>
      <NumberInput
        label="With prefix"
        placeholder="Dollars"
        prefix="$"
        defaultValue={100}
        mb="md"
      />
      <NumberInput
        label="With suffix"
        placeholder="Percents"
        suffix="%"
        defaultValue={100}
        mt="md"
      />
    </>
  );
}

Loader changes

Loader component is now built with CSS only. This change improves performance and reduces HTML output of the component.

Color
Size
Type
import { Loader } from '@mantine/core';

function Demo() {
  return <Loader color="blue" />;
}

Theme object no longer supports theme.loader property – it is also now possible to add custom loaders on theme with default props. Specified Loader will be used in all components that use it under the hood (LoadingOverlay, Button, ActionIcon, Stepper, etc.).

import { MantineProvider, Loader } from '@mantine/core';
import { RingLoader } from './RingLoader';

function Demo() {
  return (
    <MantineProvider
      theme={{
        components: {
          Loader: Loader.extend({
            defaultProps: {
              loaders: { ...Loader.defaultLoaders, ring: RingLoader },
              type: 'ring',
            },
          }),
        },
      }}
    >
      <Loader />
    </MantineProvider>
  );
}

Progress changes

Progress component now supports compound components pattern. Advanced features that were previously implemented in Progress are now supposed to be implemented with compound components instead.

Documents
Photos
Other
import { Progress } from '@mantine/core';

function Demo() {
  return (
    <Progress.Root size="xl">
      <Progress.Section value={35} color="cyan">
        <Progress.Label>Documents</Progress.Label>
      </Progress.Section>
      <Progress.Section value={28} color="pink">
        <Progress.Label>Photos</Progress.Label>
      </Progress.Section>
      <Progress.Section value={15} color="orange">
        <Progress.Label>Other</Progress.Label>
      </Progress.Section>
    </Progress.Root>
  );
}

Table changes

Table component changes:

  • Styles API support
  • It is now required to use compound components instead of elements: Table.Tr, Table.Td, etc.
  • It is now easier to override styles – all styles are added with classes instead of deeply nested selectors on root element
  • New props: borderColor, withRowBorders, stripedColor, highlightOnHoverColor
  • withBorder prop was renamed to withTableBorder
  • fontSize prop was removed, use fz style prop instead
  • New Table.ScrollContainer component to create scrollable table
Element positionElement nameSymbolAtomic mass
6CarbonC12.011
7NitrogenN14.007
39YttriumY88.906
56BariumBa137.33
58CeriumCe140.12
import { Table } from '@mantine/core';

function Demo() {
  const rows = elements.map((element) => (
    <Table.Tr key={element.name}>
      <Table.Td>{element.position}</Table.Td>
      <Table.Td>{element.name}</Table.Td>
      <Table.Td>{element.symbol}</Table.Td>
      <Table.Td>{element.mass}</Table.Td>
    </Table.Tr>
  ));

  return (
    <Table>
      <Table.Thead>
        <Table.Tr>
          <Table.Th>Element position</Table.Th>
          <Table.Th>Element name</Table.Th>
          <Table.Th>Symbol</Table.Th>
          <Table.Th>Atomic mass</Table.Th>
        </Table.Tr>
      </Table.Thead>
      <Table.Tbody>{rows}</Table.Tbody>
    </Table>
  );
}

Group changes

Group component changes:

  • position prop was renamed to justify – it now supports all justify-content values
  • noWrap prop was replaced with wrap="nowrap", wrap prop now supports all flex-wrap values
  • spacing prop was replaced with gap
  • Group now supports new preventGrowOverflow prop which allows customizing how group items will behave when they grow larger than their dedicated space
Gap
import { Group, Button } from '@mantine/core';

function Demo() {
  return (
    <Group>
      <Button variant="default">First</Button>
      <Button variant="default">Second</Button>
      <Button variant="default">Third</Button>
    </Group>
  );
}

Tabs changes

  • Styles API selector tabsList renamed to list
  • TabProps type was renamed to TabsTabProps
  • onTabChange prop was renamed to onChange
  • Tabs.List position prop was renamed to justify, it now supports all justify-content values

Button changes

  • compact prop was removed, use size="compact-XXX" instead
  • leftIcon and rightIcon props were renamed to leftSection and rightSection
  • uppercase prop was removed, use tt style prop instead
  • loaderPosition prop was removed, Loader is now always rendered in the center to prevent layout shifts
  • Styles API selectors were changed, see Button Styles API documentation for more details

AppShell changes

AppShell component was completely rewritten, it now supports more features:

  • AppShell now uses compound components pattern: Navbar, Aside, Header and Footer are no longer exported from @mantine/core package. Instead, use AppShell.Navbar, AppShell.Aside, etc.
  • AppShell now supports animations when navbar/aside are opened/closed
  • Navbar/aside can now be collapsed on desktop – state is handled separately for mobile and desktop
  • Header/footer can now be collapsed the same way as navbar/aside. For example, the header can be collapsed based on scroll position or direction.
  • AppShell no longer supports fixed prop – all components have position: fixed styles, static positioning is no longer supported
  • The documentation was updated, it now includes 10+ examples on a separate page

SimpleGrid changes

SimpleGrid now uses object format to define grid breakpoints and spacing, it works the same way as style props.

1

2

3

4

5

import { SimpleGrid } from '@mantine/core';

function Demo() {
  return (
    <SimpleGrid
      cols={{ base: 1, sm: 2, lg: 5 }}
      spacing={{ base: 10, sm: 'xl' }}
      verticalSpacing={{ base: 'md', sm: 'xl' }}
    >
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
    </SimpleGrid>
  );
}

Grid changes

Grid now uses object format in gutter, offset, span and order props, all props now work the same way as style props.

1
2
3
4
import { Grid } from '@mantine/core';

function Demo() {
  return (
    <Grid>
      <Grid.Col span={{ base: 12, md: 6, lg: 3 }}>1</Grid.Col>
      <Grid.Col span={{ base: 12, md: 6, lg: 3 }}>2</Grid.Col>
      <Grid.Col span={{ base: 12, md: 6, lg: 3 }}>3</Grid.Col>
      <Grid.Col span={{ base: 12, md: 6, lg: 3 }}>4</Grid.Col>
    </Grid>
  );
}

Image changes

Image component changes:

  • Image component no longer includes figure and other associated elements
  • caption prop is no longer available
  • width and height props are replaced with w and h style props
  • Placeholder functionality was replaced with fallback image
import { Image } from '@mantine/core';

function Demo() {
  return (
    <Image
      radius="md"
      src={null}
      h={200}
      fallbackSrc="https://placehold.co/600x400?text=Placeholder"
    />
  );
}

Spotlight changes

Spotlight changes:

  • The logic is no longer based on React context
  • SpotlightProvider was renamed to Spotlight
  • useSpotlight hook was removed, use spotlight object instead
  • actions prop now uses a different data format
  • It is now possible to have multiple spotlights in the same app
  • Spotlight component now uses compound components pattern for advanced customization
import { useState } from 'react';
import { Spotlight, spotlight } from '@mantine/spotlight';
import { Button } from '@mantine/core';
import { IconSearch } from '@tabler/icons-react';

const data = ['Home', 'About us', 'Contacts', 'Blog', 'Careers', 'Terms of service'];

function Demo() {
  const [query, setQuery] = useState('');

  const items = data
    .filter((item) => item.toLowerCase().includes(query.toLowerCase().trim()))
    .map((item) => <Spotlight.Action key={item} label={item} />);

  return (
    <>
      <Button onClick={spotlight.open}>Open spotlight</Button>

      <Spotlight.Root query={query} onQueryChange={setQuery}>
        <Spotlight.Search placeholder="Search..." leftSection={<IconSearch stroke={1.5} />} />
        <Spotlight.ActionsList>
          {items.length > 0 ? items : <Spotlight.Empty>Nothing found...</Spotlight.Empty>}
        </Spotlight.ActionsList>
      </Spotlight.Root>
    </>
  );
}

Carousel changes

Carousel now uses object format for responsive values in slideSize and slideGap props instead of breakpoints prop:

import { Carousel } from '@mantine/carousel';

function Demo() {
  return (
    <Carousel
      withIndicators
      height={200}
      slideSize={{ base: '100%', sm: '50%', md: '33.333333%' }}
      slideGap={{ base: 0, sm: 'md' }}
      loop
      align="start"
    >
      <Carousel.Slide>1</Carousel.Slide>
      <Carousel.Slide>2</Carousel.Slide>
      <Carousel.Slide>3</Carousel.Slide>
      {/* ...other slides */}
    </Carousel>
  );
}

@mantine/prism deprecation

@mantine/prism package was deprecated in favor of @mantine/code-highlight package. The new package uses highlight.js instead of Prism.

function Button() {
  return <button>Click me</button>;
}
import { CodeHighlightTabs } from '@mantine/code-highlight';
import { TypeScriptIcon, CssIcon } from '@mantine/ds';

const tsxCode = `
function Button() {
  return <button>Click me</button>;
}
`;

const cssCode = `
.button {
  background-color: transparent;
  color: var(--mantine-color-blue-9);
}
`;

function getFileIcon(fileName: string) {
  if (fileName.endsWith('.ts') || fileName.endsWith('.tsx')) {
    return <TypeScriptIcon size={18} />;
  }

  if (fileName.endsWith('.css')) {
    return <CssIcon size={18} />;
  }

  return null;
}

function Demo() {
  return (
    <CodeHighlightTabs
      getFileIcon={getFileIcon}
      code={[
        {
          fileName: 'Button.tsx',
          code: tsxCode,
          language: 'tsx',
        },
        {
          fileName: 'Button.module.css',
          code: cssCode,
          language: 'scss',
        },
      ]}
    />
  );
}

Fieldset component

New Fieldset component:

Personal information
Variant
Radius
import { Fieldset } from '@mantine/core';

function Demo() {
  return (
    <Fieldset legend="Personal information">
      <TextInput label="Your name" placeholder="Your name" />
      <TextInput label="Email" placeholder="Email" mt="md" />
    </Fieldset>
  );
}

Combobox component

The new Combobox component allows building custom select, autocomplete, tags input, multiselect and other similar components. It is used as a base for updated Autocomplete, Select, TagsInput and MultiSelect components.

Combobox is very flexible and allows you to have full control over the component rendering and logic. Advanced features that were previously implemented in Autocomplete, Select and MultiSelect are now supposed to be implemented with Combobox instead.

You can find 50+ Combobox examples on this page.

import { useState } from 'react';
import { Input, InputBase, Combobox, useCombobox } from '@mantine/core';

const groceries = ['🍎 Apples', '🍌 Bananas', '🥦 Broccoli', '🥕 Carrots', '🍫 Chocolate'];

function Demo() {
  const combobox = useCombobox({
    onDropdownClose: () => combobox.resetSelectedOption(),
  });

  const [value, setValue] = useState<string | null>(null);

  const options = groceries.map((item) => (
    <Combobox.Option value={item} key={item}>
      {item}
    </Combobox.Option>
  ));

  return (
    <Combobox
      store={combobox}
      onOptionSubmit={(val) => {
        setValue(val);
        combobox.closeDropdown();
      }}
    >
      <Combobox.Target>
        <InputBase
          component="button"
          pointer
          rightSection={<Combobox.Chevron />}
          onClick={() => combobox.toggleDropdown()}
        >
          {value || <Input.Placeholder>Pick value</Input.Placeholder>}
        </InputBase>
      </Combobox.Target>

      <Combobox.Dropdown>
        <Combobox.Options>{options}</Combobox.Options>
      </Combobox.Dropdown>
    </Combobox>
  );
}

TagsInput component

New TagsInput component based on Combobox component. The component is similar to MultiSelect but allows entering custom values.

import { TagsInput } from '@mantine/core';

function Demo() {
  return (
    <TagsInput
      label="Press Enter to submit a tag"
      placeholder="Pick tag from list"
      data={['React', 'Angular', 'Svelte']}
    />
  );
}

withErrorStyles prop

All inputs now support withErrorStyles prop, which allows removing error styles from the input. It can be used to apply custom error styles without override, or use other techniques to indicate error state. For example, it can be used to render an icon in the right section:

Something went wrong

Something went wrong

import { TextInput, rem } from '@mantine/core';
import { IconExclamationCircle } from '@tabler/icons-react';

function Demo() {
  return (
    <>
      <TextInput placeholder="Error as boolean" label="Error as boolean" error />
      <TextInput
        mt="md"
        placeholder="Error as react node"
        label="Error as react node"
        error="Something went wrong"
      />

      <TextInput
        mt="md"
        placeholder="Without error styles on input"
        label="Without error styles on input"
        error="Something went wrong"
        withErrorStyles={false}
        rightSectionPointerEvents="none"
        rightSection={
          <IconExclamationCircle
            style={{ width: rem(20), height: rem(20) }}
            color="var(--mantine-color-error)"
          />
        }
      />
    </>
  );
}

hiddenFrom and visibleFrom props

All Mantine components now support hiddenFrom and visibleFrom props. These props accept breakpoint (xs, sm, md, lg, xl) and hide the component when viewport width is less than or greater than the specified breakpoint:

import { Button, Group } from '@mantine/core';

function Demo() {
  return (
    <Group justify="center">
      <Button hiddenFrom="sm" color="orange">
        Hidden from sm
      </Button>
      <Button visibleFrom="sm" color="cyan">
        Visible from sm
      </Button>
      <Button visibleFrom="md" color="pink">
        Visible from md
      </Button>
    </Group>
  );
}

Other changes

  • New VisuallyHidden component
  • New ActionIcon.Group component
  • DatesProvider now supports setting timezone
  • All transitions are now disabled during color scheme change
  • theme.respectReducedMotion is now set to false by default – it caused a lot of confusion for users who did not know about it
  • Notifications system now exports notifications.updateState function to update notifications state with a given callback
  • Blockquote component has new design
  • Breadcrumbs component now supports separatorMargin prop
  • Tooltip component now supports mainAxis and crossAxis offset configuration
  • Slider and RangeSlider components radius prop now affects thumb as well as track
  • NativeSelect component now supports setting options as children and options groups
  • Anchor component now supports underline prop which lets you configure how link will be underlined: hover (default), always or never
  • Affix component no longer supports target prop, use portalProps instead
  • Container component no longer supports sizes prop, use CSS variables to customize sizes on theme instead
  • useComponentDefaultProps hook was renamed to useProps
  • withinPortal prop is now true by default in all overlay components (Popover, HoverCard, Tooltip, etc.)
  • AlphaSlider and HueSlider components are no longer available, they can be used only as a part of ColorPicker
  • Text default root element is now <p />
  • Title no longer supports all Text props, only style props are available
  • MediaQuery component was removed – use CSS modules to apply responsive styles
  • Highlight component prop highlightColor was renamed to color
  • Tooltip and Tooltip.Floating components no longer support width prop, use w style prop instead
  • Stack component spacing prop was renamed to gap
  • Input and other Input based components icon prop was renamed to leftSection
  • Loader component variant prop was renamed to type
  • @mantine/core package no longer depends on Radix UI ScrollArea, ScrollArea component is now a native Mantine component – it reduces bundle size, allows setting CSP for styles and improves performance (all styles are now applied with classes instead of inline <style /> tags)
  • Overlay opacity prop was renamed to backgroundOpacity to avoid collision with opacity style prop
  • Badge Styles API selectors were changed, see Badge Styles API documentation for more details
  • Slider Styles API selectors were changed, see Slider Styles API documentation for more details
  • Text component no longer supports underline, color, strikethrough, italic, transform, align and weight prop – use style props instead
  • Portal component innerRef prop was renamed to ref
  • ScrollArea now supports x and y values in offsetScrollbars prop
  • TransferList component is no longer available as a part of @mantine/core package, instead you can implement it with Combobox component (example)
  • Chip component now supports custom check icon
  • PasswordInput no longer supports visibilityToggleLabel and toggleTabIndex props, use visibilityToggleButtonProps prop instead
  • Stepper now longer supports breakpoint prop, you can apply responsive styles with Styles API
  • ColorInput no longer supports dropdownZIndex, transitionProps, withinPortal, portalProps and shadow props, you can now pass these props with popoverProps prop
  • LoadingOverlay props are now grouped by the component they are passed down to: overlayProps, loaderProps and transitionProps now replace props that were previously passed to LoadingOverlay directly
  • Dropzone component no longer supports padding prop, use p style prop instead
  • Dialog component now supports all Paper and Affix props, transitionDuration, transition and other transition related props were replaced with transitionProps
  • Checkbox, Radio, Chip and Switch components now support rootRef prop which allows using them with Tooltip and other similar components