## File: README.md

# Mantine

[](https://github.com/mantinedev/mantine/blob/master/LICENSE)
[](https://opencollective.com/mantinedev)
[](https://github.com/mantinedev/mantine/graphs/contributors)
[](https://www.npmjs.com/package/@mantine/core)
[](https://www.npmjs.com/package/@mantine/hooks)
[](https://github.com/mantinedev/mantine/labels/help%20wanted)
[](https://discord.gg/wbH82zuWMN)
[](https://x.com/mantinedev)

## Links

- [Documentation](https://mantine.dev/)
- [Contribute](https://mantine.dev/contribute)
- [Ask question or give feedback](https://github.com/mantinedev/mantine/discussions)
- [Changelog](https://mantine.dev/changelog/all-releases)
- [Follow on X](https://x.com/mantinedev)
- [Join Discord community](https://discord.gg/wbH82zuWMN)

## Packages

- [`@mantine/hooks`](https://mantine.dev/hooks/package/) – collection of 80+ hooks for state and UI management
- [`@mantine/core`](https://mantine.dev/core/package/) – core components library – 100+ components
- [`@mantine/form`](https://mantine.dev/form/use-form) – forms management library
- [`@mantine/charts`](https://mantine.dev/charts/getting-started/) – recharts based charts library
- [`@mantine/notifications`](https://mantine.dev/x/notifications) – a fully featured notifications system
- [`@mantine/spotlight`](https://mantine.dev/x/spotlight) – `Ctrl + K` command center for your application
- [`@mantine/code-highlight`](https://mantine.dev/x/code-highlight/) – code highlight built with [highlight.js](https://highlightjs.org/)
- [`@mantine/tiptap`](https://mantine.dev/x/tiptap) – a Tiptap based rich text editor
- [`@mantine/dropzone`](https://mantine.dev/x/dropzone) – manages files drag 'n' drop to an area or entire screen
- [`@mantine/carousel`](https://mantine.dev/x/carousel) – Carousel component
- [`@mantine/nprogress`](https://mantine.dev/x/nprogress) – navigation progress
- [`@mantine/modals`](https://mantine.dev/x/modals) – centralized modals manager
- [`@mantine/schedule`](https://mantine.dev/x/schedule) – Schedule component for displaying events

## Getting help

Mantine has a very friendly community, we are always happy to help you get started:

- [Join Discord community](https://discord.gg/wbH82zuWMN) – it is the easiest way to get help, all questions are usually answered in about 30 minutes
- [GitHub Discussions](https://github.com/mantinedev/mantine/discussions) – ask anything about the project or give feedback

## Contributors

<a href="https://github.com/mantinedev/mantine/graphs/contributors">
  
</a>

[Become a contributor](https://mantine.dev/contribute)

## Support development

[](https://opencollective.com/mantinedev)

Mantine is a MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome [backers](https://opencollective.com/mantinedev). If you'd like to join them, please consider contributing financially on [OpenCollective](https://opencollective.com/mantinedev).

[](https://opencollective.com/mantinedev)

## License

MIT

---

## File: apps/mantine.dev/src/pages/guides/6x-to-7x.mdx

import { ThemingDemos } from '@docs/demos';
import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.SixToSeven);

# 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](/changelog/7-0-0).

## 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](/styles/emotion).

### createStyles and Global component

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

```tsx
// 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](/styles/emotion):

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

function Demo() {
  return (
    <>
       ({ backgroundColor: theme.colors.red[5] })}
      />
      
    </>
  );
}
```

### theme.colorScheme

In v7, the color scheme value is managed by [MantineProvider](/theming/mantine-provider),
and the [theme object](/theming/theme-object) no longer includes the `colorScheme` property.
Although it's still possible to access the color scheme value in components with the
[useMantineColorScheme](/theming/color-schemes#use-mantine-color-scheme-hook) hook,
it's not recommended to base your styles on its value. Instead, use the `light`/`dark`
[utilities](/styles/emotion#utilities).

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

```tsx
// 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,
  },
}));
```

```tsx
// 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](/styles/css-modules) documentation.
The most notable sections are:

- [CSS Modules](/styles/css-modules)
- [Mantine PostCSS preset](/styles/postcss-preset)
- [CSS variables](/styles/css-variables)
- [data-\* attributes](/styles/data-attributes)
- [Styles API](/styles/styles-api)
- [Responsive styles](/styles/responsive)

Note that this guide assumes you have [postcss-preset-mantine](/styles/postcss-preset) installed and configured
in your project.

### createStyles

The `createStyles` function is no longer available in 7.0. Use [CSS Modules](/styles/css-modules) instead.

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

const useStyles = createStyles((theme) => ({
  root: {
    backgroundColor: theme.colors.red[5],
  },
}));
```

```scss
/* 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](/styles/style) instead.

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

function Demo() {
  return (
     ({ backgroundColor: theme.colors.red[5] })} />
  );
}
```

```tsx
// 7.0
import { Box } from '@mantine/core';

function Demo() {
  return (
    
  );
}
```

Nested selectors are not supported in the [style prop](/styles/style); use `className` instead:

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

function Demo() {
  return ;
}
```

```scss
.box {
  &:hover {
    background: red;
  }
}
```

### styles prop

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

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

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

```scss
/* 7.0 */
.input {
  &:focus {
    color: red;
  }
}
```

Regular selectors are still supported:

```tsx
// 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.

```tsx
// 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',
        },
      })}
    />
  );
}
```

```scss
/* 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](/theming/theme-object) properties are now available as [CSS variables](/styles/css-variables). We recommend using
[CSS variables](/styles/css-variables) instead of referencing the theme object in styles.

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

function Demo() {
  return (
     ({
        backgroundColor: theme.colors.red[6],
        color: theme.white,
        padding: `calc(${theme.spacing.xl} * 2)`,
      })}
    />
  );
}
```

```scss
/* 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](/theming/mantine-provider),
and the [theme object](/theming/theme-object) no longer includes the `colorScheme` property.
Although it's still possible to access the color scheme value in components with the
[useMantineColorScheme](/theming/color-schemes#use-mantine-color-scheme-hook) hook,
it's not recommended to base your styles on its value. Instead, use the `light`/`dark`
[mixins](/styles/postcss-preset) or the `light-dark` CSS [function](/styles/postcss-preset#light-dark-function).

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

```tsx
// 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,
  },
}));
```

```scss
/* 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](/theming/color-schemes#color-scheme-value-caveats)).
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:

<Demo data={ThemingDemos.colorSchemeControl} />

---

## File: apps/mantine.dev/src/pages/guides/7x-to-8x.mdx

import { PopoverDemos } from '@docs/demos';
import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.SevenToEight);

# 7.x → 8.x migration guide

## Global styles imports

If you used separate styles imports from `@mantine/core/styles/global.css`, you need to update imports to use new files.
Note that if you previously imported `@mantine/core/styles.css`, no changes are required – all new files are already included in `styles.css`.

7.x version import:
```tsx
// ❌ No longer includes all global styles
import '@mantine/core/styles/global.css';
```

8.x version import:
```tsx
// ✅ Import all global styles separately
import '@mantine/core/styles/baseline.css';
import '@mantine/core/styles/default-css-variables.css';
import '@mantine/core/styles/global.css';
```

If you used `@mantine/core/styles.css`, no changes are required;
the import works the same in 7.x and 8.x versions:
```tsx
// 👍 No changes needed if you used styles.css
import '@mantine/core/styles.css';
```

## Portal reuseTargetNode

The `reuseTargetNode` prop of the [Portal](/core/portal) component is now enabled by default.
This option improves performance by reusing the target node between portal renders, but
in some edge cases, it might cause issues with `z-index` stacking context.

If you experience issues with `z-index`, change the `reuseTargetNode` prop to `false` in theme:

```tsx
import { createTheme, Portal } from '@mantine/core';

export const theme = createTheme({
  components: {
    Portal: Portal.extend({
      defaultProps: {
        // ✅ Disable reuseTargetNode by default if your application has z-index issues
        reuseTargetNode: false,
      },
    }),
  }
});
```

## Switch withThumbIndicator

The [Switch](/core/switch) component's default styles have been updated; it now
includes a checked state indicator inside the thumb. If you want to use the
old styles without the indicator, set the `withThumbIndicator` prop to `false` in the theme:

```tsx
import { createTheme, Switch } from '@mantine/core';

export const theme = createTheme({
  components: {
    Switch: Switch.extend({
      defaultProps: {
        // ✅ Disable withThumbIndicator if you want to use old styles
        withThumbIndicator: false,
      },
    }),
  }
});
```

## Date string values

`@mantine/dates` components now use date string values in `onChange` and other callbacks.
If you want to continue using `@mantine/dates` components the same way as in 7.x, you need
to convert callback values to `Date` objects:

```tsx
import { useState } from 'react';
import { DatePicker } from '@mantine/dates';

export function Demo7x() {
  const [value, setValue] = useState<Date | null>(null);
  // ⛔ 7.x – onChange is called with Date object
  return <DatePicker value={value} onChange={setValue} />
}

export function Demo8x() {
  const [value, setValue] = useState<Date | null>(null);
  // ✅ 8.x – onChange is called with string date value (for example '1994-08-21')
  // You can either
  // 1. Convert it to Date object to preserve old behavior
  // 2. Update your code to use date string values instead
  return <DatePicker value={value} onChange={val => setValue(new Date(val))} />
}
```

## DatesProvider timezone

The `DatesProvider` component no longer supports the `timezone` option:

```tsx
import { DatesProvider } from '@mantine/dates';

function Demo7x() {
  // ❌ The timezone option is no longer supported
  return (
    <DatesProvider settings={{ timezone: 'UTC', consistentWeeks: true }}>
      App
    </DatesProvider>
  );
}

function Demo8x() {
  // ✅ Remove the timezone option
  return (
    <DatesProvider settings={{ consistentWeeks: true }}>
      App
    </DatesProvider>
  );
}
```

If you need to handle timezones in your application, you can use a dedicated date library
([dayjs](https://day.js.org/), [luxon](https://moment.github.io/luxon/#/), [date-fns](https://date-fns.org/))
to update timezone values. Example of using Mantine components with [dayjs](https://day.js.org/):

```tsx
import dayjs from 'dayjs';
import { DatePicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<string | null>('2022-08-21');

  // Mantine components use strings as values; you can pass these
  // strings to a date library of your choice to assign a timezone
  const dateWithTimeZone = dayjs(value).tz("America/Toronto").toDate();

  return <DatePicker value={value} onChange={setValue} />;
}
```

## DateTimePicker timeInputProps

The [DateTimePicker](/dates/date-time-picker) component no longer accepts the `timeInputProps` prop,
as the underlying [TimeInput](/dates/time-input) component was replaced with [TimePicker](/dates/time-picker).
To pass props down to the [TimePicker](/dates/time-picker) component, use the `timePickerProps` prop instead.

7.x version:

```tsx
import { DateTimePicker } from '@mantine/dates';
import { ClockIcon } from '@phosphor-icons/react';

function Demo() {
  return (
    <DateTimePicker
      // ❌ timeInputProps is no longer available
      timeInputProps={{
        leftSection: <ClockIcon size={16} />,
      }}
    />
  );
}
```

8.x version:

```tsx
import { DateTimePicker } from '@mantine/dates';

function Demo() {
  return (
    <DateTimePicker
      // ✅ Use timePickerProps instead of timeInputProps
      timePickerProps={{
        leftSection: <ClockIcon size={16} />,
        minutesStep: 5,
        withDropdown: true,
      }}
    />
  );
}
```

## CodeHighlight usage

The [@mantine/code-highlight](/x/code-highlight) package no longer depends on [highlight.js](https://highlightjs.org).
You can follow the [updated documentation](/x/code-highlight/) to set up syntax highlighting with [shiki](https://shiki.matsu.io/).

If you want to continue using [highlight.js](https://highlightjs.org/) in your application,
install the `highlight.js` package:



Then wrap your app with `CodeHighlightAdapterProvider` and provide `createHighlightJsAdapter` as the `adapter` prop:

```tsx
import { MantineProvider } from '@mantine/core';
import { CodeHighlightAdapterProvider, createHighlightJsAdapter } from '@mantine/code-highlight';
import hljs from 'highlight.js/lib/core';
import tsLang from 'highlight.js/lib/languages/typescript';

hljs.registerLanguage('typescript', tsLang);

const highlightJsAdapter = createHighlightJsAdapter(hljs);

function App() {
  return (
    <MantineProvider>
      <CodeHighlightAdapterProvider adapter={highlightJsAdapter}>
        {/* Your app here */}
      </CodeHighlightAdapterProvider>
    </MantineProvider>
  );
}
```

Then you need to add styles from one of the highlight.js themes to your application.
You can do that by importing a CSS file from the `highlight.js` package or adding it via a
CDN link to the head of your application:

```html
<link
  rel="stylesheet"
  href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"
/>
```

After that, you can use the `CodeHighlight` component in your application the same way you did in the 7.x version.

## Menu data-hovered attribute

[Menu.Item](/core/menu) no longer uses the `data-hovered` attribute to indicate hovered state.
If you used `data-hovered` in your styles, you need to change it to `:hover` and `:focus` selectors
instead:

```scss
// ❌ 7.x – styles with `data-hovered`,
// no longer works in 8.x
.item {
  &[data-hovered] {
    background-color: red;
  }
}

// ✅ 8.x – use styles with `:hover` and `:focus`
.item {
  &:hover,
  &:focus {
    background-color: red;
  }
}
```

## Popover hideDetached

[Popover](/core/popover) now supports the `hideDetached` prop to automatically close the popover when the target element is removed from the DOM:

<Demo data={PopoverDemos.hideDetached} demoProps={{ defaultExpanded: false }} />

By default, `hideDetached` is enabled – the behavior has changed from the 7.x version.
If you prefer to keep the old behavior, you can disable `hideDetached` for all components:

```tsx
import { createTheme, Popover } from '@mantine/core';

export const theme = createTheme({
  components: {
    Popover: Popover.extend({
      defaultProps: {
        // ✅ Disable hideDetached by default
        // if you want to keep the old behavior
        hideDetached: false,
      },
    }),
  }
});
```

## Carousel changes

Starting from the 8.x version, the [@mantine/carousel](/x/carousel) package requires
`embla-carousel` and `embla-carousel-react` packages with version 8.x.

You need to update embla dependencies:



Update embla props that were previously passed to the `Carousel` component
to `emblaOptions`. Full list of props:

- `loop`
- `align`
- `slidesToScroll`
- `dragFree`
- `inViewThreshold`
- `skipSnaps`
- `containScroll`
- `speed` and `draggable` props were removed – they are no longer supported by embla

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

// ❌ 7.x – embla options passed as props,
// no longer works in 8.x
function Demo7x() {
  return <Carousel loop dragFree align="start" />
}

// ✅ 8.x – use emblaOptions to pass options to embla
function Demo8x() {
  return <Carousel emblaOptions={{ loop: true, dragFree: true, align: 'start' }} />
}
```

The `useAnimationOffsetEffect` hook was removed; it is no longer required, and you need to
remove it from your code:

```tsx
// ❌ 7.x – useAnimationOffsetEffect is no longer available in 8.x
import { Carousel, Embla, useAnimationOffsetEffect } from '@mantine/carousel';

function Demo7x() {
  const [embla, setEmbla] = useState(null);
  useAnimationOffsetEffect(embla, TRANSITION_DURATION);
  return <Carousel getEmblaApi={setEmbla} />;
}

// ✅ 8.x – remove useAnimationOffsetEffect entirely; it is not required
import { Carousel } from '@mantine/carousel';

function Demo8x() {
  return <Carousel />;
}
```

The `Embla` type is no longer exported from the `@mantine/carousel` package;
you need to change this import to reference the `embla-carousel` package instead:

```tsx
// ❌ 7.x – The Embla type is no longer available in 8.x
import { Carousel, Embla } from '@mantine/carousel';

function Demo7x() {
  const [embla, setEmbla] = useState(null);
  return <Carousel getEmblaApi={setEmbla} />;
}

// ✅ 8.x – replace the Embla type import
import { Carousel } from '@mantine/carousel';
import { EmblaCarouselType } from 'embla-carousel';

function Demo8x() {
  const [embla, setEmbla] = useState(null);
  return <Carousel getEmblaApi={setEmbla} />;
}
```

---

## File: apps/mantine.dev/src/pages/guides/functions-reference.mdx

import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.FunctionsReference);

# Functions reference

This guide contains a list of functions exported from Mantine packages that
are not documented elsewhere.

## clamp

The `clamp` function is exported from `@mantine/hooks`.
It clamps a number within the inclusive lower and upper bounds.

```tsx
import { clamp } from '@mantine/hooks';

// With both min and max boundaries
clamp(10, 0, 5); // 5
clamp(100, 0, 5); // 5
clamp(-100, 0, 5); // 0

// With only min boundary
clamp(10, 0, undefined); // 10
clamp(-100, 0, undefined); // 0

// With only max boundary
clamp(0, undefined, 5); // 0
clamp(10, undefined, 5); // 5
```

## lowerFirst

The `lowerFirst` function is exported from `@mantine/hooks`.
It converts the first character of a string to lowercase.

```tsx
import { lowerFirst } from '@mantine/hooks';

lowerFirst('Mantine'); // mantine
lowerFirst('mantine'); // mantine
```

## upperFirst

The `upperFirst` function is exported from `@mantine/hooks`.
It converts the first character of a string to uppercase.

```tsx
import { upperFirst } from '@mantine/hooks';

upperFirst('Mantine'); // Mantine
upperFirst('mantine'); // Mantine
```

## randomId

The `randomId` function is exported from `@mantine/hooks`.
It generates a random id with the `mantine-` prefix.

```tsx
import { randomId } from '@mantine/hooks';

randomId(); // mantine-d7h137oav
randomId(); // mantine-1q2j3j4j5
```

## range

The `range` function is exported from `@mantine/hooks`.
It generates an array of numbers from `start` to `end` (inclusive).

```tsx
import { range } from '@mantine/hooks';

range(0, 5); // [0, 1, 2, 3, 4, 5]
range(5, 0); // [5, 4, 3, 2, 1, 0]
```

## shallowEqual

The `shallowEqual` function is exported from `@mantine/hooks`.
It performs a shallow equality check of two objects.

```tsx
import { shallowEqual } from '@mantine/hooks';

shallowEqual({ a: 1 }, { a: 1 }); // true
shallowEqual({ a: 1 }, { a: 2 }); // false
```

## keys

The `keys` function is exported from `@mantine/core`.
It is a type-safe wrapper around `Object.keys` – it returns
an array of keys typed as `(keyof T)[]` instead of `string[]`.

```tsx
import { keys } from '@mantine/core';

const data = { name: 'Mantine', age: 4 };
const result = keys(data); // ('name' | 'age')[]
```

## deepMerge

The `deepMerge` function is exported from `@mantine/core`.
It recursively merges properties of the source object into the target object.
Arrays are not merged – they are replaced entirely by the source value.

```tsx
import { deepMerge } from '@mantine/core';

deepMerge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });
// { a: 1, b: { c: 2, d: 3 } }

deepMerge({ a: 1 }, { a: 2, b: 3 });
// { a: 2, b: 3 }
```

## filterProps

The `filterProps` function is exported from `@mantine/core`.
It removes all `undefined` properties from the given object.

```tsx
import { filterProps } from '@mantine/core';

filterProps({ a: 1, b: undefined, c: 'hello' });
// { a: 1, c: 'hello' }
```

## isElement

The `isElement` function is exported from `@mantine/core`.
It is a type guard that checks whether a value is a React element.
Returns `false` for arrays, `null`, and React Fragments.

```tsx
import { isElement } from '@mantine/core';

isElement(); // true
isElement('string'); // false
isElement(null); // false
isElement(<></>); // false
```

## isNumberLike

The `isNumberLike` function is exported from `@mantine/core`.
It checks whether a value is a number or a string that represents
a CSS numeric value (including `calc()`, `var()`, and CSS units).

```tsx
import { isNumberLike } from '@mantine/core';

isNumberLike(10); // true
isNumberLike('10px'); // true
isNumberLike('1.5rem'); // true
isNumberLike('calc(100% - 10px)'); // true
isNumberLike('var(--size)'); // true
isNumberLike('hello'); // false
```

## camelToKebabCase

The `camelToKebabCase` function is exported from `@mantine/core`.
It converts a camelCase string to kebab-case.

```tsx
import { camelToKebabCase } from '@mantine/core';

camelToKebabCase('backgroundColor'); // 'background-color'
camelToKebabCase('fontSize'); // 'font-size'
camelToKebabCase('color'); // 'color'
```

## getDefaultZIndex

The `getDefaultZIndex` function is exported from `@mantine/core`.
It returns the default z-index value for a given elevation level.

```tsx
import { getDefaultZIndex } from '@mantine/core';

getDefaultZIndex('app'); // 100
getDefaultZIndex('modal'); // 200
getDefaultZIndex('popover'); // 300
getDefaultZIndex('overlay'); // 400
getDefaultZIndex('max'); // 9999
```

## closeOnEscape

The `closeOnEscape` function is exported from `@mantine/core`.
It creates a keyboard event handler that calls the given callback
when the Escape key is pressed.

```tsx
import { closeOnEscape } from '@mantine/core';

// Basic usage
 setOpened(false))} />;

// With options
 setOpened(false), {
    active: isOpened,
    onTrigger: () => console.log('closed'),
  })}
/>;
```

## noop

The `noop` function is exported from `@mantine/core`.
It is a no-operation function that does nothing. Useful as a
default callback.

```tsx
import { noop } from '@mantine/core';

const onClick = handler || noop;
```

## findClosestNumber

The `findClosestNumber` function is exported from `@mantine/core`.
It finds the number in the given array that is closest to the
provided value. Returns the value itself if the array is empty.

```tsx
import { findClosestNumber } from '@mantine/core';

findClosestNumber(3, [1, 5, 10]); // 1
findClosestNumber(7, [1, 5, 10]); // 5
findClosestNumber(9, [1, 5, 10]); // 10
findClosestNumber(5, []); // 5
```

## toDateString

The `toDateString` function is exported from `@mantine/dates`.
It converts a date value to a `YYYY-MM-DD` string.
Accepts `Date`, `string`, `number`, and dayjs objects.
Returns `null` or `undefined` if the input is `null` or `undefined`.

```tsx
import { toDateString } from '@mantine/dates';

toDateString(new Date(2025, 0, 15)); // '2025-01-15'
toDateString('2025-01-15 14:30:00'); // '2025-01-15'
toDateString(null); // null
toDateString(undefined); // undefined
```

## toDateTimeString

The `toDateTimeString` function is exported from `@mantine/dates`.
It converts a date value to a `YYYY-MM-DD HH:mm:ss` string.
Accepts `Date`, `string`, `number`, and dayjs objects.
Returns `null` or `undefined` if the input is `null` or `undefined`.

```tsx
import { toDateTimeString } from '@mantine/dates';

toDateTimeString(new Date(2025, 0, 15, 14, 30, 0)); // '2025-01-15 14:30:00'
toDateTimeString('2025-01-15'); // '2025-01-15 00:00:00'
toDateTimeString(null); // null
```

## assignTime

The `assignTime` function is exported from `@mantine/dates`.
It assigns a time string in `HH:mm:ss` format to a date value,
returning a `YYYY-MM-DD HH:mm:ss` string. If the date value is `null`,
the current date is used.

```tsx
import { assignTime } from '@mantine/dates';

assignTime('2025-01-15', '14:30:00'); // '2025-01-15 14:30:00'
assignTime('2025-01-15 08:00:00', '20:15:30'); // '2025-01-15 20:15:30'
assignTime(null, '10:00:00'); // '[current date] 10:00:00'
```

## clampDate

The `clampDate` function is exported from `@mantine/dates`.
It clamps a date between optional min and max boundaries, returning
a `YYYY-MM-DD HH:mm:ss` string.

```tsx
import { clampDate } from '@mantine/dates';

clampDate('2025-01-01', '2025-12-31', '2025-06-15');
// '2025-06-15 00:00:00' – within range

clampDate('2025-01-01', '2025-12-31', '2024-06-15');
// '2025-01-01 00:00:00' – clamped to min

clampDate('2025-01-01', '2025-12-31', '2026-06-15');
// '2025-12-31 00:00:00' – clamped to max

clampDate(undefined, undefined, '2025-06-15');
// '2025-06-15 00:00:00' – no boundaries
```

---

## File: apps/mantine.dev/src/pages/guides/gatsby.mdx

import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.Gatsby);

# Usage with Gatsby

<GetTemplates type="gatsby" />

## Generate new application

Follow the [Gatsby quick start](https://www.gatsbyjs.com/docs/quick-start/) guide to
create a new Gatsby application:

<NpmScript
  yarnScript="yarn create gatsby"
  npmScript="npm init gatsby"
/>

When asked "Would you like to install a styling system?", select `PostCSS`.

## Installation



## PostCSS setup

Install PostCSS plugins and [postcss-preset-mantine](/styles/postcss-preset):



Create a `postcss.config.cjs` file at the root of your application with the following content:

```js
module.exports = {
  plugins: {
    'postcss-preset-mantine': {},
    'postcss-simple-vars': {
      variables: {
        'mantine-breakpoint-xs': '36em',
        'mantine-breakpoint-sm': '48em',
        'mantine-breakpoint-md': '62em',
        'mantine-breakpoint-lg': '75em',
        'mantine-breakpoint-xl': '88em',
      },
    },
  },
};
```

## Setup

Create a `src/theme.ts` file with your theme override:

```tsx
// src/theme.ts
import { createTheme } from '@mantine/core';

export const theme = createTheme({
  fontFamily: 'serif',
  // ... other theme override properties
});
```

Create a `gatsby-ssr.tsx` file with the following content:

```tsx
import { ColorSchemeScript, MantineProvider } from '@mantine/core';
import { theme } from './src/theme';

export const onPreRenderHTML = ({
  getHeadComponents,
  replaceHeadComponents,
}) => {
  const headComponents = getHeadComponents();
  replaceHeadComponents([
    ...headComponents,
    <ColorSchemeScript key="color-scheme-script" />,
  ]);
};

export const wrapPageElement = ({ element }) => {
  return <MantineProvider theme={theme}>{element}</MantineProvider>;
};
```

Create a `gatsby-browser.tsx` file with the following content:

```tsx
// Import styles of packages that you've installed.
// All packages except `@mantine/hooks` require styles imports
import '@mantine/core/styles.css';

import { MantineProvider } from '@mantine/core';
import { theme } from './src/theme';

export const wrapPageElement = ({ element }) => {
  return <MantineProvider theme={theme}>{element}</MantineProvider>;
};
```

All set! Start the development server:

```bash
npm run develop
```

## CSS modules

By default, Gatsby has different syntax for importing CSS modules:

```tsx
// Default syntax – will not work in Gatsby
import classes from './Demo.module.css';

// Gatsby syntax
import * as classes from './Demo.module.css';
```

---

## File: apps/mantine.dev/src/pages/guides/icons.mdx

import { GuidesDemos } from '@docs/demos';
import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.Icons);

# Icon libraries with Mantine

You can use any icon library with Mantine components. The most popular options are:

- [Phosphor icons](https://phosphoricons.com/)
- [Tabler icons](https://tabler-icons.io/)
- [Feather icons](https://feathericons.com/)
- [Radix icons](https://icons.radix-ui.com/)
- [react-icons](https://react-icons.github.io/react-icons/)
- [Font Awesome](https://fontawesome.com/v5/docs/web/use-with/react)

## Phosphor icons

[Phosphor icons](https://phosphoricons.com/) are used in Mantine demos, documentation,
and some `@mantine/` packages depend on them. If you don't know which icon library
to use, we recommend [Phosphor icons](https://phosphoricons.com/).

## Icon size

Most icon libraries support a `size` prop (or similar `width` and `height` props) that allows you to change the
icon width and height. Usually, it's a number in pixels.

<Demo data={GuidesDemos.icon} />

> **rem units in size prop**
>
> The icon `size` prop is usually converted to `width` and `height` props under the hood.
> If you set `size={16}` it will be converted to `width="16"` and `height="16"` attributes
> on the svg element.
>
> You can use rem units in the `size` prop: `size="1rem"` will be converted to `width="1rem"` and `height="1rem"`,
> but it's not recommended as it's prohibited by the SVG standard – some browsers (Firefox) will show a warning in the console.

## Custom icons

We recommend using icons as React components. In this case, you'll be able to use
`currentColor` in the `fill` and `stroke` props. This will change the icon color based on the context
it's used in.

<Demo data={GuidesDemos.customIcon} />

---

## File: apps/mantine.dev/src/pages/guides/javascript.mdx

import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.JavaScript);

# Usage with JavaScript

## Is it possible to use Mantine with JavaScript?

Yes, it's possible to use all `@mantine/*` packages (as well as all other npm packages) with JavaScript.
`@mantine/*` packages are written in TypeScript and have type definitions, so you'll get some benefits
of TypeScript (like autocompletion in your IDE) when using them with JavaScript.

## Transforming demos code to JavaScript

All demos in Mantine documentation are written in TypeScript. In most cases, there's no difference between
TypeScript and JavaScript code – you don't have to do anything.

To transform TypeScript code to JavaScript, you can use the [TypeScript playground](https://www.typescriptlang.org/play?jsx=1&preserveValueImports=false#code/Q)
– paste the demo code into the playground and all types will be removed. Note that you'll also need
to remove type imports from the code.

Example of transformed code:

```tsx
// TypeScript code
import { Button, ButtonProps } from '@mantine/core';

interface MyButtonProps extends ButtonProps {
  myProp: string;
}

function MyButton({ myProp, ...others }: MyButtonProps) {
  return ;
}
```

```tsx
// JavaScript code
import { Button } from '@mantine/core';

function MyButton({ myProp, ...others }) {
  return ;
}
```

## Should Mantine be used with JavaScript?

We recommend using Mantine with TypeScript. It doesn't require deep knowledge of TypeScript
and will make your code more robust and easier to maintain. For example, you'll get type errors
when you pass invalid props to components or when you use non-existent props. TypeScript will also
help you during migration to new versions of Mantine – you'll get type errors when props/components
that you have in your code are removed/renamed/changed.

If you're not familiar with TypeScript yet, using Mantine with TypeScript will be a great opportunity
to learn it. You can use any of the [templates](/getting-started) to get started – all of them include
TypeScript support out of the box.

---

## File: apps/mantine.dev/src/pages/guides/jest.mdx

import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.Jest);

# Testing with Jest

This guide will help you set up [Jest](https://jestjs.io/) and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) for your project.
Note that this guide only covers shared logic that can be applied to any framework, and
it doesn't cover the initial setup of [Jest](https://jestjs.io/) and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) as it may vary depending on the framework you're using.

## Custom render

All Mantine components require [MantineProvider](/theming/mantine-provider/) to be present in the component tree.
To add [MantineProvider](/theming/mantine-provider/) to the component tree in your tests, create a [custom render](https://testing-library.com/docs/react-testing-library/setup/#custom-render)
function:

```tsx
// ./test-utils/render.tsx
import { render as testingLibraryRender } from '@testing-library/react';
import { MantineProvider } from '@mantine/core';
// Import your theme object
import { theme } from '../src/theme';

export function render(ui: React.ReactNode) {
  return testingLibraryRender(<>{ui}</>, {
    wrapper: ({ children }: { children: React.ReactNode }) => (
      <MantineProvider theme={theme} env="test">{children}</MantineProvider>
    ),
  });
}
```

It's usually more convenient to export all `@testing-library/*` functions that you're planning to use
from a `./testing-utils/index.ts` file:

```tsx
import userEvent from '@testing-library/user-event';

export * from '@testing-library/react';
export { render } from './render';
export { userEvent };
```

Then you should import all testing utilities from `./testing-utils` instead of `@testing-library/react`:

```tsx
import { render, screen } from '../test-utils';
import { Welcome } from './Welcome';

describe('Welcome component', () => {
  it('has correct Next.js theming section link', () => {
    render(<Welcome />);
    expect(screen.getByText('this guide')).toHaveAttribute(
      'href',
      'https://mantine.dev/guides/next/'
    );
  });
});
```

## Mock Web APIs

Most Mantine components depend on browser APIs like `window.matchMedia` or `ResizeObserver`.
These APIs aren't available in the `jest-environment-jsdom` environment and you'll need to mock them in your tests.

Create a `jest.setup.js` file in your project root and add the following code to it:

```tsx
import '@testing-library/jest-dom';

const { getComputedStyle } = window;
window.getComputedStyle = (elt) => getComputedStyle(elt);
window.HTMLElement.prototype.scrollIntoView = () => {};

Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: jest.fn().mockImplementation((query) => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(),
    removeListener: jest.fn(),
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })),
});

if (!document.fonts) {
  Object.defineProperty(document, 'fonts', {
    writable: true,
    value: { addEventListener: jest.fn(), removeEventListener: jest.fn() },
  });
}

class ResizeObserver {
  observe() {}
  unobserve() {}
  disconnect() {}
}

window.ResizeObserver = ResizeObserver;
```

Then add it as a setup file in your `jest.config.js`:

```js
const config = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  // ... rest of your config
};
```

## Framework specific setup

Jest setup for different frameworks may vary and usually changes over time.
To learn how to set up Jest for your framework, either check the [Jest](https://jestjs.io/docs/getting-started)
and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) documentation
or check one of the premade [templates](/getting-started). Most of the templates include Jest setup, and
you can use them as a reference.

## Testing examples

You can find testing examples in Mantine Help Center:

- [How can I test Modal/Drawer/Popover components?](https://help.mantine.dev/q/portals-testing)
- [How can I test Select/MultiSelect components?](https://help.mantine.dev/q/combobox-testing)

---

## File: apps/mantine.dev/src/pages/guides/polymorphic.mdx

import { GuidesDemos } from '@docs/demos';
import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.Polymorphic);

# Polymorphic components

## What is a polymorphic component

A polymorphic component is a component whose root element can be changed with the `component` prop.
All polymorphic components have a default element that's used when the `component` prop is not provided.
For example, the [Button](/core/button) component's default element is `button` and
it can be changed to `a` or any other element or component:

<Demo data={GuidesDemos.polymorphic} />

## renderRoot prop

`renderRoot` is an alternative to the `component` prop, which accepts a function that should return
a React element. It is useful in cases when `component` prop cannot be used, for example,
when the component that you want to pass to the `component` is generic
(accepts type or infers it from props, for example `<Link<'/'> />`).

Example of using `renderRoot` prop, the result is the same as in the previous demo:

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

function Demo() {
  return (
     (
        <a href="https://mantine.dev/" target="_blank" {...props} />
      )}
    >
      Mantine website
    
  );
}
```

**!important** It's required to spread the `props` argument into the root element. Otherwise,
there will be no styles and the component might not be accessible.

## Polymorphic components as other React components

You can pass any other React component to the `component` prop.
For example, you can pass the `Link` component from `react-router-dom`:

```tsx
import { Link } from 'react-router-dom';
import { Button } from '@mantine/core';

function Demo() {
  return (
    
      React router link
    
  );
}
```

## Polymorphic components as Next.js Link

The Next.js link doesn't work in the same way as other similar components in all Next.js versions.

With Next.js 12 and below:

```tsx
import Link from 'next/link';
import { Button } from '@mantine/core';

function Demo() {
  return (
    <Link href="/hello" passHref>
      Next link button
    </Link>
  );
}
```

With Next.js 13 and above:

```tsx
import Link from 'next/link';
import { Button } from '@mantine/core';

function Demo() {
  return (
    
      Next link button
    
  );
}
```

## Polymorphic components with generic components

You cannot pass generic components to the `component` prop because it's not possible to infer generic types
from the component prop. For example, you cannot pass [typed Next.js Link](https://nextjs.org/docs/app/building-your-application/configuring/typescript#statically-typed-links)
to the `component` prop because it's not possible to infer the `href` type from the component prop. The component itself
will work correctly, but you'll have a TypeScript error.

To make generic components work with polymorphic components, use the `renderRoot` prop instead of `component`:

```tsx
import Link from 'next/link';
import { Button } from '@mantine/core';

function Demo() {
  return (
     <Link href="/hello" {...props} />}>
      Typed Next link button
    
  );
}
```

## Polymorphic components with react-router NavLink

The [react-router-dom](https://reactrouter.com/en/main) [NavLink](https://reactrouter.com/en/main/components/nav-link) component's
`className` prop accepts a function based on which you can add an active class to the link. This feature is
incompatible with Mantine's `component` prop, but you can use the `renderRoot` prop instead:

```tsx
import cx from 'clsx';
import { NavLink } from 'react-router-dom';
import { Button } from '@mantine/core';

function Demo() {
  return (
     (
        <NavLink
          className={({ isActive }) =>
            cx(className, { 'active-class': isActive })
          }
          {...others}
        />
      )}
    >
      React router NavLink
    
  );
}
```

## Wrapping polymorphic components

Non-polymorphic components include `React.ComponentProps<'x'>` as part of their props type,
where `x` is the root element of the component. For example, the [Container](/core/container) component
is not polymorphic – its root element is always `div`, so its props type includes `React.ComponentProps<'div'>`.

Polymorphic components don't include `React.ComponentProps<'x'>` as part of their props type
because their root element can be changed, and thus the props type can be inferred only after the component was rendered.

Example of creating a non-polymorphic wrapper component for Mantine polymorphic component:

<Demo data={GuidesDemos.staticPolymorphic} />

Example of creating a polymorphic wrapper component for Mantine polymorphic component:

<Demo data={GuidesDemos.createPolymorphic} />

## Dynamic component prop

You can use a dynamic value in the `component` prop, but in this case, you need to either provide types manually
or disable type checking by passing `any` as a type argument to the polymorphic component:

```tsx
import { Box } from '@mantine/core';

function KeepTypes() {
  return (
    
      component={(Math.random() > 0.5 ? 'input' : 'div') as any}
    />
  );
}

function NukeTypes() {
  return (
     component={Math.random() > 0.5 ? 'input' : 'div'} />
  );
}
```

## Create your own polymorphic components

Use the `polymorphic` function and [Box](/core/box) component to create new polymorphic components:

<Demo data={GuidesDemos.newPolymorphic} />

## Make Mantine component polymorphic

Polymorphic components have a performance overhead for tsserver (no impact on runtime performance),
because of that, not all Mantine components have polymorphic types, but all components still
accept the `component` prop – the root element can be changed.

To make a Mantine component polymorphic, use the `polymorphic` function the same way
as in the previous example:

```tsx
import { polymorphic, Group, GroupProps } from '@mantine/core';

const PolymorphicGroup = polymorphic<'button', GroupProps>(Group);

function Demo() {
  return (
    
  );
}
```