# Mantine UI Library - Complete Documentation
This file contains comprehensive documentation for the Mantine UI library including:
- Complete component documentation with all usage examples
- Full demo code for every example shown in the documentation
- Complete props tables with types and descriptions for all components
- Styles API documentation showing all available selectors
- FAQ and troubleshooting guides
All code examples use production npm package imports (e.g., @mantine/core, @mantine/hooks)
================================================================================
## CORE COMPONENTS AND FEATURES
Primary Package: @mantine/core
### Accordion
Package: @mantine/core
Import: import { Accordion } from '@mantine/core';
Description: Divide content into collapsible sections
## Usage
Accordion allows users to expand and collapse sections of content.
It helps manage large amounts of information in a limited space
by showing only section headers initially and revealing content upon interaction.
Accordion is commonly used for:
* FAQ sections: displaying questions as headers with answers revealed when clicked
* Forms: organizing long forms into sections, for example, personal info, shipping, and payment
* Menus: nested navigation in sidebars or mobile views
```tsx
// Demo.tsx
import { Accordion } from '@mantine/core';
import { data } from './data';
function Demo() {
const items = data.map((item) => (
{item.value}{item.description}
));
return (
{items}
);
}
// data.ts
export const data = [
{
emoji: 'π',
value: 'Apples',
description:
'Crisp and refreshing fruit. Apples are known for their versatility and nutritional benefits. They come in a variety of flavors and are great for snacking, baking, or adding to salads.',
},
{
emoji: 'π',
value: 'Bananas',
description:
'Naturally sweet and potassium-rich fruit. Bananas are a popular choice for their energy-boosting properties and can be enjoyed as a quick snack, added to smoothies, or used in baking.',
},
{
emoji: 'π₯¦',
value: 'Broccoli',
description:
'Nutrient-packed green vegetable. Broccoli is packed with vitamins, minerals, and fiber. It has a distinct flavor and can be enjoyed steamed, roasted, or added to stir-fries.',
},
];
```
## order prop
The `order` prop (used in all demos on this page) sets the heading level for the `Accordion.Control` root element.
According to [WAI-ARIA recommendations](https://www.w3.org/TR/wai-aria-practices-1.1/examples/accordion/accordion.html),
it is required to use `h2`-`h6` heading levels to fit correctly within the outline of the page.
All examples on this page use `order={3}`, which means that all `button` elements of
`Accordion.Control` are wrapped with an `h3` tag (`h2` tags are used for the documentation sections).
The `order` prop is not enforced by the library but is required if your application
must meet accessibility standards.
## Change chevron
Use the `chevron` prop to change the chevron icon. When `chevron` is set,
the `chevronIconSize` prop is ignored. To remove the chevron icon, use `chevron={null}`.
To customize chevron styles, use [Styles API](https://alpha.mantine.dev/llms/styles-styles-api.md) with the
[data-rotate](https://alpha.mantine.dev/llms/styles-data-attributes.md) attribute. This attribute is set when the item
is opened if the `disableChevronRotation` prop is not set.
Example of a custom chevron icon with rotation styles:
```tsx
// Demo.module.css
.chevron {
&[data-rotate] {
transform: rotate(45deg);
}
}
.icon {
width: 16px;
height: 16px;
}
// data.ts
export const data = [
{
emoji: 'π',
value: 'Apples',
description:
'Crisp and refreshing fruit. Apples are known for their versatility and nutritional benefits. They come in a variety of flavors and are great for snacking, baking, or adding to salads.',
},
{
emoji: 'π',
value: 'Bananas',
description:
'Naturally sweet and potassium-rich fruit. Bananas are a popular choice for their energy-boosting properties and can be enjoyed as a quick snack, added to smoothies, or used in baking.',
},
{
emoji: 'π₯¦',
value: 'Broccoli',
description:
'Nutrient-packed green vegetable. Broccoli is packed with vitamins, minerals, and fiber. It has a distinct flavor and can be enjoyed steamed, roasted, or added to stir-fries.',
},
];
```
## Custom control label
You can use any React node as a label for `Accordion.Control` component.
When you use nested elements in `Accordion.Control`, it is recommended to
set `aria-label` attribute to make the control accessible for screen readers.
```tsx
import { Flex, Avatar, Text, Accordion } from '@mantine/core';
const charactersList = [
{
id: 'bender',
image: 'https://img.icons8.com/clouds/256/000000/futurama-bender.png',
label: 'Bender Bending RodrΓguez',
description: 'Fascinated with cooking, though has no sense of taste',
content: "Bender Bending RodrΓguez, (born September 4, 2996), designated Bending Unit 22, and commonly known as Bender, is a bending unit created by a division of MomCorp in Tijuana, Mexico, and his serial number is 2716057. His mugshot id number is 01473. He is Fry's best friend.",
},
{
id: 'carol',
image: 'https://img.icons8.com/clouds/256/000000/futurama-mom.png',
label: 'Carol Miller',
description: 'One of the richest people on Earth',
content: "Carol Miller (born January 30, 2880), better known as Mom, is the evil chief executive officer and shareholder of 99.7% of Momcorp, one of the largest industrial conglomerates in the universe and the source of most of Earth's robots. She is also one of the main antagonists of the Futurama series.",
},
{
id: 'homer',
image: 'https://img.icons8.com/clouds/256/000000/homer-simpson.png',
label: 'Homer Simpson',
description: 'Overweight, lazy, and often ignorant',
content: 'Homer Jay Simpson (born May 12) is the main protagonist and one of the five main characters of The Simpsons series(or show). He is the spouse of Marge Simpson and father of Bart, Lisa and Maggie Simpson.',
},
];
interface AccordionLabelProps {
label: string;
image: string;
description: string;
}
function AccordionLabel({ label, image, description }: AccordionLabelProps) {
return (
{label}
{description}
);
}
function Demo() {
const items = charactersList.map((item) => (
{item.content}
));
return (
{items}
);
}
```
## With icons
Use the `icon` prop to display any element in the left section of the `Accordion.Control`:
```tsx
import { ImageIcon, PrinterIcon, CameraIcon } from '@phosphor-icons/react';
import { Accordion } from '@mantine/core';
function Demo() {
return (
}
>
Recent photos
Content}
>
Print photos
Content}
>
CameraIcon settings
Content
);
}
```
## Change transition
To change transition duration, set `transitionDuration` prop:
To disable transitions, set `transitionDuration` to 0:
## Default opened items
For `multiple={false}`, set `defaultValue` as string:
```tsx
import { Accordion } from '@mantine/core';
function Demo() {
// Second item will be opened by default
return (
{/* item-1 */}{/* item-2 */}
);
}
```
For `multiple={true}`, set `defaultValue` as an array of strings:
```tsx
import { Accordion } from '@mantine/core';
function Demo() {
// Both items are opened by default
return (
{/* item-1 */}{/* item-2 */}
);
}
```
## Control opened state
For `multiple={false}`, set `value` as string:
```tsx
import { useState } from 'react';
import { Accordion } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(null);
return (
{/* item-1 */}{/* item-2 */}
);
}
```
For `multiple={true}`, set `value` as an array of strings:
```tsx
import { useState } from 'react';
import { Accordion } from '@mantine/core';
function Demo() {
const [value, setValue] = useState([]);
return (
{/* item-1 */}{/* item-2 */}
);
}
```
## Compose controls
Putting a button or link inside `Accordion.Control` is a common mistake when
using Accordion. The `Accordion.Control` root element is a `button`. Putting interactive
elements inside other interactive elements is forbidden β you will receive a DOM
validation error from React if you try to implement the following component:
```tsx
import { Accordion } from '@mantine/core';
// β Incorrect usage: do not do this
function Demo() {
return (
Control 1Panel 1
);
}
```
Instead of putting interactive elements inside the `Accordion.Control`, render them
next to it. For example, you can add an [ActionIcon](https://alpha.mantine.dev/llms/core-action-icon.md) or [Menu](https://alpha.mantine.dev/llms/core-menu.md)
to the right side of the original control. If you need to display an interactive element
over the `Accordion.Control`, use `position: absolute` instead.
```tsx
import { Accordion, ActionIcon, AccordionControlProps, Center } from '@mantine/core';
import { DotsThreeIcon } from '@phosphor-icons/react';
function AccordionControl(props: AccordionControlProps) {
return (
);
}
function Demo() {
return (
Control 1Panel 1Control 2Panel 2Control 3Panel 3
);
}
```
## Disabled items
Set the `disabled` prop on the `Accordion.Control` component to disable it.
When you disable items, users cannot activate them with the mouse or keyboard,
and arrow key navigation will skip them:
```tsx
// Demo.tsx
import { Accordion } from '@mantine/core';
import { data } from './data';
function Demo() {
const items = data.map((item) => (
{item.value}
{item.description}
));
return (
{items}
);
}
// data.ts
export const data = [
{
emoji: 'π',
value: 'Apples',
description:
'Crisp and refreshing fruit. Apples are known for their versatility and nutritional benefits. They come in a variety of flavors and are great for snacking, baking, or adding to salads.',
},
{
emoji: 'π',
value: 'Bananas',
description:
'Naturally sweet and potassium-rich fruit. Bananas are a popular choice for their energy-boosting properties and can be enjoyed as a quick snack, added to smoothies, or used in baking.',
},
{
emoji: 'π₯¦',
value: 'Broccoli',
description:
'Nutrient-packed green vegetable. Broccoli is packed with vitamins, minerals, and fiber. It has a distinct flavor and can be enjoyed steamed, roasted, or added to stir-fries.',
},
];
```
## TypeScript
The `AccordionProps` type exported from `@mantine/core` is a generic that accepts a boolean type
describing the `multiple` state:
```tsx
import type { AccordionProps } from '@mantine/core';
type MultipleAccordionProps = AccordionProps;
type DefaultAccordionProps = AccordionProps;
```
## Accessibility
The Accordion component implements the [WAI-ARIA accessibility pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/).
## Keyboard interactions
#### Props
**Accordion props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| chevron | React.ReactNode | - | Custom chevron icon |
| chevronIconSize | string \| number | - | Size of the default chevron icon. Ignored when `chevron` prop is set. Use `chevronSize` instead when using custom chevron. |
| chevronPosition | "left" \| "right" | - | Position of the chevron relative to the item label |
| chevronSize | string \| number | - | Size of the chevron icon container |
| defaultValue | string \| string[] \| null | - | Uncontrolled component default value |
| disableChevronRotation | boolean | - | If set, chevron rotation is disabled |
| keepMounted | boolean | - | If set to `false`, panels are unmounted when collapsed. By default, panels stay mounted when collapsed. |
| loop | boolean | - | If set, arrow keys loop through items (first to last and last to first) |
| multiple | boolean | - | If set, multiple items can be opened at the same time |
| onChange | (value: AccordionValue) => void | - | Called when value changes, payload type depends on `multiple` prop |
| order | 2 \| 3 \| 4 \| 5 \| 6 | - | Sets heading level (h2-h6) for `Accordion.Control` elements to meet WAI-ARIA requirements. Has no visual effect. |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius. Numbers are converted to rem. |
| transitionDuration | number | - | Transition duration in ms |
| value | string \| string[] \| null | - | Controlled component value |
**Accordion.Item props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| value | string | required | Value that is used to manage the accordion state |
**Accordion.Control props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| chevron | React.ReactNode | - | Custom chevron icon |
| children | React.ReactNode | - | Control label |
| disabled | boolean | - | Sets `disabled` attribute, prevents interactions |
| icon | React.ReactNode | - | Icon displayed next to the label |
#### Styles API
Accordion component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Accordion selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Accordion-root | Root element |
| item | .mantine-Accordion-item | `Accordion.Item` root element |
| control | .mantine-Accordion-control | `Accordion.Control` root element |
| chevron | .mantine-Accordion-chevron | `Accordion.Control` chevron container element |
| label | .mantine-Accordion-label | `Accordion.Control` label |
| icon | .mantine-Accordion-icon | `Accordion.Control` icon |
| itemTitle | .mantine-Accordion-itemTitle | `Accordion.Control` title (h2-h6) tag |
| panel | .mantine-Accordion-panel | `Accordion.Panel` root element |
| content | .mantine-Accordion-content | Wrapper element of `Accordion.Panel` `children` |
**Accordion CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --accordion-chevron-size | Controls chevron container element `width` and `min-width` |
| root | --accordion-radius | Controls `border-radius` in various elements, depending on variant |
| root | --accordion-transition-duration | Controls all animations `transition-duration` |
--------------------------------------------------------------------------------
### ActionIcon
Package: @mantine/core
Import: import { ActionIcon } from '@mantine/core';
Description: Icon button
## Usage
```tsx
import { ActionIcon } from '@mantine/core';
import { SlidersHorizontalIcon } from '@phosphor-icons/react';
function Demo() {
return (
);
}
```
```tsx
import { ActionIcon } from '@mantine/core';
import { HeartIcon } from '@phosphor-icons/react';
function Demo() {
return (
);
}
```
## Size
You can use any valid CSS value in the `size` prop, which is used to set the `width`, `min-width`, `min-height` and `height`
properties. Note that the `size` prop does not control the child [icon](https://alpha.mantine.dev/llms/guides-icons.md) size β you need to
set it manually on the icon component. When `size` is a number, the value is treated as `px` units and
converted to [rem](https://alpha.mantine.dev/llms/styles-rem.md) units.
```tsx
import { ActionIcon } from '@mantine/core';
import { HeartIcon } from '@phosphor-icons/react';
function Demo() {
return (
);
}
```
If you want `ActionIcon` to have the same size as Mantine inputs, use the `size="input-sm"` prop:
```tsx
import { ActionIcon, Group, TextInput } from '@mantine/core';
function Demo() {
return (
SM
);
}
```
## Disabled state
To make `ActionIcon` disabled, set the `disabled` prop. This will prevent any interactions with the button
and add disabled styles. If you want the button to just look disabled but still be interactive,
set the `data-disabled` prop instead. Note that disabled styles are the same for all variants.
```tsx
import { ActionIcon, Group } from '@mantine/core';
import { HeartIcon } from '@phosphor-icons/react';
function Demo() {
return (
);
}
```
## Disabled state when ActionIcon is link
The `` element does not support the `disabled` attribute. To make `ActionIcon` disabled when it is
rendered as a link, set the `data-disabled` attribute instead and prevent default behavior in the
`onClick` event handler.
```tsx
import { ActionIcon } from '@mantine/core';
import { ArrowSquareOutIcon } from '@phosphor-icons/react';
function Demo() {
return (
event.preventDefault()}
>
);
}
```
## Customize disabled styles
To customize disabled styles, it is recommended to use both `&:disabled` and `&[data-disabled]`
selectors:
* `&:disabled` is used to style the button when the `disabled` prop is set and
also when the button is disabled by the parent component (for example, when the `disabled` prop is set on a
`` element which contains `ActionIcon`).
* `&[data-disabled]` is used to style the button when it is not actually disabled but should look like
it is (for example, `data-disabled` should be used if you need to use [Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md) with a disabled `ActionIcon`
or when `ActionIcon` is used as a link)
```tsx
// Demo.module.css
.button {
&:disabled,
&[data-disabled] {
border-color: light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
background-color: transparent;
}
}
// Demo.tsx
import { ActionIcon } from '@mantine/core';
import { HeartIcon } from '@phosphor-icons/react';
import classes from './Demo.module.css';
function Demo() {
return (
);
}
```
## Disabled button with Tooltip
The `onMouseLeave` event [is not triggered](https://github.com/facebook/react/issues/18753) when `ActionIcon` is disabled, so if you need to use
[Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md) with a disabled `ActionIcon`, you need to set the `data-disabled` prop on `ActionIcon`
instead of `disabled`. Note that it is also required to change the `onClick` event handler to
`(event) => event.preventDefault()` as `ActionIcon` is not actually disabled and will still trigger
the `onClick` event.
```tsx
import { ActionIcon, Tooltip } from '@mantine/core';
import { HeartIcon } from '@phosphor-icons/react';
function Demo() {
return (
event.preventDefault()}
>
);
}
```
## Loading state
When the `loading` prop is set, `ActionIcon` will be disabled and a [Loader](https://alpha.mantine.dev/llms/core-loader.md) with overlay will be rendered
in the center of the button. The [Loader](https://alpha.mantine.dev/llms/core-loader.md) color depends on the `ActionIcon` variant.
```tsx
import { ActionIcon, Group, Switch } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { HeartIcon } from '@phosphor-icons/react';
function Demo() {
const [loading, { toggle }] = useDisclosure();
return (
<>
>
);
}
```
## Loader props
You can customize the [Loader](https://alpha.mantine.dev/llms/core-loader.md) with the `loaderProps` prop, which accepts all props that the
[Loader](https://alpha.mantine.dev/llms/core-loader.md) component has:
```tsx
import { ActionIcon } from '@mantine/core';
function Demo() {
return ;
}
```
## Add custom variants
To add new `ActionIcon` variants, use the [data-variant](https://alpha.mantine.dev/llms/styles-variants-sizes.md) attribute.
Usually new variants are added to the [theme](https://alpha.mantine.dev/llms/theming-theme-object.md). This way they are
available in all `ActionIcon` components in your application.
```tsx
// Demo.tsx
import { Group, ActionIcon, MantineProvider, createTheme } from '@mantine/core';
import { HeartIcon } from '@phosphor-icons/react';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
ActionIcon: ActionIcon.extend({
classNames: classes,
}),
},
});
function Demo() {
return (
);
}
// Demo.module.css
.root {
&[data-variant='danger'] {
background-color: var(--mantine-color-red-9);
color: var(--mantine-color-red-0);
}
&[data-variant='primary'] {
background: linear-gradient(45deg, #4b6cb7 10%, #253b67 90%);
color: var(--mantine-color-white);
}
}
```
## Customize variants colors
You can customize colors for `ActionIcon` and other components variants by adding
[variantColorResolver](https://alpha.mantine.dev/llms/theming-colors.md#colors-variant-resolver) to your theme.
```tsx
import { ImageIcon, FingerprintIcon, WarningIcon } from '@phosphor-icons/react';
import {
ActionIcon,
Group,
MantineProvider,
defaultVariantColorsResolver,
VariantColorsResolver,
parseThemeColor,
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)',
hoverColor: '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: `1px 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 (
);
}
```
```tsx
import { FingerprintIcon } from '@phosphor-icons/react';
import { ActionIcon, Group } from '@mantine/core';
function Demo() {
return (
);
}
```
## Add custom sizes
`ActionIcon` sizes are defined by `--ai-size-{x}` CSS variables. The easiest way to add new sizes is to
define additional `--ai-size-{x}` variables on the `root` element:
```tsx
// Demo.tsx
import { ActionIcon, createTheme, Group, MantineThemeProvider } from '@mantine/core';
import { HeartIcon } from '@phosphor-icons/react';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
ActionIcon: ActionIcon.extend({
classNames: classes,
}),
},
});
function Demo() {
return (
);
}
// Demo.module.css
.root {
--ai-size-xxs: 16px;
--ai-size-xxl: 50px;
}
```
## ActionIcon.Group
```tsx
import { ActionIcon } from '@mantine/core';
import { ImageIcon, GearSixIcon, HeartIcon } from '@phosphor-icons/react';
function Demo() {
return (
);
}
```
Note that you must not wrap child `ActionIcon` components with any additional elements:
```tsx
import { ActionIcon } from '@mantine/core';
// Will not work correctly
function Demo() {
return (
This will not work
ActionIcons will have incorrect borders
);
}
```
## ActionIcon.GroupSection
Use the `ActionIcon.GroupSection` component to render sections that are not `ActionIcon` inside `ActionIcon.Group`:
```tsx
import { CaretDownIcon, CaretUpIcon } from '@phosphor-icons/react';
import { ActionIcon } from '@mantine/core';
import { useCounter } from '@mantine/hooks';
function Demo() {
const [value, { increment, decrement }] = useCounter(135, { min: 0 });
return (
{value}
);
}
```
## Accessibility
To make `ActionIcon` accessible for screen readers, you need to either set `aria-label` or
use the [VisuallyHidden](https://alpha.mantine.dev/llms/core-visually-hidden.md) component:
```tsx
import { HeartIcon } from '@phosphor-icons/react';
import { ActionIcon, VisuallyHidden } from '@mantine/core';
function Demo() {
return (
<>
Like post
>
);
}
```
#### Props
**ActionIcon props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts text color based on background color for `filled` variant |
| children | React.ReactNode | - | Icon element |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color. |
| disabled | boolean | - | Sets `disabled` attribute, prevents interactions |
| gradient | MantineGradient | - | Gradient values used with `variant="gradient"`. |
| loaderProps | LoaderProps | - | Props passed down to the `Loader` component. Ignored when `loading` prop is not set. |
| loading | boolean | - | If set, `Loader` component is displayed instead of the `children` |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius. Numbers are converted to rem. |
| size | number \| MantineSize \| (string & {}) \| "input-xs" \| "input-sm" \| "input-md" \| "input-lg" \| "input-xl" | - | Controls width and height of the button. Numbers are converted to rem. |
**ActionIcon.Group props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| borderWidth | string \| number | - | `border-width` of the child components. |
| children | React.ReactNode | - | `ActionIcon` and `ActionIcon.GroupSection` components only |
| orientation | "horizontal" \| "vertical" | - | Group orientation |
#### Styles API
ActionIcon component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**ActionIcon selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-ActionIcon-root | Root element |
| loader | .mantine-ActionIcon-loader | `Loader` component, rendered inside root element when `loading` prop is set |
| icon | .mantine-ActionIcon-icon | Inner icon wrapper |
**ActionIcon CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --ai-bg | Controls `background` |
| root | --ai-hover | Controls `background` when hovered |
| root | --ai-bd | Controls `border` |
| root | --ai-color | Controls icon `color` |
| root | --ai-hover-color | Controls icon `color` when hovered |
| root | --ai-radius | Controls `border-radius` |
| root | --ai-size | Controls `width`, `height`, `min-width` and `min-height` styles |
**ActionIcon data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-disabled | `disabled` prop is set | - |
**ActionIcon.Group selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| group | .mantine-ActionIconGroup-group | Root element |
**ActionIcon.Group CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
**ActionIcon.Group data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| group | data-orientation | - | Value of `orientation` prop |
--------------------------------------------------------------------------------
### Affix
Package: @mantine/core
Import: import { Affix } from '@mantine/core';
Description: Renders children inside portal at fixed position
## Usage
`Affix` renders a div element with a fixed position inside the [Portal](https://alpha.mantine.dev/llms/core-portal.md) component.
Use it to display elements fixed at any position on the screen, for example, scroll to top button:
```tsx
import { ArrowUpIcon } from '@phosphor-icons/react';
import { useWindowScroll } from '@mantine/hooks';
import { Affix, Button, Text, Transition } from '@mantine/core';
function Demo() {
const [scroll, scrollTo] = useWindowScroll();
return (
<>
Affix is located at the bottom of the screen, scroll to see it 0}>
{(transitionStyles) => (
}
style={transitionStyles}
onClick={() => scrollTo({ y: 0 })}
>
Scroll to top
)}
>
);
}
```
#### Props
**Affix props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| portalProps | BasePortalProps | - | Props passed down to the `Portal` component. Ignored when `withinPortal` is `false`. |
| position | AffixPosition | - | Affix position on screen |
| withinPortal | boolean | - | Determines whether the component is rendered within `Portal` |
| zIndex | React.CSSProperties["zIndex"] | - | Root element `z-index` property |
#### Styles API
Affix component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Affix selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Affix-root | Root element |
**Affix CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --affix-z-index | Controls `z-index` property |
| root | --affix-top | Controls `top` property |
| root | --affix-bottom | Controls `bottom` property |
| root | --affix-left | Controls `left` property |
| root | --affix-right | Controls `right` property |
--------------------------------------------------------------------------------
### Alert
Package: @mantine/core
Import: import { Alert } from '@mantine/core';
Description: Attract user attention with important static message
## Accessibility
* Root element role set to `alert`
* `aria-describedby` set to body element id, `aria-labelledby` set to title element id if `title` is provided
* Set `closeButtonLabel` prop to make close button accessible
```tsx
import { Alert } from '@mantine/core';
function Invalid() {
// -> not ok
return ;
}
function Valid() {
// -> ok
return ;
}
function AlsoValid() {
// -> ok, without close button, closeButtonLabel is not needed
return ;
}
```
#### Props
**Alert props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts text color based on background color for `filled` variant |
| closeButtonLabel | string | - | Close button `aria-label` |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
| icon | React.ReactNode | - | Icon displayed next to the title |
| onClose | () => void | - | Called when the close button is clicked |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius |
| title | React.ReactNode | - | Alert title |
| withCloseButton | boolean | - | Determines whether close button should be displayed |
#### Styles API
Alert component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Alert selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Alert-root | Root element |
| wrapper | .mantine-Alert-wrapper | Wrapper around `body` and `icon` |
| body | .mantine-Alert-body | Body element, contains `title` and `message` |
| title | .mantine-Alert-title | Title element, contains `label` and `icon` |
| label | .mantine-Alert-label | Title label |
| message | .mantine-Alert-message | Alert message |
| icon | .mantine-Alert-icon | Icon element |
| closeButton | .mantine-Alert-closeButton | Close button |
**Alert CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --alert-bd | Controls `border` |
| root | --alert-bg | Controls `background` |
| root | --alert-color | Controls `color` |
| root | --alert-radius | Controls `border-radius` |
**Alert data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| title | data-with-close-button | `withCloseButton` prop is set | - |
--------------------------------------------------------------------------------
### AlphaSlider
Package: @mantine/core
Import: import { AlphaSlider } from '@mantine/core';
Description: Slider component for selecting alpha channel in color pickers (0 β 1)
## Usage
Use `AlphaSlider` component to allow users to select alpha (opacity) value of a color.
It accepts values from `0` to `1`. `AlphaSlider` is a part of [ColorPicker](https://alpha.mantine.dev/llms/core-color-picker.md) component,
but can also be used separately.
```tsx
import { useState } from 'react';
import { AlphaSlider, Text } from '@mantine/core';
function Demo() {
const [value, onChange] = useState(0.55);
return (
<>
Alpha value: {value}
>
);
}
```
#### Props
**AlphaSlider props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| color | string | required | - |
| focusable | boolean | - | If set, slider thumb can be focused |
| onChange | (value: number) => void | - | Called when value changes |
| onChangeEnd | (value: number) => void | - | Called when user stops dragging the slider or uses keyboard to change value |
| onScrubEnd | () => void | - | Called when user stops dragging the slider |
| onScrubStart | () => void | - | Called when user starts dragging the slider |
| size | MantineSize | - | Slider size |
| value | number | required | Controlled component value |
--------------------------------------------------------------------------------
### Anchor
Package: @mantine/core
Import: import { Anchor } from '@mantine/core';
Description: Display link with theme styles
## Usage
```tsx
import { Anchor } from '@mantine/core';
function Demo() {
return (
Anchor component
);
}
```
## Underline
Use the `underline` prop to configure the `text-decoration` property. It accepts the following values:
* `always` - link is always underlined
* `hover` - link is underlined on hover
* `never` - link is never underlined
* `not-hover` - link is underlined when not hovered
```tsx
import { Anchor, Group } from '@mantine/core';
function Demo() {
return (
Underline always
Underline hover
Underline never
Underline not-hover
);
}
```
You can also configure the `underline` prop for all `Anchor` components with [default props](https://alpha.mantine.dev/llms/theming-default-props.md):
```tsx
import { Anchor, createTheme, MantineProvider } from '@mantine/core';
const theme = createTheme({
components: {
Anchor: Anchor.extend({
defaultProps: {
underline: 'always',
},
}),
},
});
function Demo() {
return (
{/* Your app here */}
);
}
```
## Text props
The `Anchor` component supports all [Text](https://alpha.mantine.dev/llms/core-text.md) component props.
For example, you can use the gradient variant:
```tsx
import { Anchor } from '@mantine/core';
function Demo() {
return (
A link with pink to yellow gradient
);
}
```
#### Props
**Anchor props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| gradient | MantineGradient | - | Gradient configuration, ignored when `variant` is not `gradient` |
| inherit | boolean | - | Determines whether font properties should be inherited from the parent |
| inline | boolean | - | Sets `line-height` to 1 for centering |
| lineClamp | number | - | Number of lines after which Text will be truncated |
| size | MantineSize \| (string & {}) | - | Controls `font-size` and `line-height` |
| truncate | TextTruncate | - | Side on which Text must be truncated, if `true`, text is truncated from the start |
| underline | "always" \| "hover" \| "not-hover" \| "never" | - | Defines when `text-decoration: underline` styles are applied. |
--------------------------------------------------------------------------------
### AngleSlider
Package: @mantine/core
Import: import { AngleSlider } from '@mantine/core';
Description: Pick angle value between 0 and 360
## Usage
Use the `AngleSlider` component to pick an angle value between 0 and 360:
```tsx
import { AngleSlider } from '@mantine/core';
function Demo() {
return ;
}
```
## Controlled
The `AngleSlider` value is a number between 0 and 360.
```tsx
import { useState } from 'react';
import { AngleSlider } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(180);
return ;
}
```
## AngleSlider with uncontrolled forms
`AngleSlider` can be used with uncontrolled forms.
Set the `name` attribute to include slider value in `FormData` object on form submission.
To control initial value in uncontrolled forms, use `defaultValue` prop.
Props for usage with uncontrolled forms:
* `name` β name attribute passed to the hidden input
* `hiddenInputProps` β additional props passed to the hidden input
Example of uncontrolled `AngleSlider` with `FormData`:
```tsx
import { AngleSlider } from '@mantine/core';
export function WithFormData() {
return (
);
}
```
## formatLabel
Use the `formatLabel` prop to change the angle label format.
It accepts a function that takes the angle value and returns a React node:
```tsx
import { AngleSlider } from '@mantine/core';
function Demo() {
return `${value}Β°`} />;
}
```
## Marks
Set the `marks` prop to display marks on the slider.
A mark is an object with a value (required, number between 0 and 360) and label (optional, React node).
To restrict selection to marks only, set the `restrictToMarks` prop:
```tsx
import { AngleSlider, Group } from '@mantine/core';
function Demo() {
return (
`${value}Β°`}
size={100}
restrictToMarks
marks={[
{ value: 0 },
{ value: 45 },
{ value: 90 },
{ value: 135 },
{ value: 180 },
{ value: 225 },
{ value: 270 },
{ value: 315 },
]}
/>
`${value}Β°`}
size={100}
marks={[
{ value: 0, label: '0Β°' },
{ value: 45, label: '45Β°' },
{ value: 90, label: '90Β°' },
{ value: 135, label: '135Β°' },
{ value: 180, label: '180Β°' },
{ value: 225, label: '225Β°' },
{ value: 270, label: '270Β°' },
{ value: 315, label: '315Β°' },
]}
/>
);
}
```
## onChangeEnd
The `onChangeEnd` callback fires when the user stops dragging the slider or changes its value with the keyboard.
Use it as a debounced callback to prevent frequent updates.
```tsx
import { useState } from 'react';
import { AngleSlider, Text } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(0);
const [endValue, setEndValue] = useState(0);
return (
<>
Current value: {value}End value: {endValue}
>
);
}
```
## disabled
The `disabled` prop disables the component and prevents user interaction:
```tsx
import { AngleSlider } from '@mantine/core';
function Demo() {
return ;
}
```
## Accessibility
To make the component accessible for screen readers, set the `aria-label` prop:
```tsx
import { AngleSlider } from '@mantine/core';
function Demo() {
return ;
}
```
Keyboard interactions when the component is focused:
## Based on use-radial-move
`AngleSlider` is based on the [use-radial-move](https://alpha.mantine.dev/llms/hooks-use-radial-move.md) hook.
You can build a custom radial slider using this hook if you need more control over the component's behavior.
```tsx
// Demo.tsx
import { useState } from 'react';
import { Box } from '@mantine/core';
import { useRadialMove } from '@mantine/hooks';
import classes from './Demo.module.css';
function Demo() {
const [value, setValue] = useState(115);
const { ref } = useRadialMove(setValue);
return (
{value}Β°
);
}
// Demo.module.css
.root {
position: relative;
width: 160px;
height: 160px;
border-radius: 160px;
display: flex;
align-items: center;
justify-content: center;
--empty-color: light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-6));
--filled-color: light-dark(var(--mantine-color-blue-6), var(--mantine-color-blue-8));
background-image: conic-gradient(
var(--filled-color) 0deg,
var(--filled-color) var(--angle, 0deg),
var(--empty-color) var(--angle, 0deg)
);
}
.value {
background-color: var(--mantine-color-body);
width: 132px;
height: 132px;
border-radius: 132px;
display: flex;
align-items: center;
justify-content: center;
}
.thumb {
position: absolute;
width: 14px;
height: 160px;
transform: rotate(var(--angle, 0deg));
&::before {
content: '';
position: absolute;
width: 14px;
height: 14px;
background-color: light-dark(var(--mantine-color-white), var(--filled-color));
border: 2px solid light-dark(var(--filled-color), var(--mantine-color-white));
border-radius: 50%;
left: 50%;
transform: translateX(-50%);
}
}
```
#### Props
**AngleSlider props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| defaultValue | number | - | Uncontrolled component default value |
| disabled | boolean | - | Sets `data-disabled` attribute, disables interactions |
| formatLabel | (value: number) => ReactNode | - | A function to format label based on the current value |
| hiddenInputProps | React.ComponentProps<"input"> | - | Props passed down to the hidden input |
| marks | { value: number; label?: string; }[] \| undefined | - | Array of marks displayed on the slider |
| name | string | - | Hidden input name, use with uncontrolled component |
| onChange | (value: number) => void | - | Called on value change |
| onChangeEnd | (value: number) => void | - | Called after the selection is finished |
| onScrubEnd | () => void | - | Called in `onMouseUp` and `onTouchEnd` |
| onScrubStart | () => void | - | Called in `onMouseDown` and `onTouchStart` |
| restrictToMarks | boolean | - | If set, the selection is allowed only from the given marks array |
| size | number | - | Slider size in px |
| step | number | - | Step between values |
| thumbSize | number | - | Size of the thumb in px. Calculated based on the `size` value by default. |
| value | number | - | Controlled component value |
| withLabel | boolean | - | If set, the label is displayed inside the slider |
#### Styles API
AngleSlider component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**AngleSlider selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-AngleSlider-root | Root element |
| label | .mantine-AngleSlider-label | Label inside the slider |
| marks | .mantine-AngleSlider-marks | Wrapper for all marks |
| mark | .mantine-AngleSlider-mark | Mark element |
| thumb | .mantine-AngleSlider-thumb | Slider thumb |
**AngleSlider CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --slider-size | Controls slider width and height |
| root | --thumb-size | Controls thumb size |
**AngleSlider data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | disabled | `disabled` prop is set | - |
--------------------------------------------------------------------------------
### AppShell
Package: @mantine/core
Import: import { AppShell } from '@mantine/core';
Description: Responsive shell for your application with header, navbar, aside and footer
## Examples
This page contains documentation only. All `AppShell` components have a fixed
position; examples are included in a separate documentation section.
## Usage
`AppShell` is a layout component that can be used to create a common Header / Navbar / Footer / Aside
layout pattern. All `AppShell` components have `position: fixed` styling, so they do not scroll with
the page.
[Basic AppShell example](https://mantine.dev/app-shell?e=BasicAppShell) with header and navbar.
The navbar is hidden on mobile by default and can be toggled with the burger button.
```tsx
import { AppShell, Burger } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [opened, { toggle }] = useDisclosure();
return (
Logo
NavbarMain
);
}
```
## AppShell components
* `AppShell` β root component that wraps all other sections and configures the overall layout.
* `AppShell.Header` β fixed header at the top, controlled by the `header` prop.
* `AppShell.Navbar` β fixed navbar on the left, controlled by the `navbar` prop.
* `AppShell.Aside` β fixed aside on the right, controlled by the `aside` prop.
* `AppShell.Footer` β fixed footer at the bottom, controlled by the `footer` prop.
* `AppShell.Main` β main content area, statically positioned and offset by the other sections.
* `AppShell.Section` β utility for grouping content inside `AppShell.Navbar` or `AppShell.Aside`, useful for scrollable areas.
## Configuration
The `AppShell` component accepts `header`, `footer`, `navbar`, and `aside` props to configure the corresponding sections.
You must set these props if you want to use the corresponding components.
For example, to use the `AppShell.Header` component, you need to set the `header` prop on the `AppShell` component.
`header` and `footer` configuration objects share the same type:
```tsx
interface Configuration {
/** Height of the section: number, string or
** object with breakpoints as keys and height as values */
height: AppShellSize | AppShellResponsiveSize;
/** When collapsed is true, the section is hidden
** from the viewport and doesn't affect the AppShell.Main offset */
collapsed?: boolean;
/** Controls whether AppShell.Main should be offset by this section.
** Useful for scenarios like hiding a header based on scroll position. */
offset?: boolean;
}
```
`navbar` and `aside` configuration objects type:
```tsx
interface Configuration {
/** Width of the section: number, string, or
** object with breakpoints as keys and widths as values */
width: AppShellSize | AppShellResponsiveSize;
/** Breakpoint at which the section switches to mobile mode.
** In mobile mode, the section always has 100% width and its
** collapsed state is controlled by `collapsed.mobile`
** instead of `collapsed.desktop` */
breakpoint: MantineBreakpoint | (string & {}) | number;
/** Determines whether the section should be collapsed */
collapsed?: { desktop?: boolean; mobile?: boolean };
}
```
## layout prop
`layout` prop controls how `AppShell.Header`/`AppShell.Footer` and `AppShell.Navbar`/`AppShell.Aside`
are positioned relative to each other. It accepts `alt` and `default` values:
* `alt` β `AppShell.Navbar`/`AppShell.Aside` extends the full viewport height, while `AppShell.Header`/`AppShell.Footer` width equals the viewport width minus the width of `AppShell.Navbar` and `AppShell.Aside` ([example](https://mantine.dev/app-shell?e=AltLayout))
* `default` β `AppShell.Navbar`/`AppShell.Aside` height equals the viewport height minus `AppShell.Header`/`AppShell.Footer` height, and `AppShell.Header`/`AppShell.Footer` spans the full viewport width ([example](https://mantine.dev/app-shell?e=FullLayout))
## Height configuration
The `height` property in `header` and `footer` configuration objects works as follows:
* If you pass a number, the value will be converted to [rem](https://alpha.mantine.dev/llms/styles-rem.md) and used as the
height at all viewport sizes.
* To change height based on viewport width, use an object with breakpoints as keys and height as
values. This works the same way as [style props](https://alpha.mantine.dev/llms/styles-style-props.md#responsive-styles).
Example with height as a number: `height` is converted to [rem](https://alpha.mantine.dev/llms/styles-rem.md),
and `height` remains the same at all viewport sizes:
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return (
Header
);
}
```
Example with height as an object with breakpoints:
* `height` is 48 when viewport width is \< `theme.breakpoints.sm`
* `height` is 60 when viewport width is >= `theme.breakpoints.sm` and \< `theme.breakpoints.lg`
* `height` is 76 when viewport width is >= `theme.breakpoints.lg`
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return (
Header
);
}
```
## Width configuration
The `width` property in `navbar` and `aside` configuration objects works as follows:
* If you pass a number, the value will be converted to [rem](https://alpha.mantine.dev/llms/styles-rem.md) and used as the
width when the viewport is larger than `breakpoint`.
* To change width based on viewport width, use an object with breakpoints as keys and width as
values. This works the same way as [style props](https://alpha.mantine.dev/llms/styles-style-props.md#responsive-styles).
Note that width is always 100% when the viewport is smaller than `breakpoint`.
Example with width as a number: `width` is converted to [rem](https://alpha.mantine.dev/llms/styles-rem.md),
and `width` remains the same at viewport sizes larger than `breakpoint`.
The `width` is 100% when viewport width is less than `breakpoint`:
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return (
Navbar
);
}
```
Example with width as an object with breakpoints:
* `width` is 100% when viewport width is \< `theme.breakpoints.sm`
* `width` is 200 when viewport width is >= `theme.breakpoints.sm` and \< `theme.breakpoints.lg`
* `width` is 300 when viewport width is >= `theme.breakpoints.lg`
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return (
Navbar
);
}
```
## padding prop
The `padding` prop controls the padding of the `AppShell.Main` component. It's important to use this prop
instead of setting padding directly on `AppShell.Main` because this padding is also used to calculate offsets for
the `AppShell.Header`, `AppShell.Navbar`, `AppShell.Aside`, and `AppShell.Footer` components.
The `padding` prop works the same way as [style props](https://alpha.mantine.dev/llms/styles-style-props.md#responsive-styles) and
accepts numbers, strings, and objects with breakpoints as keys and padding values. You can
reference `theme.spacing` values or use any valid CSS value.
Example with static `padding` prop:
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return {/* AppShell content */};
}
```
Example with responsive `padding` prop:
* `padding` is 10 when viewport width is \< `theme.breakpoints.sm`
* `padding` is 15 when viewport width is >= `theme.breakpoints.sm` and \< `theme.breakpoints.lg`
* `padding` is `theme.spacing.xl` when viewport width is >= `theme.breakpoints.lg`
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return (
{/* AppShell content */}
);
}
```
## Header offset configuration
The `header` prop includes an `offset` property that allows you to control
whether the `AppShell.Main` component is offset by the header's height.
This is particularly useful when you want to collapse the `AppShell.Header`
based on scroll position. For example, you can use the [use-headroom](https://alpha.mantine.dev/llms/hooks-use-headroom.md)
hook to hide the header when the user scrolls down and show it when they
scroll up ([example](https://mantine.dev/app-shell?e=Headroom)).
```tsx
import { AppShell, rem } from '@mantine/core';
import { useHeadroom } from '@mantine/hooks';
function Demo() {
const pinned = useHeadroom({ fixedAt: 120 });
return (
Header
{/* Content */}
);
}
```
## Collapsed navbar/aside configuration
The `navbar` and `aside` props include a `collapsed` property that accepts an object with the format `{ mobile: boolean; desktop: boolean }`.
This allows you to configure the collapsed state differently based on viewport width.
[Example](https://mantine.dev/app-shell?e=CollapseDesktop) with separate collapsed states for mobile and desktop:
```tsx
import { AppShell, Button } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
export function CollapseDesktop() {
const [mobileOpened, { toggle: toggleMobile }] = useDisclosure();
const [desktopOpened, { toggle: toggleDesktop }] =
useDisclosure(true);
return (
HeaderNavbar
);
}
```
## withBorder prop
The `withBorder` prop is available on `AppShell` and associated sections: `AppShell.Header`, `AppShell.Navbar`, `AppShell.Aside` and `AppShell.Footer`.
By default, `withBorder` prop is `true` β all components have a border on the side that is adjacent to the `AppShell.Main` component.
For example, `AppShell.Header` is located at the top of the page β it has a border on the bottom side,
`AppShell.Navbar` is located on the left side of the page β it has a border on the right side.
To remove the border from all components, set `withBorder={false}` on the `AppShell`:
```tsx
import { AppShell } from '@mantine/core';
// None of the components will have a border
function Demo() {
return (
{/* AppShell content */}
);
}
```
To remove the border from a specific component, set `withBorder={false}` on that component:
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return (
Header
);
}
```
## zIndex prop
The `zIndex` prop is available on `AppShell` and its associated sections: `AppShell.Header`, `AppShell.Navbar`, `AppShell.Aside`, and `AppShell.Footer`.
By default, all sections have a `z-index` of `100`.
To change the `z-index` of all sections, set the `zIndex` prop on the `AppShell` component:
```tsx
import { AppShell } from '@mantine/core';
// All sections will have z-index of 200
function Demo() {
return {/* AppShell content */};
}
```
To change `z-index` of a specific section, set `zIndex` prop on that section:
```tsx
import { AppShell } from '@mantine/core';
// AppShell.Header has z-index of 100
// AppShell.Navbar and AppShell.Aside have z-index of 300
function Demo() {
return (
HeaderNavbarAside
);
}
```
## Control transitions
Use the `transitionDuration` and `transitionTimingFunction` props on the `AppShell` component to control section animations:
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return (
{/* AppShell content */}
);
}
```
## disabled prop
Set the `disabled` prop on the `AppShell` component to prevent all sections except `AppShell.Main` from rendering.
This is useful when you want to hide the shell on certain pages of your application.
```tsx
import { AppShell } from '@mantine/core';
function Demo() {
return {/* AppShell content */};
}
```
## AppShell.Section component
`AppShell.Section` is used to create organized areas within `AppShell.Navbar` and `AppShell.Aside`.
Since these components are flexbox containers with `flex-direction: column`, the `AppShell.Section`
component with the `grow` prop will expand to fill the available space and can be made scrollable by setting
`component={ScrollArea}`.
In the following example:
* The first and last sections (header and footer) take only the space needed for their content
* The middle section with `grow` takes all the remaining space and becomes scrollable when content exceeds the available height
```tsx
import { AppShell, ScrollArea } from '@mantine/core';
function Demo() {
return (
Navbar header
Navbar main section that will expand to fill available space
Navbar footer β always at the bottom
Main
);
}
```
## Semantic elements
Important: do not use a `` element inside `AppShell.Main`, as only one `` element is allowed per page.
## CSS variables
Example of using CSS variables in styles:
```scss
.main {
min-height: calc(100dvh - var(--app-shell-header-height));
}
```
#### Props
**AppShell props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| aside | AppShellAsideConfiguration | - | `Aside` configuration, controls width, breakpoints and collapsed state. Required if you use `Aside` component. |
| disabled | boolean | - | If set, `Navbar`, `Aside`, `Header` and `Footer` components are hidden |
| footer | AppShellFooterConfiguration | - | `Footer` configuration, controls height, offset and collapsed state. Required if you use `Footer` component. |
| header | AppShellHeaderConfiguration | - | `Header` configuration, controls height, offset and collapsed state. Required if you use `Header` component. |
| layout | "default" \| "alt" | - | Determines how `Navbar`/`Aside` are arranged relative to `Header`/`Footer` |
| mode | "fixed" \| "static" | - | Determines positioning mode of all sections |
| navbar | AppShellNavbarConfiguration | - | `Navbar` configuration, controls width, breakpoints and collapsed state. Required if you use `Navbar` component. |
| offsetScrollbars | boolean | - | If set, `Header` and `Footer` components include styles to offset scrollbars. Based on `react-remove-scroll`. |
| padding | MantineSpacing \| AppShellResponsiveSize | - | Padding of the main section. Important: use `padding` prop instead of `p`. |
| transitionDuration | number | - | Duration of all transitions in ms |
| transitionTimingFunction | TransitionTimingFunction | - | Timing function of all transitions |
| withBorder | boolean | - | If set, the associated components have a border |
| zIndex | string \| number | - | `z-index` of all associated elements |
**AppShell.Aside props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| withBorder | boolean | - | If set, component haves a border, overrides `withBorder` prop on `AppShell` component |
| zIndex | React.CSSProperties["zIndex"] | - | Sets `z-index`. Inherited from the `AppShell` by default. |
**AppShell.Navbar props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| withBorder | boolean | - | If set, component haves a border, overrides `withBorder` prop on `AppShell` component |
| zIndex | React.CSSProperties["zIndex"] | - | Sets `z-index`. Inherited from the `AppShell` by default. |
**AppShell.Header props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| withBorder | boolean | - | If set, component haves a border, overrides `withBorder` prop on `AppShell` component |
| zIndex | React.CSSProperties["zIndex"] | - | Sets `z-index`. Inherited from the `AppShell` by default. |
**AppShell.Footer props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| withBorder | boolean | - | If set, component haves a border, overrides `withBorder` prop on `AppShell` component |
| zIndex | React.CSSProperties["zIndex"] | - | Sets `z-index`. Inherited from the `AppShell` by default. |
**AppShell.Section props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| grow | boolean | - | If set, the section expands to take all available space |
#### Styles API
AppShell component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**AppShell selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-AppShell-root | Root element (`AppShell` component) |
| navbar | .mantine-AppShell-navbar | `AppShell.Navbar` root element |
| header | .mantine-AppShell-header | `AppShell.Header` root element |
| main | .mantine-AppShell-main | `AppShell.Main` root element |
| aside | .mantine-AppShell-aside | `AppShell.Aside` root element |
| footer | .mantine-AppShell-footer | `AppShell.Footer` root element |
| section | .mantine-AppShell-section | `AppShell.Section` root element |
**AppShell CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --app-shell-transition-duration | Controls transition duration of all children |
**AppShell data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-resizing | User is resizing the window | - |
| root | data-layout | - | Value of the `layout` prop |
| root | data-disabled | `disabled` prop is set | - |
--------------------------------------------------------------------------------
### AspectRatio
Package: @mantine/core
Import: import { AspectRatio } from '@mantine/core';
Description: Maintain responsive consistent width/height ratio
## Usage
`AspectRatio` maintains a consistent width/height ratio.
It can be used to display images, maps, videos, and other media.
```tsx
import { AspectRatio } from '@mantine/core';
function Demo() {
return (
);
}
```
## Map embed
```tsx
import { AspectRatio } from '@mantine/core';
function Demo() {
return (
);
}
```
## Video embed
```tsx
import { AspectRatio } from '@mantine/core';
function Demo() {
return (
);
}
```
## Inside flex container
By default, `AspectRatio` does not have a fixed width and height β it will take as much space as possible
in a regular container. However, when used inside a flex container, it will not stretch to fill the available space.
To make it work inside a flexbox container, you need to set the `width` or `flex` property.
```tsx
import { AspectRatio, Image } from '@mantine/core';
function Demo() {
return (
);
}
```
#### Props
**AspectRatio props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| ratio | number | - | Aspect ratio, for example, `16 / 9`, `4 / 3`, `1920 / 1080` |
#### Styles API
AspectRatio component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**AspectRatio selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-AspectRatio-root | Root element |
**AspectRatio CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --ar-ratio | Aspect ratio |
--------------------------------------------------------------------------------
### Autocomplete
Package: @mantine/core
Import: import { Autocomplete } from '@mantine/core';
Description: Autocomplete user input with any list of options
## Not a searchable select
`Autocomplete` is not a searchable select, it is a text input with suggestions.
Values are not enforced to be one of the suggestions β users can type anything.
If you need a searchable select, use the [Select](https://alpha.mantine.dev/llms/core-select.md) component instead.
To learn more about the differences between `Autocomplete` and `Select`, check the
[help center article](https://help.mantine.dev/q/select-autocomplete-difference).
## Usage
`Autocomplete` provides users with a list of suggestions based on the input,
however users are not limited to suggestions and can type anything.
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Loading state
Set `loading` prop to display a loading indicator. By default, the loader is displayed on the right side of the input.
You can change the position with the `loadingPosition` prop to `'left'` or `'right'`. This is useful for async operations like API calls, searches, or validations:
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Controlled
The `Autocomplete` value must be a string; other types are not supported.
The `onChange` function is called with a string value as a single argument.
```tsx
import { useState } from 'react';
import { Autocomplete } from '@mantine/core';
function Demo() {
const [value, setValue] = useState('');
return ;
}
```
## Uncontrolled
`Autocomplete` can be used with uncontrolled forms the same way as a native `input` element.
Set the `name` attribute to include autocomplete value in `FormData` object on form submission.
To control the initial value in uncontrolled forms, use the `defaultValue` prop.
Example usage of uncontrolled `Autocomplete` with `FormData`:
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Select first option on change
Set the `selectFirstOptionOnChange` prop to automatically select the first option in the dropdown when the input value changes.
This feature allows users to type a value and immediately press `Enter` to select the first matching option,
without needing to press the arrow down key first.
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## autoSelectOnBlur
Set the `autoSelectOnBlur` prop to automatically select the highlighted option when the input loses focus.
To see this feature in action: select an option with the up/down arrows, then click outside the input:
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Data prop
Data that is used in Autocomplete must be an array of strings or objects with value and label properties. You can also specify additional properties that will be available in renderOption function.
## Filtering
Autocomplete provides built-in filtering functionality. You can control filtering behavior with filter prop or implement custom filtering logic.
```tsx
import { Autocomplete, ComboboxItem, OptionsFilter } from '@mantine/core';
const optionsFilter: OptionsFilter = ({ options, search }) => {
const splittedSearch = search.toLowerCase().trim().split(' ');
return (options as ComboboxItem[]).filter((option) => {
const words = option.label.toLowerCase().trim().split(' ');
return splittedSearch.every((searchWord) => words.some((word) => word.includes(searchWord)));
});
};
function Demo() {
return (
);
}
```
## Sort options
By default, options are sorted by their position in the data array. You can change this behavior
with the `filter` function:
```tsx
import { Autocomplete, ComboboxItem, OptionsFilter } from '@mantine/core';
const optionsFilter: OptionsFilter = ({ options, search }) => {
const filtered = (options as ComboboxItem[]).filter((option) =>
option.label.toLowerCase().trim().includes(search.toLowerCase().trim())
);
filtered.sort((a, b) => a.label.localeCompare(b.label));
return filtered;
};
function Demo() {
return (
);
}
```
## Fuzzy search with fuse.js
You can implement fuzzy search using the [fuse.js](https://fusejs.io/) library to match options
even with typos or partial matches:
```tsx
import { Autocomplete, ComboboxItem, OptionsFilter } from '@mantine/core';
import Fuse from 'fuse.js';
const optionsFilter: OptionsFilter = ({ options, search }) => {
if (!search.trim()) {
return options;
}
const fuse = new Fuse(options as ComboboxItem[], {
keys: ['label'],
threshold: 0.3,
minMatchCharLength: 1,
});
return fuse.search(search).map((result) => result.item);
};
function Demo() {
return (
);
}
```
## Large datasets
Autocomplete can handle large datasets efficiently. Consider implementing virtualization for datasets with thousands of items to improve performance.
```tsx
import { Autocomplete } from '@mantine/core';
const largeData = Array(100_000)
.fill(0)
.map((_, index) => `Option ${index}`);
function Demo() {
return (
);
}
```
## renderOption
The `renderOption` callback allows you to customize option rendering. It is called with an option object.
The function must return a React node.
```tsx
import { Autocomplete, AutocompleteProps, Avatar, Group, Text } from '@mantine/core';
const usersData: Record = {
'Emily Johnson': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-7.png',
email: 'emily92@gmail.com',
},
'Ava Rodriguez': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-8.png',
email: 'ava_rose@gmail.com',
},
'Olivia Chen': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-4.png',
email: 'livvy_globe@gmail.com',
},
'Ethan Barnes': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-1.png',
email: 'ethan_explorer@gmail.com',
},
'Mason Taylor': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-2.png',
email: 'mason_musician@gmail.com',
},
};
const renderAutocompleteOption: AutocompleteProps['renderOption'] = ({ option }) => (
{option.value}
{usersData[option.value].email}
);
function Demo() {
return (
);
}
```
## Nothing found message
The `Autocomplete` component does not support a nothing found message. It is designed to
accept any string as a value, so it does not make sense to show a nothing found message.
If you want to limit user input to suggestions, you can use a searchable [Select](https://alpha.mantine.dev/llms/core-select.md)
component instead. To learn more about the differences between `Autocomplete` and `Select`, check the
[help center article](https://help.mantine.dev/q/select-autocomplete-difference).
## Scrollable dropdown
By default, the options list is wrapped with [ScrollArea.Autosize](https://alpha.mantine.dev/llms/core-scroll-area.md).
You can control the dropdown max-height with the `maxDropdownHeight` prop if you do not change the default settings.
If you want to use native scrollbars, set `withScrollArea={false}`. Note that in this case,
you will need to change the dropdown styles with [Styles API](https://alpha.mantine.dev/llms/styles-styles-api.md).
```tsx
import { Autocomplete } from '@mantine/core';
const data = Array(100)
.fill(0)
.map((_, index) => `Option ${index}`);
function Demo() {
return (
<>
>
);
}
```
## Group options
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Disabled options
When an option is disabled, it cannot be selected and is ignored in keyboard navigation.
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Inside Popover
To use `Autocomplete` inside popover, you need to set `withinPortal: false`:
```tsx
import { Popover, Button, Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Clearable
Set the `clearable` prop to display the clear button in the right section. The button is not displayed
when:
* The component does not have a value
* The component is disabled
* The component is read only
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
```tsx
import { CaretDownIcon } from '@phosphor-icons/react';
import { Autocomplete, Stack } from '@mantine/core';
function Demo() {
return (
}
clearSectionMode="both"
/>
}
clearSectionMode="rightSection"
/>
}
clearSectionMode="clear"
/>
);
}
```
## Control dropdown opened state
You can control the dropdown opened state with the `dropdownOpened` prop. Additionally,
you can use `onDropdownClose` and `onDropdownOpen` to listen to dropdown opened state changes.
```tsx
import { Autocomplete, Button } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [dropdownOpened, { toggle }] = useDisclosure();
return (
<>
>
);
}
```
## Dropdown position
By default, the dropdown is displayed below the input if there is enough space; otherwise it is displayed above the input.
You can change this behavior by setting the `position` and `middlewares` props, which are passed down to the
underlying [Popover](https://alpha.mantine.dev/llms/core-popover.md) component.
Example of dropdown that is always displayed above the input:
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Dropdown animation
By default, dropdown animations are disabled. To enable them, you can set `transitionProps`,
which will be passed down to the underlying [Transition](https://alpha.mantine.dev/llms/core-transition.md) component.
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Dropdown padding
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
<>
>
);
}
```
## Dropdown shadow
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Input sections
Autocomplete supports left and right sections to display icons, buttons or other content alongside the input.
```tsx
import { Autocomplete } from '@mantine/core';
import { SquaresFourIcon } from '@phosphor-icons/react';
function Demo() {
const icon = ;
return (
<>
>
);
}
```
## Input props
Autocomplete component supports [Input](https://mantine.dev/core/input) and [Input.Wrapper](https://mantine.dev/core/input) components features and all input element props. Autocomplete documentation does not include all features supported by the component β see [Input](https://mantine.dev/core/input) documentation to learn about all available features.
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Read only
Set `readOnly` to make the input read only. When `readOnly` is set,
`Autocomplete` will not show suggestions and will not call the `onChange` function.
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
## Disabled
Set `disabled` to disable the input. When `disabled` is set,
users cannot interact with the input and `Autocomplete` will not show suggestions.
```tsx
import { Autocomplete } from '@mantine/core';
function Demo() {
return (
);
}
```
#### Props
**Autocomplete props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoSelectOnBlur | boolean | - | If set, the highlighted option is selected when the input loses focus |
| clearButtonProps | InputClearButtonProps | - | Props passed down to the clear button |
| clearSectionMode | ClearSectionMode | - | Determines how the clear button and rightSection are rendered |
| clearable | boolean | - | If set, the clear button is displayed when the component has a value |
| comboboxProps | ComboboxProps | - | Props passed down to `Combobox` component |
| data | ComboboxGenericData | - | Data used to display options. Values must be unique. |
| defaultDropdownOpened | boolean | - | Uncontrolled dropdown initial opened state |
| defaultValue | string | - | Default value for uncontrolled component |
| description | React.ReactNode | - | Contents of `Input.Description` component. If not set, description is not displayed. |
| descriptionProps | InputDescriptionProps | - | Props passed down to the `Input.Description` component |
| disabled | boolean | - | Sets `disabled` attribute on the `input` element |
| dropdownOpened | boolean | - | Controlled dropdown opened state |
| error | React.ReactNode | - | Contents of `Input.Error` component. If not set, error is not displayed. |
| errorProps | InputErrorProps | - | Props passed down to the `Input.Error` component |
| filter | OptionsFilter | - | Function based on which items are filtered and sorted |
| inputContainer | (children: ReactNode) => ReactNode | - | Render function to wrap the input element. Useful for adding tooltips, popovers, or other wrappers around the input. |
| inputSize | string | - | HTML `size` attribute for the input element (number of visible characters) |
| inputWrapperOrder | ("input" \| "label" \| "description" \| "error")[] | - | Controls order and visibility of wrapper elements. Only elements included in this array will be rendered. |
| label | React.ReactNode | - | Contents of `Input.Label` component. If not set, label is not displayed. |
| labelProps | InputLabelProps | - | Props passed down to the `Input.Label` component |
| leftSection | React.ReactNode | - | Content section displayed on the left side of the input |
| leftSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `leftSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| leftSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `leftSection` element |
| leftSectionWidth | React.CSSProperties["width"] | - | Left section width, used to set `width` of the section and input `padding-left`, by default equals to the input height |
| limit | number | - | Maximum number of options displayed at a time, `Infinity` by default |
| loading | boolean | - | Displays loading indicator in the left or right section |
| loadingPosition | "left" \| "right" | - | Position of the loading indicator |
| maxDropdownHeight | string \| number | - | `max-height` of the dropdown, only applicable when `withScrollArea` prop is `true`, `250` by default |
| onChange | (value: string) => void | - | Called when value changes |
| onClear | () => void | - | Called when the clear button is clicked |
| onDropdownClose | () => void | - | Called when dropdown closes |
| onDropdownOpen | () => void | - | Called when dropdown opens |
| onOptionSubmit | (value: string) => void | - | Called when option is submitted from dropdown with mouse click or `Enter` key |
| openOnFocus | boolean | - | If set, the dropdown opens when the input receives focus |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem |
| renderOption | RenderAutocompleteOption | - | Function to render custom option content |
| required | boolean | - | Adds required attribute to the input and a red asterisk on the right side of label |
| rightSection | React.ReactNode | - | Content section displayed on the right side of the input |
| rightSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `rightSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| rightSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `rightSection` element |
| rightSectionWidth | React.CSSProperties["width"] | - | Right section width, used to set `width` of the section and input `padding-right`, by default equals to the input height |
| scrollAreaProps | ScrollAreaProps | - | Props passed to the underlying `ScrollArea` component in the dropdown |
| selectFirstOptionOnChange | boolean | - | If set, the first option is selected when value changes, `false` by default |
| selectFirstOptionOnDropdownOpen | boolean | - | If set, the first option is selected when dropdown opens, `false` by default |
| size | MantineSize | - | Controls input `height`, horizontal `padding`, and `font-size` |
| value | string | - | Controlled component value |
| withAsterisk | boolean | - | If set, the required asterisk is displayed next to the label. Overrides `required` prop. Does not add required attribute to the input. |
| withErrorStyles | boolean | - | Determines whether the input should have red border and red text color when the `error` prop is set |
| withScrollArea | boolean | - | Determines whether the options should be wrapped with `ScrollArea.AutoSize`, `true` by default |
| wrapperProps | WrapperProps | - | Props passed down to the root element |
#### Styles API
Autocomplete component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Autocomplete selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| wrapper | .mantine-Autocomplete-wrapper | Root element of the Input |
| input | .mantine-Autocomplete-input | Input element |
| section | .mantine-Autocomplete-section | Left and right sections |
| root | .mantine-Autocomplete-root | Root element |
| label | .mantine-Autocomplete-label | Label element |
| required | .mantine-Autocomplete-required | Required asterisk element, rendered inside label |
| description | .mantine-Autocomplete-description | Description element |
| error | .mantine-Autocomplete-error | Error element |
**Autocomplete data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| option | data-combobox-selected | Option is selected | - |
| option | data-combobox-active | Options was activated by keyboard | - |
| option | data-combobox-disabled | Option is disabled | - |
--------------------------------------------------------------------------------
### Avatar
Package: @mantine/core
Import: import { Avatar } from '@mantine/core';
Description: Display user profile image, initials or fallback icon
## Usage
```tsx
import { Avatar } from '@mantine/core';
import { StarIcon } from '@phosphor-icons/react';
function Demo() {
return (
<>
{/* With image */}
{/* Default placeholder */}
{/* Letters with xl radius */}
MK
{/* Custom placeholder icon */}
>
);
}
```
## Initials
To display initials instead of the default placeholder, set the `name` prop
to the name of the person, for example, `name="John Doe"`. If the name
is set, you can use `color="initials"` to generate a color based on the name:
```tsx
import { Avatar, Group } from '@mantine/core';
${namesCode}
function Demo() {
const avatars = names.map((name) => );
return {avatars};
}
```
## Allowed initials colors
By default, all colors from the default theme are allowed for initials. You can restrict them
by providing the `allowedInitialsColors` prop with an array of colors. Note that the default colors
array does not include custom colors defined in the theme β you need to provide them manually
if needed.
```tsx
import { Avatar, Group } from '@mantine/core';
${namesCode}
function Demo() {
const avatars = names.map((name) => (
));
return {avatars};
}
```
## Placeholder
If the image cannot be loaded or is not provided, `Avatar` will display a placeholder instead. By default,
the placeholder is an icon, but it can be changed to any React node:
```tsx
import { Avatar } from '@mantine/core';
import { StarIcon } from '@phosphor-icons/react';
function Demo() {
return (
<>
{/* Default placeholder */}
{/* Default placeholder with custom color */}
{/* Placeholder with initials */}
VR
{/* Placeholder with custom icon */}
>
);
}
```
## Variants
```tsx
import { Avatar } from '@mantine/core';
function Demo() {
return ;
}
```
## Avatar.Group
The `Avatar.Group` component combines multiple avatars into a stack:
```tsx
import { Avatar } from '@mantine/core';
function Demo() {
return (
+5
);
}
```
Note that you must not wrap child `Avatar` components with any additional elements,
but you can wrap `Avatar` with components that do not render any HTML elements
in the current tree, for example [Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md).
```tsx
import { Avatar } from '@mantine/core';
// Will not work correctly
function Demo() {
return (
+5
);
}
```
Example of usage with [Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md):
```tsx
import { Avatar, Tooltip } from '@mantine/core';
function Demo() {
return (
John Outcast
Levi Capitan
>
}
>
+2
);
}
```
Example of using `Avatar` as a link:
```tsx
import { Avatar } from '@mantine/core';
function Demo() {
return (
);
}
```
## Accessibility
Avatar renders an `` HTML element. Set the `alt` prop to describe the image β
it is also used as the `title` attribute for the avatar placeholder when the image cannot be loaded.
```tsx
import { Avatar } from '@mantine/core';
function Demo() {
// β No alt for image
return ;
// β alt is set
return ;
// β title is not required, but still recommended
return RJ;
// β title is set on placeholder
return RJ;
}
```
#### Props
**Avatar props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| allowedInitialsColors | DefaultMantineColor[] | - | A list of colors that is used for autogenerated initials. By default, all default Mantine colors can be used except gray and dark. |
| alt | string | - | Image `alt` attribute, also used as `title` attribute for placeholder |
| autoContrast | boolean | - | If set, adjusts text color based on background color for `filled` variant |
| children | React.ReactNode | - | Avatar placeholder, displayed when `src={null}` or when the image cannot be loaded |
| color | DefaultMantineColor \| "initials" | - | Key of `theme.colors` or any valid CSS color |
| gradient | MantineGradient | - | Gradient configuration for `variant="gradient"` |
| imageProps | DetailedHTMLProps, HTMLImageElement> | - | Attributes passed down to `img` element |
| name | string | - | Name of the user. When `src` is not set, used to display initials and to generate color when `color="initials"` is set. |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius |
| size | MantineSize \| number | - | Width and height of the avatar, numbers are converted to rem |
| src | string \| null | - | Image url, if the image cannot be loaded or `src={null}`, then placeholder is displayed instead |
**Avatar.Group props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
#### Styles API
Avatar component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Avatar selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Avatar-root | Root element |
| image | .mantine-Avatar-image | `img` element |
| placeholder | .mantine-Avatar-placeholder | Avatar placeholder, displayed when the image cannot be loaded |
**Avatar CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --avatar-bd | Controls placeholder `border` |
| root | --avatar-bg | Controls placeholder `background` |
| root | --avatar-color | Controls placeholder text `color` |
| root | --avatar-size | Controls `width`, `min-width` and `height` |
| root | --avatar-radius | Controls `border-radius` |
**Avatar.Group selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| group | .mantine-AvatarGroup-group | Root element |
**Avatar.Group CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| group | --ag-spacing | Controls negative spacing between avatars |
--------------------------------------------------------------------------------
### BackgroundImage
Package: @mantine/core
Import: import { BackgroundImage } from '@mantine/core';
Description: Displays image as background
## Usage
```tsx
import { BackgroundImage, Center, Text, Box } from '@mantine/core';
function Demo() {
return (
BackgroundImage component can be used to add any content on image. It is useful for hero
headers and other similar sections
);
}
```
#### Props
**BackgroundImage props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius, numbers are converted to rem |
| src | string | required | Image url |
#### Styles API
BackgroundImage component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**BackgroundImage selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-BackgroundImage-root | Root element |
**BackgroundImage CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --bi-radius | Controls `border-radius` |
--------------------------------------------------------------------------------
### Badge
Package: @mantine/core
Import: import { Badge } from '@mantine/core';
Description: Display badge, pill or tag
## Usage
```tsx
import { Badge } from '@mantine/core';
function Demo() {
return Badge;
}
```
```tsx
import { Badge } from '@mantine/core';
function Demo() {
return (
Gradient badge
);
}
```
## Rounded
Set the `circle` prop to reduce horizontal padding and make the badge width equal to its height:
```tsx
import { Badge, Group } from '@mantine/core';
function Demo() {
return (
1
7
9
3
8
);
}
```
## Left and right sections
```tsx
import { Badge, Group } from '@mantine/core';
import { AtIcon } from '@phosphor-icons/react';
function Demo() {
const icon = ;
return (
With left sectionWith right section
);
}
```
## Full width
Set `fullWidth` to make the badge span the full width of its parent element:
```tsx
import { Badge } from '@mantine/core';
function Demo() {
return Full width badge;
}
```
#### Props
**Badge props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts text color based on background color for `filled` variant |
| children | React.ReactNode | - | Main badge content |
| circle | boolean | - | If set, badge `min-width` becomes equal to its `height` and horizontal padding is removed |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
| fullWidth | boolean | - | Determines whether Badge should take 100% of its parent width |
| gradient | MantineGradient | - | Gradient configuration used when `variant=\"gradient\"` |
| leftSection | React.ReactNode | - | Content displayed on the left side of the badge label |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| rightSection | React.ReactNode | - | Content displayed on the right side of the badge label |
| size | MantineSize | - | Controls `font-size`, `height` and horizontal `padding` |
#### Styles API
Badge component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Badge selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Badge-root | Root element |
| section | .mantine-Badge-section | Left and right sections |
| label | .mantine-Badge-label | Badge children |
**Badge CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --badge-bd | Controls `border` |
| root | --badge-bg | Controls `background` |
| root | --badge-color | Controls text `color` |
| root | --badge-dot-color | Controls dot `color`, only applicable when `variant="dot"` |
| root | --badge-fz | Controls `font-size` |
| root | --badge-height | Controls `height` |
| root | --badge-padding-x | Controls horizontal `padding` |
| root | --badge-radius | Controls `border-radius` |
**Badge data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-block | `fullWidth` prop is set | - |
| section | data-position | - | Section position: left or right |
--------------------------------------------------------------------------------
### Blockquote
Package: @mantine/core
Import: import { Blockquote } from '@mantine/core';
Description: Blockquote with optional cite
## Usage
```tsx
import { Blockquote } from '@mantine/core';
import { InfoIcon } from '@phosphor-icons/react';
function Demo() {
const icon = ;
return (
Life is like an npm install β you never know what you are going to get.
);
}
```
#### Props
**Blockquote props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| cite | React.ReactNode | - | Reference to a cited quote |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
| icon | React.ReactNode | - | Blockquote icon, displayed at the top left side |
| iconSize | string \| number | - | Controls icon `width` and `height`, numbers are converted to rem |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
#### Styles API
Blockquote component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Blockquote selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Blockquote-root | Root element |
| icon | .mantine-Blockquote-icon | Icon element |
| cite | .mantine-Blockquote-cite | Cite element |
**Blockquote CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --bq-bd | Controls `border` |
| root | --bq-bg-dark | Controls `background-color` in dark color scheme |
| root | --bq-bg-light | Controls `background-color` in light color scheme |
| root | --bq-icon-size | Controls `width` and `height` of the icon |
| root | --bq-radius | Controls `border-radius` |
--------------------------------------------------------------------------------
### Box
Package: @mantine/core
Import: import { Box } from '@mantine/core';
Description: Base component for all Mantine components
## Usage
`Box` component is used as a base for all other components. `Box` supports the following features:
* [component prop](https://alpha.mantine.dev/llms/guides-polymorphic.md)
* [style props](https://alpha.mantine.dev/llms/styles-style-props.md)
* [style prop](https://alpha.mantine.dev/llms/styles-style.md)
You can use `Box` as a base for your own components or as a replacement for HTML elements:
```tsx
import { Box } from '@mantine/core';
function Demo() {
return (
My component
);
}
```
--------------------------------------------------------------------------------
### Breadcrumbs
Package: @mantine/core
Import: import { Breadcrumbs } from '@mantine/core';
Description: Separates list of react nodes with given separator
## Usage
`Breadcrumbs` component accepts any number of React nodes as children
and adds a given separator (defaults to `/`) between them:
```tsx
import { Breadcrumbs, Anchor } from '@mantine/core';
const items = [
{ title: 'Mantine', href: '#' },
{ title: 'Mantine hooks', href: '#' },
{ title: 'use-id', href: '#' },
].map((item, index) => (
{item.title}
));
function Demo() {
return (
<>
{items}
{items}
>
);
}
```
#### Props
**Breadcrumbs props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | React nodes that should be separated with `separator` |
| separator | React.ReactNode | - | Separator between children |
| separatorMargin | MantineSpacing | - | Controls spacing between separator and breadcrumb |
#### Styles API
Breadcrumbs component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Breadcrumbs selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Breadcrumbs-root | Root element |
| separator | .mantine-Breadcrumbs-separator | Separator between children |
| breadcrumb | .mantine-Breadcrumbs-breadcrumb | Breadcrumb item |
**Breadcrumbs CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --bc-separator-margin | Control left and right `margin` of separator |
--------------------------------------------------------------------------------
### Burger
Package: @mantine/core
Import: import { Burger } from '@mantine/core';
Description: Open/close navigation button
## Usage
The `Burger` component renders an open/close menu button.
Set the `opened` and `onClick` props to control the component state.
If the `opened` prop is set, a cross will be rendered, otherwise a burger icon.
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Burger } from '@mantine/core';
function Demo() {
const [opened, { toggle }] = useDisclosure();
return ;
}
```
## Change line size
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Burger } from '@mantine/core';
function Demo() {
const [opened, { toggle }] = useDisclosure();
return ;
}
```
## Accessibility
To make the `Burger` accessible for screen readers, you need to either set `aria-label` or
use the [VisuallyHidden](https://alpha.mantine.dev/llms/core-visually-hidden.md) component:
```tsx
import { Burger, VisuallyHidden } from '@mantine/core';
function Demo() {
return (
<>
Toggle navigation
>
);
}
```
#### Props
**Burger props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| color | MantineColor | - | Key of `theme.colors` of any valid CSS value, by default `theme.white` in dark color scheme and `theme.black` in light |
| lineSize | string \| number | - | Controls height of lines, by default calculated based on `size` prop |
| opened | boolean | - | State of the burger, when `true` burger is transformed into X |
| size | MantineSize \| number | - | Controls burger `width` and `height`, numbers are converted to rem |
| transitionDuration | number | - | `transition-duration` property value in ms |
| transitionTimingFunction | string | - | `transition-timing-function` property value |
#### Styles API
Burger component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Burger selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Burger-root | Root element (button) |
| burger | .mantine-Burger-burger | Inner element that contains burger lines |
**Burger CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --burger-line-size | Controls height of lines |
| root | --burger-color | Controls background-color of lines |
| root | --burger-size | Controls width and height of the button |
| root | --burger-transition-duration | Controls transition-duration of lines |
| root | --burger-transition-timing-function | Controls transition-timing-function of lines |
**Burger data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| burger | data-opened | opened prop is set | - |
--------------------------------------------------------------------------------
### Button
Package: @mantine/core
Import: import { Button } from '@mantine/core';
Description: Button component to render button or link
## Usage
```tsx
import { Button } from '@mantine/core';
function Demo() {
return ;
}
```
## Full width
If the `fullWidth` prop is set, the `Button` will take 100% of the parent width:
```tsx
import { Button } from '@mantine/core';
function Demo() {
return ;
}
```
## Left and right sections
`leftSection` and `rightSection` allow adding icons or any other element to the left and right sides of the button.
When a section is added, padding on the corresponding side is reduced.
Note that `leftSection` and `rightSection` are flipped in [RTL](https://alpha.mantine.dev/llms/styles-rtl.md) mode
(`leftSection` is displayed on the right and `rightSection` is displayed on the left).
```tsx
import { Group, Button } from '@mantine/core';
import { ImageIcon, DownloadSimpleIcon, ArrowRightIcon } from '@phosphor-icons/react';
function Demo() {
return (
} variant="default">
Gallery
}>Download
}
rightSection={}
>
Visit gallery
);
}
```
## Sections position
The `justify` prop sets the `justify-content` of the `inner` element. You can use it to change the alignment of
left and right sections. For example, to spread them across the button, set `justify="space-between"`.
If you need to align just one section to the side of the button, set `justify` to `space-between`
and add an empty `` to the opposite section.
```tsx
import { Button } from '@mantine/core';
import { ImageIcon } from '@phosphor-icons/react';
function Demo() {
const icon = ;
return (
<>
}
variant="default"
mt="md"
>
Button label
>
);
}
```
## Compact size
`Button` supports `xs` β `xl` and `compact-xs` β `compact-xl` sizes. `compact` sizes have
the same font size as `xs` β `xl` but with reduced padding and height.
```tsx
import { Button, Group } from '@mantine/core';
function Demo() {
return (
);
}
```
```tsx
import { Button } from '@mantine/core';
function Demo() {
return (
);
}
```
## Disabled state
To make a `Button` disabled, set the `disabled` prop. This will prevent any interactions with the button
and add disabled styles. If you want the button to just look disabled but still be interactive,
set the `data-disabled` prop instead. Note that disabled styles are the same for all variants.
```tsx
import { Button } from '@mantine/core';
function Demo() {
return ;
}
```
## Disabled state when Button is link
The `` element does not support the `disabled` attribute. To make a `Button` disabled when it is
rendered as a link, set the `data-disabled` attribute instead and prevent default behavior in the
`onClick` event handler.
```tsx
import { Button } from '@mantine/core';
function Demo() {
return (
);
}
```
## Customize disabled styles
To customize disabled styles, it is recommended to use both `&:disabled` and `&[data-disabled]`
selectors:
* `&:disabled` is used to style the button when the `disabled` prop is set and
also when the button is disabled by the parent component (for example, when the `disabled` prop is set on a
`` element which contains the `Button`).
* `&[data-disabled]` is used to style the button when it is not actually disabled but should look like
it is (for example, `data-disabled` should be used if you need to use [Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md) with a disabled `Button`
or when the `Button` is used as a link)
```tsx
// Demo.module.css
.button {
&:disabled,
&[data-disabled] {
border-color: light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
background-color: transparent;
}
}
// Demo.tsx
import { Button } from '@mantine/core';
import classes from './Demo.module.css';
function Demo() {
return (
);
}
```
## Disabled button with Tooltip
The `onMouseLeave` event [is not triggered](https://github.com/facebook/react/issues/18753) when a `Button` is disabled, so if you need to use a
[Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md) with a disabled `Button`, you need to set the `data-disabled` prop on the `Button`
instead of `disabled`. Note that it is also required to change the `onClick` event handler to
`(event) => event.preventDefault()` as the `Button` is not actually disabled and will still trigger the
`onClick` event.
```tsx
import { Button, Tooltip } from '@mantine/core';
function Demo() {
return (
);
}
```
## Loading state
When the `loading` prop is set, the `Button` will be disabled and a [Loader](https://alpha.mantine.dev/llms/core-loader.md) with overlay will be rendered
in the center of the button. [Loader](https://alpha.mantine.dev/llms/core-loader.md) color depends on the `Button` variant.
```tsx
import { Button, Group, Switch } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [loading, { toggle }] = useDisclosure();
return (
<>
>
);
}
```
## Custom variants
To add new `Button` variants, use the [data-variant](https://alpha.mantine.dev/llms/styles-variants-sizes.md) attribute.
Usually new variants are added to the [theme](https://alpha.mantine.dev/llms/theming-theme-object.md), this way they are
available in all `Button` components in your application.
```tsx
// Demo.tsx
import { Group, Button, MantineProvider, createTheme } from '@mantine/core';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
Button: Button.extend({
classNames: classes,
}),
},
});
function Demo() {
return (
);
}
// Demo.module.css
.root {
&[data-variant='danger'] {
background-color: var(--mantine-color-red-9);
color: var(--mantine-color-red-0);
}
&[data-variant='primary'] {
background: linear-gradient(45deg, #4b6cb7 10%, #253b67 90%);
color: var(--mantine-color-white);
border-width: 0;
}
}
```
## Customize variant colors
You can customize colors for `Button` and other component variants by adding
[variantColorResolver](https://alpha.mantine.dev/llms/theming-colors.md#colors-variant-resolver) to your theme.
```tsx
import {
Button,
Group,
MantineProvider,
defaultVariantColorsResolver,
VariantColorsResolver,
parseThemeColor,
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)',
hoverColor: '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: `1px 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 (
);
}
```
```tsx
import { Button, Group } from '@mantine/core';
function Demo() {
return (
);
}
```
## Button.Group
```tsx
import { Button } from '@mantine/core';
function Demo() {
return (
);
}
```
Note that you must not wrap child `Button` components with any additional elements:
```tsx
import { Button } from '@mantine/core';
function Demo() {
return (
);
}
```
## Button.GroupSection
Use `Button.GroupSection` component to render sections that are not buttons inside `Button.Group`:
```tsx
import { CaretDownIcon, CaretUpIcon } from '@phosphor-icons/react';
import { Button } from '@mantine/core';
import { useCounter } from '@mantine/hooks';
function Demo() {
const [value, { increment, decrement }] = useCounter(135, { min: 0 });
return (
{value}
);
}
```
#### Props
**Button props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts text color based on background color for `filled` variant |
| children | React.ReactNode | - | Button content |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
| disabled | boolean | - | Sets `disabled` attribute, applies disabled styles |
| fullWidth | boolean | - | Sets `width: 100%` |
| gradient | MantineGradient | - | Gradient configuration used for `variant="gradient"` |
| justify | JustifyContent | - | Sets `justify-content` of `inner` element, can be used to change distribution of sections and label |
| leftSection | React.ReactNode | - | Content on the left side of the button label |
| loaderProps | LoaderProps | - | Props added to the `Loader` component (only visible when `loading` prop is set) |
| loading | boolean | - | If set, the `Loader` component is displayed over the button |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| rightSection | React.ReactNode | - | Content on the right side of the button label |
| size | ButtonSize | - | Controls button `height`, `font-size` and horizontal `padding` |
**Button.Group props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| borderWidth | string \| number | - | `border-width` of the child `Button` components. Numbers are converted to rem. |
| children | React.ReactNode | - | `Button` components |
| orientation | "horizontal" \| "vertical" | - | Orientation of the group |
**Button.GroupSection props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts text color based on background color for `filled` variant |
| gradient | MantineGradient | - | Gradient configuration used when `variant="gradient"` |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| size | ButtonSize | - | Controls section `height`, `font-size` and horizontal `padding` |
#### Styles API
Button component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Button selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Button-root | Root element |
| loader | .mantine-Button-loader | Loader component, displayed only when `loading` prop is set |
| inner | .mantine-Button-inner | Contains all other elements, child of the `root` element |
| section | .mantine-Button-section | Left and right sections of the button |
| label | .mantine-Button-label | Button children |
**Button CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --button-bg | Controls `background` |
| root | --button-bd | Control `border` |
| root | --button-hover | Controls `background` when hovered |
| root | --button-color | Control text `color` |
| root | --button-hover-color | Control text `color` when hovered |
| root | --button-radius | Controls `border-radius` |
| root | --button-height | Controls `height` of the button |
| root | --button-padding-x | Controls horizontal `padding` of the button |
| root | --button-fz | Controls `font-size` of the button |
| root | --button-justify | Controls `justify-content` of `inner` element |
**Button data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-disabled | `disabled` prop is set | - |
**Button.Group selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| group | .mantine-ButtonGroup-group | Root element |
**Button.Group CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| group | --button-border-width | `border-width` of child `Button` components |
**Button.Group data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| group | data-orientation | - | Value of `orientation` prop |
**Button.GroupSection selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| groupSection | .mantine-ButtonGroupSection-groupSection | Root element |
**Button.GroupSection CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| groupSection | --section-bg | Controls `background` |
| groupSection | --section-bd | Control `border` |
| groupSection | --section-color | Control text `color` |
| groupSection | --section-radius | Controls `border-radius` |
| groupSection | --section-height | Controls `height` of the section |
| groupSection | --section-padding-x | Controls horizontal `padding` of the section |
| groupSection | --section-fz | Controls `font-size` of the section |
--------------------------------------------------------------------------------
### Card
Package: @mantine/core
Import: import { Card } from '@mantine/core';
Description: Card with sections
## Usage
`Card` is a wrapper around the [Paper](https://alpha.mantine.dev/llms/core-paper.md) component with some additional styles and a `Card.Section`
component that allows you to split the card into sections. If you do not need sections, you can use the [Paper](https://alpha.mantine.dev/llms/core-paper.md) component instead.
```tsx
import { Card, Image, Text, Badge, Button, Group } from '@mantine/core';
function Demo() {
return (
Norway Fjord AdventuresOn Sale
With Fjord Tours you can explore more of the magical fjord landscapes with tours and
activities on and around the fjords of Norway
);
}
```
## Horizontal orientation
```tsx
import { Box, Card, Group, RingProgress, Text } from '@mantine/core';
const completed = 1887;
const total = 2334;
const stats = [
{ value: 447, label: 'Remaining' },
{ value: 76, label: 'In progress' },
];
function Demo() {
const items = stats.map((stat) => (
{stat.value}
{stat.label}
));
return (
{((completed / total) * 100).toFixed(0)}%
Completed
}
/>
Project tasks1887
Completed
{items}
);
}
```
## Polymorphic component
Card is a [polymorphic component](https://alpha.mantine.dev/llms/guides-polymorphic.md), you can change its root element:
```tsx
import { Card, Image, Text } from '@mantine/core';
function Demo() {
return (
You've won a million dollars in cash!
Please click anywhere on this card to claim your reward, this is not a fraud, trust us
);
}
```
## Card.Section
`Card.Section` is a special component that is used to remove Card padding from its children while other elements still have horizontal spacing.
`Card.Section` works in the following way:
* If the component is the first child in Card, then it has negative top, left and right margins
* If it is the last child in Card, then it has negative bottom, left and right margins
* If it is in the middle, then only the left and right margins will be negative
```tsx
import { Card, Text } from '@mantine/core';
function Demo() {
return (
{/* top, right, left margins are negative β -1 * theme.spacing.xl */}
First section
{/* Content that is not inside Card.Section will have theme.spacing.xl spacing on all sides relative to Card */}
Some other content
{/* right, left margins are negative β -1 * theme.spacing.xl */}
Middle section
{/* bottom, right, left margins are negative β -1 * theme.spacing.xl */}
Last section
);
}
```
Note that `Card` relies on mapping direct children and you cannot use fragments or other wrappers for `Card.Section`:
```tsx
import { Card } from '@mantine/core';
function Demo() {
return (
Won't work
<>
Won't work either
>
Works fine
);
}
```
## Polymorphic Card.Section
`Card.Section` is a [polymorphic component](https://alpha.mantine.dev/llms/guides-polymorphic.md), you can change its root element:
```tsx
import { Card, Image, Text, Badge, Button, Group } from '@mantine/core';
function Demo() {
return (
Norway Fjord AdventuresOn Sale
With Fjord Tours you can explore more of the magical fjord landscapes with tours and
activities on and around the fjords of Norway
);
}
```
## withBorder and inheritPadding props
* `withBorder` prop adds top and bottom borders to `Card.Section` depending on its position relative to other content and sections
* `inheritPadding` prop adds the same left and right padding to `Card.Section` as set in the `Card` component
```tsx
import { ActionIcon, Card, Group, Image, Menu, SimpleGrid, Text } from '@mantine/core';
import { DotsThreeIcon, EyeIcon, FileZipIcon, TrashIcon } from '@phosphor-icons/react';
const images = [
'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/images/bg-1.png',
'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/images/bg-2.png',
'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/images/bg-3.png',
];
function Demo() {
return (
Review pictures
200+ images uploaded
{' '}
since last visit, review them to select which one should be added to your gallery
{images.map((image) => (
))}
);
}
```
#### Props
**Card props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Card content |
| orientation | "horizontal" \| "vertical" | - | Card orientation |
| padding | MantineSpacing | - | Key of `theme.spacing` or any valid CSS value to set padding |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius, numbers are converted to rem |
| shadow | MantineShadow | - | Key of `theme.shadows` or any valid CSS value to set `box-shadow` |
| withBorder | boolean | - | Adds border to the card |
**Card.Section props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| inheritPadding | boolean | - | If set, the section inherits padding from the parent `Card` |
| withBorder | boolean | - | Adds border to the root element |
#### Styles API
Card component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Card selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Card-root | Root element |
| section | .mantine-Card-section | `Card.Section` root element |
**Card CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
**Card data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| section | data-first-section | `Card.Section` is the child of the `Card` | - |
| section | data-last-section | `Card.Section` is the last child of the `Card` | - |
| root | data-with-border | `withBorder` prop is set on `Card` component | - |
| section | data-with-border | `withBorder` prop is set on `Card.Section` component | - |
| section | data-inherit-padding | `inheritPadding` prop is set on `Card.Section` component | - |
--------------------------------------------------------------------------------
### Center
Package: @mantine/core
Import: import { Center } from '@mantine/core';
Description: Centers content vertically and horizontally
## Usage
```tsx
import { Center, Box } from '@mantine/core';
function Demo() {
return (
All elements inside Center are centered
);
}
```
## Inline
To use `Center` with inline elements, set the `inline` prop.
For example, you can center a link icon and label:
```tsx
import { Center, Anchor, Box } from '@mantine/core';
import { ArrowLeftIcon } from '@phosphor-icons/react';
function Demo() {
return (
Back to Mantine website
);
}
```
#### Props
**Center props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Content to center |
| inline | boolean | - | If set, `inline-flex` is used instead of `flex` |
#### Styles API
Center component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Center selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Center-root | Root element |
--------------------------------------------------------------------------------
### Checkbox
Package: @mantine/core
Import: import { Checkbox } from '@mantine/core';
Description: Capture boolean input from user
## Usage
```tsx
import { Checkbox } from '@mantine/core';
function Demo() {
return (
);
}
```
## Controlled state
Use `checked` and `onChange` props to control `Checkbox` state:
```tsx
import { useState } from 'react';
import { Checkbox } from '@mantine/core';
function Demo() {
const [checked, setChecked] = useState(false);
return (
setChecked(event.currentTarget.checked)}
/>
);
}
```
## Checkbox with @mantine/form
Example of using `Checkbox` with [@mantine/form](https://alpha.mantine.dev/llms/form-use-form.md):
```tsx
import { Button, Checkbox } from '@mantine/core';
import { isNotEmpty, useForm } from '@mantine/form';
function Demo() {
const form = useForm({
mode: 'uncontrolled',
initialValues: { terms: false },
validate: {
terms: isNotEmpty('You must accept terms and conditions'),
},
});
return (
);
}
```
## Checkbox with uncontrolled forms
`Checkbox` can be used with uncontrolled forms the same way as native `input[type="checkbox"]`.
Set the `name` attribute to include checkbox value in `FormData` object on form submission.
To control initial checked state in uncontrolled forms, use `defaultChecked` prop.
Example usage of uncontrolled `Checkbox` with `FormData`:
```tsx
import { Checkbox } from '@mantine/core';
function Demo() {
return (
);
}
```
## States
```tsx
import { Checkbox, Stack } from '@mantine/core';
function Demo() {
return (
{}} label="Default checkbox" />
{}} indeterminate label="Indeterminate checkbox" />
{}} label="Checked checkbox" />
{}} label="Outline checked checkbox" />
{}}
indeterminate
label="Outline indeterminate checkbox"
/>
{}} label="Disabled checked checkbox" />
);
}
```
## Error state
Use the `error` prop to display error message below the checkbox label.
If you want to apply error styles to checkbox without error message, user boolean `error` prop.
If you want to display error message without applying error styles, set `withErrorStyles={false}`.
```tsx
import { Checkbox, Stack } from '@mantine/core';
function Demo() {
return (
);
}
```
## Change icons
```tsx
import { Checkbox, CheckboxIconComponent } from '@mantine/core';
import { BiohazardIcon, RadioactiveIcon } from '@phosphor-icons/react';
const CheckboxIcon: CheckboxIconComponent = ({ indeterminate, ...others }) =>
indeterminate ? : ;
function Demo() {
return (
<>
>
);
}
```
## Change icon color
Use the `iconColor` prop to change the icon color. You can reference colors from `theme.colors` or use any valid CSS color:
```tsx
import { Checkbox } from '@mantine/core';
function Demo() {
return (
);
}
```
## Indeterminate state
`Checkbox` supports indeterminate state. When the `indeterminate` prop is set,
the `checked` prop is ignored (checkbox always has checked styles):
```tsx
import { useListState, randomId } from '@mantine/hooks';
import { Checkbox } from '@mantine/core';
const initialValues = [
{ label: 'Receive email notifications', checked: false, key: randomId() },
{ label: 'Receive sms notifications', checked: false, key: randomId() },
{ label: 'Receive push notifications', checked: false, key: randomId() },
];
export function IndeterminateCheckbox() {
const [values, handlers] = useListState(initialValues);
const allChecked = values.every((value) => value.checked);
const indeterminate = values.some((value) => value.checked) && !allChecked;
const items = values.map((value, index) => (
handlers.setItemProp(index, 'checked', event.currentTarget.checked)}
/>
));
return (
<>
handlers.setState((current) =>
current.map((value) => ({ ...value, checked: !allChecked }))
)
}
/>
{items}
>
);
}
```
## Label with link
```tsx
import { Checkbox, Anchor } from '@mantine/core';
function Demo() {
return (
I accept{' '}
terms and conditions
>
}
/>
);
}
```
## Checkbox with tooltip
You can change the target element to which the tooltip is attached with `refProp`:
* If `refProp` is not set, the tooltip is attached to the checkbox input
* If `refProp="rootRef"` is set, the tooltip is attached to the root element (contains label, input and other elements)
```tsx
import { Tooltip, Checkbox } from '@mantine/core';
function Demo() {
return (
<>
>
);
}
```
## Pointer cursor
By default, checkbox input and label have `cursor: default` (same as native `input[type="checkbox"]`).
To change the cursor to pointer, set `cursorType` on [theme](https://alpha.mantine.dev/llms/theming-theme-object.md):
```tsx
import { MantineProvider, createTheme, Checkbox } from '@mantine/core';
const theme = createTheme({
cursorType: 'pointer',
});
function Demo() {
return (
<>
>
);
}
```
```tsx
import { Checkbox, Stack } from '@mantine/core';
function Demo() {
return (
);
}
```
## Add custom sizes
You can add any number of custom sizes with [data-size](https://alpha.mantine.dev/llms/styles-data-attributes.md) attribute:
```tsx
// Demo.tsx
import { MantineProvider, Checkbox, createTheme } from '@mantine/core';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
Checkbox: Checkbox.extend({ classNames: classes }),
},
});
function Demo() {
return (
);
}
// Demo.module.css
.root {
--checkbox-size-xxl: 42px;
--checkbox-size-xxs: 14px;
&[data-size='xxl'] {
.label {
font-size: 22px;
line-height: 40px;
}
}
&[data-size='xxs'] {
.label {
font-size: 10px;
line-height: 14px;
}
}
}
```
## Wrapper props
Checkbox supports additional props that are passed to the wrapper element for more customization options.
## Checkbox.Group
`Checkbox.Group` manages the state of multiple checkboxes, it accepts `value` and `onChange`
props, which are used to control the state of checkboxes inside the group. The `value` prop should be an array of strings, where each string is the value of a checkbox.
The `onChange` prop should be a function that receives the new value as an array of strings.
```tsx
import { useState } from 'react';
import { Checkbox } from '@mantine/core';
function Demo() {
const [value, setValue] = useState([]);
return (
);
}
```
`Checkbox.Group` component supports all [Input.Wrapper](https://alpha.mantine.dev/llms/core-input.md#inputwrapper-component)
props.
```tsx
import { Checkbox, Group } from '@mantine/core';
function Demo() {
return (
);
}
```
## Checkbox.Group disabled
```tsx
import { Checkbox } from '@mantine/core';
function Demo() {
return (
);
}
```
## maxSelectedValues
Use `maxSelectedValues` prop to limit the number of selected values in `Checkbox.Group`.
When the limit is reached, the remaining checkboxes are disabled and cannot be selected.
```tsx
import { Checkbox, Group } from '@mantine/core';
function Demo() {
return (
);
}
```
## Checkbox.Group with @mantine/form
Example of using `Checkbox.Group` with [@mantine/form](https://alpha.mantine.dev/llms/form-use-form.md):
```tsx
import { Button, Checkbox, Group } from '@mantine/core';
import { hasLength, useForm } from '@mantine/form';
interface FormValues {
frameworks: string[];
}
function Demo() {
const form = useForm({
mode: 'uncontrolled',
initialValues: { frameworks: [] },
validate: {
frameworks: hasLength({ min: 1 }, 'Select at least one framework'),
},
});
return (
);
}
```
## Checkbox.Group with uncontrolled forms
`Checkbox.Group` can be used with uncontrolled forms, it renders a hidden input
which joins all checked values into a single string using `hiddenInputValuesSeparator` prop.
Props for usage with uncontrolled forms:
* `name` β name attribute passed to the hidden input
* `hiddenInputValuesSeparator` β string used to join checked values into a single string, `','` by default
* `hiddenInputProps` β additional props passed to the hidden input
```tsx
export function UncontrolledForm() {
return (
);
}
```
## Checkbox.Indicator
`Checkbox.Indicator` looks exactly the same as the `Checkbox` component, but it does not
have any semantic meaning, it's just a visual representation of checkbox state. You
can use it in any place where you need to display checkbox state without any interaction
related to the indicator. For example, it is useful in cards based on buttons, trees, etc.
Note that `Checkbox.Indicator` cannot be focused or selected with keyboard. It is not
accessible and should not be used as a replacement for the `Checkbox` component.
```tsx
import { Checkbox, Group } from '@mantine/core';
function Demo() {
return (
);
}
```
## Example: Table with row selection
```tsx
import { useState } from 'react';
import { Table, Checkbox } from '@mantine/core';
const elements = [
{ position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' },
{ position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' },
{ position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' },
{ position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' },
{ position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' },
];
function Demo() {
const [selectedRows, setSelectedRows] = useState([]);
const rows = elements.map((element) => (
setSelectedRows(
event.currentTarget.checked
? [...selectedRows, element.position]
: selectedRows.filter((position) => position !== element.position)
)
}
/>
{element.position}{element.name}{element.symbol}{element.mass}
));
return (
Element positionElement nameSymbolAtomic mass{rows}
);
}
```
## Example: Customize with Styles API
```tsx
// Demo.tsx
import { useState } from 'react';
import { Checkbox } from '@mantine/core';
import classes from './Demo.module.css';
function Demo() {
const [checked, setChecked] = useState(false);
return (
setChecked(event.currentTarget.checked)}
wrapperProps={{
onClick: () => setChecked((c) => !c),
}}
/>
);
}
// Demo.module.css
.root {
border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm);
border-radius: var(--mantine-radius-md);
font-weight: 600;
transition:
color 100ms ease,
background-color 100ms ease,
border-color 100ms ease;
cursor: pointer;
&[data-checked] {
background-color: var(--mantine-color-blue-filled);
border-color: var(--mantine-color-blue-filled);
color: var(--mantine-color-white);
}
& * {
pointer-events: none;
user-select: none;
}
}
```
## wrapperProps
Most of the `Checkbox` props are passed down to the `input` element.
If you want to pass props to the root element instead, use `wrapperProps` prop.
```tsx
import { Checkbox } from '@mantine/core';
function Demo() {
return (
);
}
```
## id attribute
By default, `Checkbox` generates a random `id` attribute for the input element
to associate it with the label. You can supply your own `id` attribute with `id` prop.
It will be used in `id` attribute of the input element and `htmlFor` attribute of the label element.
```tsx
import { Checkbox } from '@mantine/core';
function Demo() {
return ;
}
```
## Accessibility
Checkbox component is based on the native `input[type="checkbox"]` element, so it is accessible by default.
Set `aria-label` or `label` prop to make the checkbox accessible for screen readers:
```tsx
import { Checkbox } from '@mantine/core';
// Not ok, input is not labeled
function Bad() {
return ;
}
// Ok, input is labelled by aria-label
function GoodAriaLabel() {
return ;
}
// Ok, input is labelled by label element
function GoodLabel() {
return ;
}
```
#### Props
**Checkbox props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts icon color based on background color for `filled` variant |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color to set input background color in checked state |
| description | React.ReactNode | - | Description below the label |
| error | React.ReactNode | - | Error message below the label |
| icon | CheckboxIconComponent | - | Icon for checked or indeterminate state |
| iconColor | MantineColor | - | Key of `theme.colors` or any valid CSS color to set icon color. By default, depends on `theme.autoContrast`. |
| id | string | - | Unique input id |
| indeterminate | boolean | - | Indeterminate state of the checkbox. If set, `checked` prop is dismissed. |
| label | React.ReactNode | - | `label` associated with the checkbox |
| labelPosition | "left" \| "right" | - | Position of the label relative to the input |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| rootRef | Ref | - | Root element ref |
| size | MantineSize | - | Controls size of the component |
| withErrorStyles | boolean | - | If set, applies error styles to the checkbox when `error` prop is set |
| wrapperProps | React.ComponentProps<"div"> | - | Props passed down to the root element |
**Checkbox.Group props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
**Checkbox.Indicator props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts icon color based on background color for `filled` variant |
| checked | boolean | - | Determines whether the component should have checked styles |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color to set input background color in checked state |
| disabled | boolean | - | Indicates disabled state |
| icon | CheckboxIconComponent | - | Icon for checked or indeterminate state |
| iconColor | MantineColor | - | Key of `theme.colors` or any valid CSS color to set icon color, by default value depends on `theme.autoContrast` |
| indeterminate | boolean | - | Indeterminate state of the checkbox. If set, `checked` prop is ignored. |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| size | MantineSize | - | Controls size of the component |
**Checkbox.CardContext props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
**Checkbox.Card props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| checked | boolean | - | Controlled component value |
| defaultChecked | boolean | - | Uncontrolled component default value |
| onChange | (checked: boolean) => void | - | Called when value changes |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem |
| value | string | - | Value of the checkbox, used with `Checkbox.Group` |
| withBorder | boolean | - | Adds border to the root element |
#### Styles API
Checkbox component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Checkbox selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Checkbox-root | Root element |
| input | .mantine-Checkbox-input | Input element (`input[type="checkbox"]`) |
| icon | .mantine-Checkbox-icon | Checkbox icon, used to display checkmark and indeterminate state icon |
| inner | .mantine-Checkbox-inner | Wrapper for `icon` and `input` |
| body | .mantine-Checkbox-body | Input body, contains all other elements |
| labelWrapper | .mantine-Checkbox-labelWrapper | Contains `label`, `description` and `error` |
| label | .mantine-Checkbox-label | Label element |
| description | .mantine-Checkbox-description | Description displayed below the label |
| error | .mantine-Checkbox-error | Error message displayed below the label |
**Checkbox CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --checkbox-color | Controls checked checkbox `background-color` |
| root | --checkbox-radius | Controls checkbox `border-radius` |
| root | --checkbox-size | Controls checkbox `width` and `height` |
| root | --checkbox-icon-color | Controls checkbox icon `color` |
**Checkbox data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-checked | `checked` prop is set | - |
| input | data-error | `error` prop is set | - |
| input | data-indeterminate | `indeterminate` prop is set | - |
| inner | data-label-position | - | Value of `labelPosition` prop |
**Checkbox.Group selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-CheckboxGroup-root | Root element |
| label | .mantine-CheckboxGroup-label | Label element |
| required | .mantine-CheckboxGroup-required | Required asterisk element, rendered inside label |
| description | .mantine-CheckboxGroup-description | Description element |
| error | .mantine-CheckboxGroup-error | Error element |
**Checkbox.Indicator selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| indicator | .mantine-CheckboxIndicator-indicator | Root element |
| icon | .mantine-CheckboxIndicator-icon | Checkbox icon |
**Checkbox.Indicator CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| indicator | --checkbox-color | Controls checked checkbox `background-color` |
| indicator | --checkbox-radius | Controls checkbox `border-radius` |
| indicator | --checkbox-size | Controls checkbox `width` and `height` |
| indicator | --checkbox-icon-color | Controls checkbox icon `color` |
**Checkbox.Indicator data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| indicator | data-checked | `checked` prop is set | - |
| indicator | data-disabled | `disabled` prop is set | - |
**Checkbox.Card selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| card | .mantine-CheckboxCard-card | Root element |
**Checkbox.Card CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| card | --card-radius | Controls card `border-radius` |
**Checkbox.Card data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| card | data-checked | `checked` prop is set | - |
| card | data-with-border | `withBorder` prop is set | - |
--------------------------------------------------------------------------------
### Chip
Package: @mantine/core
Import: import { Chip } from '@mantine/core';
Description: Pick one or multiple values with inline controls
## Usage
```tsx
import { Chip } from '@mantine/core';
function Demo() {
return Awesome chip
}
```
## Controlled
```tsx
import { useState } from 'react';
import { Chip } from '@mantine/core';
function Demo() {
const [checked, setChecked] = useState(false);
return (
setChecked((v) => !v)}>
My chip
);
}
```
## Change checked icon
```tsx
import { Chip } from '@mantine/core';
import { XIcon } from '@phosphor-icons/react';
function Demo() {
return (
}
color="red"
variant="filled"
defaultChecked
>
Forbidden
);
}
```
## States
```tsx
function Demo() {
return (
<>
Outline default
Outline checked
Outline checked disabled
Light default
Light checked
Light checked disabled
Filled default
Filled checked
Filled checked disabled
>
);
}
```
## Chip with tooltip
To use `Chip` with [Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md) and other similar components, set `refProp="rootRef"`
on the [Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md) component:
```tsx
import { Tooltip, Chip } from '@mantine/core';
function Demo() {
return (
Chip with tooltip
);
}
```
## Wrapper props
Chip supports additional props that are passed to the wrapper element for more customization options.
## Chip.Group
The `Chip.Group` component manages the state of child Chip components.
Set the `multiple` prop to allow multiple chips to be selected at a time:
```tsx
import { Chip, Group } from '@mantine/core';
function Demo() {
return (
<>
Single chipCan be selectedAt a timeMultiple chipsCan be selectedAt a time
>
);
}
```
## Controlled Chip.Group
```tsx
import { useState } from 'react';
import { Chip } from '@mantine/core';
function Single() {
// string value when multiple is false (default)
const [value, setValue] = useState('react');
return (
ReactAngularSvelteVue
);
}
function Multiple() {
// array of strings value when multiple is true
const [value, setValue] = useState(['react']);
return (
ReactAngularSvelteVue
);
}
```
## Deselect radio chip
```tsx
import { useState } from 'react';
import { Chip, Group } from '@mantine/core';
function Demo() {
const [value, setValue] = useState('first');
const handleChipClick = (event: React.MouseEvent) => {
if (event.currentTarget.value === value) {
setValue(null);
}
};
return (
First
Second
Third
);
}
```
## Accessibility
`Chip` and `Chip.Group` components are accessible by default β they are built with native radio/checkbox inputs,
all keyboard events work the same as with native controls.
#### Props
**Chip props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts text color based on the chip background color for `filled` variant |
| checked | boolean | - | Controlled checked state |
| children | React.ReactNode | required | `label` element associated with the input |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color. |
| defaultChecked | boolean | - | Uncontrolled checked state initial value |
| icon | React.ReactNode | - | Any element or component to replace the default icon |
| id | string | - | Unique input id, generated randomly if not provided |
| onChange | (checked: boolean) => void | - | Calls when checked state changes |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| rootRef | Ref | - | Assigns ref of the root element |
| size | MantineSize | - | Controls various properties related to the component size |
| type | "checkbox" \| "radio" | - | Chip input type |
| wrapperProps | React.ComponentProps<"div"> | - | Props passed down to the root element |
**Chip.Group props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | `Chip` components and any other elements |
| defaultValue | string \| Value[] \| null | - | Uncontrolled component initial value |
| multiple | boolean | - | If set, multiple values can be selected |
| onChange | (value: Multiple extends true ? Value[] : Value) => void | - | Called when value changes. If `multiple` prop is set, called with an array of selected values. If not, called with a string value of selected chip. |
| value | string \| Value[] \| null | - | Controlled component value |
**Chip.GroupContext props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
#### Styles API
Chip component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Chip selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Chip-root | Root element |
| checkIcon | .mantine-Chip-checkIcon | Check icon, visible when checked prop is true |
| iconWrapper | .mantine-Chip-iconWrapper | Wraps `checkIcon` for alignment |
| input | .mantine-Chip-input | Input element, hidden by default |
| label | .mantine-Chip-label | Input label, used as a chip body |
**Chip CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --chip-fz | Controls `font-size` |
| root | --chip-size | Controls `height` |
| root | --chip-icon-size | Controls width and height of the icon |
| root | --chip-padding | Controls horizontal padding when chip is not checked |
| root | --chip-checked-padding | Controls horizontal padding when chip is checked |
| root | --chip-radius | Controls `border-radius` |
| root | --chip-bg | Controls `background-color` when chip is checked |
| root | --chip-hover | Controls `background-color` when chip is checked and hovered |
| root | --chip-color | Controls `color` when chip is checked |
| root | --chip-bd | Controls border when chip is checked |
| root | --chip-spacing | Controls spacing between check icon and label |
**Chip data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| label | data-checked | Chip is checked | - |
| label | data-disabled | `disabled` prop is set | - |
--------------------------------------------------------------------------------
### CloseButton
Package: @mantine/core
Import: import { CloseButton } from '@mantine/core';
Description: Button with close icon
## Usage
`CloseButton` renders a button with an `X` icon inside. It is used in other Mantine components like [Drawer](https://alpha.mantine.dev/llms/core-drawer.md) or [Modal](https://alpha.mantine.dev/llms/core-modal.md).
```tsx
import { CloseButton } from '@mantine/core';
function Demo() {
return ;
}
```
## Change icon
You can change the icon by passing any react node to the `icon` prop.
It is useful when `CloseButton` is used as a part of other components,
for example, in [Drawer](https://alpha.mantine.dev/llms/core-drawer.md) or [Modal](https://alpha.mantine.dev/llms/core-modal.md).
Note that if you use the `icon` prop, the `iconSize` prop is ignored β
you will have to set the icon size manually.
```tsx
import { XCircleIcon } from '@phosphor-icons/react';
import { CloseButton } from '@mantine/core';
function Demo() {
return } />;
}
```
## Accessibility
To make the `CloseButton` accessible for screen readers, you need to either set `aria-label` or
use the [VisuallyHidden](https://alpha.mantine.dev/llms/core-visually-hidden.md) component:
```tsx
import { CloseButton, VisuallyHidden } from '@mantine/core';
function Demo() {
return (
<>
Close modal
>
);
}
```
#### Props
**CloseButton props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Content rendered inside the button. For example `VisuallyHidden` with label for screen readers. |
| disabled | boolean | - | Sets `disabled` attribute, assigns disabled styles |
| icon | React.ReactNode | - | React node to replace the default close icon. If set, `iconSize` prop is ignored. |
| iconSize | string \| number | - | `X` icon `width` and `height` |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius. Numbers are converted to rem. |
| size | MantineSize \| number | - | Controls width and height of the button. Numbers are converted to rem. |
#### Styles API
CloseButton component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**CloseButton selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-CloseButton-root | Root element |
**CloseButton CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --cb-icon-size | Controls `width` of the `X` icon |
| root | --cb-radius | Controls `border-radius` of the button |
| root | --cb-size | Controls `width` and `height` of the button |
--------------------------------------------------------------------------------
### Code
Package: @mantine/core
Import: import { Code } from '@mantine/core';
Description: Inline and block code
## Usage
By default, the Code component renders an inline `code` html element:
```tsx
import { Code } from '@mantine/core';
function Demo() {
return React.createElement();
}
```
## Block code
To render code in a `pre` element, pass the `block` prop to the Code component:
```tsx
import { Code } from '@mantine/core';
const codeForPreviousDemo = `import { Code } from '@mantine/core';
function Demo() {
return React.createElement();
}`;
function Demo() {
return {codeForPreviousDemo};
}
```
## Custom color
By default, the code color is gray. You can change it to any valid CSS color or to one
of the [theme.colors](https://alpha.mantine.dev/llms/theming-colors.md):
```tsx
import { Code, Group } from '@mantine/core';
function Demo() {
return (
React.createElement()
React.createElement()
);
}
```
#### Props
**Code props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| block | boolean | - | If set, code is rendered in `pre` |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color, controls `background-color` of the code. By default, calculated based on the color scheme. |
**Code.Highlight props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| background | MantineColor | - | Controls background color of the code. By default, the value depends on color scheme. |
| code | string | required | Code to highlight |
| codeColorScheme | (string & {}) \| "dark" \| "light" | - | Set to use dark or light color scheme. When using shiki adapter, you can use loaded themes here |
| collapseCodeLabel | string | - | Label for collapse button |
| controls | ReactNode[] | - | Extra controls to display in the controls list |
| copiedLabel | string | - | Label for copy button in copied state |
| copyLabel | string | - | Label for copy button in default state |
| defaultExpanded | boolean | - | Uncontrolled expanded default state |
| expandCodeLabel | string | - | Label for expand button |
| expanded | boolean | - | Controlled expanded state |
| language | string | - | Language of the code, used for syntax highlighting |
| maxCollapsedHeight | string \| number | - | Max height of collapsed state |
| onExpandedChange | (expanded: boolean) => void | - | Called when expanded state changes |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius |
| withBorder | boolean | - | Adds border to the root element |
| withCopyButton | boolean | - | Determines whether the copy button should be displayed |
| withExpandButton | boolean | - | Determines whether the expand/collapse button should be displayed |
**Code.HighlightTabs props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| activeTab | number | - | Index of controlled active tab state |
| background | MantineColor | - | Controls background color of the code. By default, the value depends on color scheme. |
| code | CodeHighlightTabsCode[] | required | Code to highlight with meta data (file name and icon) |
| codeColorScheme | (string & {}) \| "dark" \| "light" | - | Set to use dark or light color scheme. When using shiki adapter, you can use loaded themes here |
| collapseCodeLabel | string | - | Label for collapse button |
| controls | ReactNode[] | - | Extra controls to display in the controls list |
| copiedLabel | string | - | Label for copy button in copied state |
| copyLabel | string | - | Label for copy button in default state |
| defaultActiveTab | number | - | Default active tab index |
| defaultExpanded | boolean | - | Uncontrolled expanded default state |
| expandCodeLabel | string | - | Label for expand button |
| expanded | boolean | - | Controlled expanded state |
| getFileIcon | (fileName: string) => ReactNode | - | Function that returns icon based on file name |
| maxCollapsedHeight | string \| number | - | Max height of collapsed state |
| onExpandedChange | (expanded: boolean) => void | - | Called when expanded state changes |
| onTabChange | (tab: number) => void | - | Called when tab changes |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius |
| withBorder | boolean | - | Adds border to the root element |
| withCopyButton | boolean | - | Determines whether the copy button should be displayed |
| withExpandButton | boolean | - | Determines whether the expand/collapse button should be displayed |
#### Styles API
Code component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Code selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Code-root | Root element |
**Code CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --code-bg | Controls `background-color` |
**Code data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-block | `block` prop is set | - |
**Codehighlight selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| codeHighlight | .mantine-Codehighlight-codeHighlight | Root element |
| showCodeButton | .mantine-Codehighlight-showCodeButton | Button that reveals full code when it is collapsed |
| pre | .mantine-Codehighlight-pre | Pre element, contains code element |
| code | .mantine-Codehighlight-code | Code element |
| control | .mantine-Codehighlight-control | Control button, copy/collapse, custom controls |
| controlTooltip | .mantine-Codehighlight-controlTooltip | Root element of control tooltip |
| controls | .mantine-Codehighlight-controls | A wrapper around controls |
| scrollarea | .mantine-Codehighlight-scrollarea | Scroll area, contains code |
**Codehighlight CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| codeHighlight | --ch-background | Background color |
| codeHighlight | --ch-max-height | Max height of code block in collapsed state |
| codeHighlight | --ch-radius | Border radius |
**Codehighlighttabs selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| codeHighlight | .mantine-Codehighlighttabs-codeHighlight | Root element of inner CodeHighlight component |
| showCodeButton | .mantine-Codehighlighttabs-showCodeButton | Button that reveals full code when it is collapsed |
| pre | .mantine-Codehighlighttabs-pre | Pre element, contains code element |
| code | .mantine-Codehighlighttabs-code | Code element |
| control | .mantine-Codehighlighttabs-control | Control button, copy/collapse, custom controls |
| controlTooltip | .mantine-Codehighlighttabs-controlTooltip | Root element of control tooltip |
| controls | .mantine-Codehighlighttabs-controls | A wrapper around controls |
| scrollarea | .mantine-Codehighlighttabs-scrollarea | Scroll area, contains code |
| root | .mantine-Codehighlighttabs-root | Root element |
| filesScrollarea | .mantine-Codehighlighttabs-filesScrollarea | Scrollarea with files list |
| files | .mantine-Codehighlighttabs-files | Files names list |
| file | .mantine-Codehighlighttabs-file | File name |
| fileIcon | .mantine-Codehighlighttabs-fileIcon | File icon |
--------------------------------------------------------------------------------
### Collapse
Package: @mantine/core
Import: import { Collapse } from '@mantine/core';
Description: Animate presence with slide down/up transition
## Usage
```tsx
import { Button, Group, Text, Collapse, Box } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [expanded, { toggle }] = useDisclosure(false);
return (
{/* ... content */}
);
}
```
## Horizontal orientation
```tsx
import { Button, Collapse, Stack, Typography } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [expanded, handlers] = useDisclosure(false);
return (
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
);
}
```
## Change transition
Set the following props to control the transition:
* `transitionDuration` β duration in ms
* `transitionTimingFunction` β timing function (ease, linear, etc.), defaults to `ease`
* `onTransitionEnd` β called when transition ends (both open and close)
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Button, Group, Text, Collapse, Box } from '@mantine/core';
function Demo() {
const [expanded, { toggle }] = useDisclosure(false);
return (
{/* ...content */}
);
}
```
## Example: nested Collapse components
```tsx
function Demo() {
return (
This collapse contains another collapse
{lorem}
This collapse is inside another collapse
{lorem}
);
}
```
## use-collapse hook
[use-collapse](https://alpha.mantine.dev/llms/hooks-use-collapse.md) is the hook version of the `Collapse` component.
It allows more flexible usage and control over the collapse behavior.
```tsx
import { Button, Typography } from '@mantine/core';
import { useCollapse, useDisclosure } from '@mantine/hooks';
function Demo() {
const [expanded, handlers] = useDisclosure(false);
const getCollapseProps = useCollapse({ expanded });
return (
<>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
);
}
```
## Usage
`Container` centers content and limits its `max-width` to the value specified in the `size` prop.
Note that the `size` prop does not make `max-width` responsive. For example,
when it is set to `lg` it will always be `lg` regardless of screen size.
```tsx
import { Container } from '@mantine/core';
function Demo() {
const demoProps = {
bg: 'var(--mantine-color-blue-light)',
h: 50,
mt: 'md',
};
return (
<>
Default Container
xs Container
480px Container without padding
>
);
}
```
## Fluid
Set the `fluid` prop to make the container fluid. It will take 100% of available width,
which is the same as setting `size="100%"`.
```tsx
import { Container } from '@mantine/core';
function Demo() {
return (
Fluid container has 100% max-width
);
}
```
## Customize sizes
You can customize existing `Container` sizes and add new ones with [CSS variables](https://alpha.mantine.dev/llms/styles-styles-api.md)
on [theme](https://alpha.mantine.dev/llms/theming-theme-object.md):
```tsx
import { Container, MantineProvider, createTheme, rem } from '@mantine/core';
const CONTAINER_SIZES: Record = {
xxs: 300,
xs: 400,
sm: 500,
md: 600,
lg: 700,
xl: 800,
xxl: 900,
};
const theme = createTheme({
components: {
Container: Container.extend({
vars: (_, { size, fluid }) => ({
root: {
'--container-size': fluid
? '100%'
: size !== undefined && size in CONTAINER_SIZES
? rem(CONTAINER_SIZES[size])
: rem(size),
},
}),
}),
},
});
function Demo() {
return (
Container with custom size
);
}
```
## Responsive max-width
To make `Container` `max-width` responsive, use [Styles API](https://alpha.mantine.dev/llms/styles-styles-api.md) to set
`classNames`. For example, you can add a `responsive` size that will make the `Container`
`max-width` different depending on screen size:
```tsx
// Demo.tsx
import cx from 'clsx';
import { MantineProvider, Container, createTheme } from '@mantine/core';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
Container: Container.extend({
classNames: (_, { size }) => ({
root: cx({ [classes.responsiveContainer]: size === 'responsive' }),
}),
}),
},
});
function Demo() {
return (
Container with responsive size
);
}
// Demo.module.css
.responsiveContainer {
max-width: 300px;
@media (min-width: em(400px)) {
max-width: 400px;
}
@media (min-width: em(600px)) {
max-width: 600px;
}
}
```
#### Props
**Container props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| fluid | boolean | - | If set, the container takes 100% width of its parent and `size` prop is ignored. |
| size | MantineSize \| number | - | `max-width` of the container, value is not responsive β it is the same for all screen sizes. Numbers are converted to rem. Ignored when `fluid` prop is set. |
| strategy | "block" \| "grid" | - | Centering strategy |
#### Styles API
Container component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Container selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Container-root | Root element |
**Container CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --container-size | Controls container `max-width` |
--------------------------------------------------------------------------------
### CopyButton
Package: @mantine/core
Import: import { CopyButton } from '@mantine/core';
Description: Copies given text to clipboard
## Usage
`CopyButton` is based on the [use-clipboard](https://alpha.mantine.dev/llms/hooks-use-clipboard.md) hook.
Its children is a function that receives an object with the following properties:
* `copied` β boolean value that indicates that a given value was recently copied to the clipboard, it resets after a given timeout (defaults to 500ms)
* `copy` β function that should be called to copy the given value to the clipboard
```tsx
import { CopyButton, Button } from '@mantine/core';
function Demo() {
return (
{({ copied, copy }) => (
)}
);
}
```
## Security
Due to security reasons, the `CopyButton` component will not work in iframes and may not work with local files opened with the `file://` protocol
(the component will work fine with local websites that are using the `http://` protocol). You can learn more about `navigator.clipboard` [here](https://web.dev/async-clipboard/).
## Timeout
You can provide a custom `copied` reset `timeout`:
```tsx
import { ActionIcon, CopyButton, Tooltip } from '@mantine/core';
import { CopyIcon, CheckIcon } from '@phosphor-icons/react';
function Demo() {
return (
{({ copied, copy }) => (
{copied ? : }
)}
);
}
```
## Server components
CopyButton is not compatible with React Server Components as it uses useEffect and other client-side features. You can use it in client components only.
#### Props
**CopyButton props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | (payload: { copied: boolean; copy: () => void; }) => ReactNode | required | Children callback, provides current status and copy function as an argument |
| timeout | number | - | Copied status timeout in ms |
| value | string | required | Value that is copied to the clipboard when the button is clicked |
--------------------------------------------------------------------------------
### Dialog
Package: @mantine/core
Import: import { Dialog } from '@mantine/core';
Description: Display a fixed overlay dialog at any side of the screen
## Usage
`Dialog` is a simplified version of the [Modal](https://alpha.mantine.dev/llms/core-modal.md) component.
It does not include most of the accessibility and usability [Modal](https://alpha.mantine.dev/llms/core-modal.md) features:
* Focus trap is not available
* Does not close on click outside
* Does not have an overlay
Use `Dialog` to attract attention with non-important information or actions.
For example, you can create an email subscription form:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Dialog, Group, Button, TextInput, Text } from '@mantine/core';
function Demo() {
const [opened, { toggle, close }] = useDisclosure(false);
return (
<>
>
);
}
```
## Change position
`Dialog` is rendered in [Portal](https://alpha.mantine.dev/llms/core-portal.md) and has a fixed position. Set the `position` prop to control the dialog's position:
```tsx
import { Dialog } from '@mantine/core';
function Demo() {
return (
<>
>
);
}
```
## Accessibility
`Dialog` is not accessible and most likely will not be announced by screen readers.
Make sure you do not put any important information in it. In most cases it would be better
to select [Modal](https://alpha.mantine.dev/llms/core-modal.md), [Drawer](https://alpha.mantine.dev/llms/core-drawer.md) or [Notifications](https://alpha.mantine.dev/llms/x-notifications.md).
#### Props
**Dialog props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Dialog content |
| keepMounted | boolean | - | If set, the component uses `display: none` to hide the root element instead of removing the DOM node |
| onClose | () => void | - | Called on close button click |
| opened | boolean | required | Opened state |
| portalProps | BasePortalProps | - | Props passed down to the `Portal` component. Ignored when `withinPortal` is `false`. |
| position | AffixPosition | - | Affix position on screen |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius, numbers are converted to rem |
| shadow | MantineShadow | - | Key of `theme.shadows` or any valid CSS value to set `box-shadow` |
| size | MantineSize \| number | - | Controls `width` of the dialog |
| transitionProps | TransitionProps | - | Props passed down to the underlying `Transition` component |
| withBorder | boolean | - | Adds border to the root element |
| withCloseButton | boolean | - | If set, displays the close button |
| withinPortal | boolean | - | Determines whether the component is rendered within `Portal` |
| zIndex | React.CSSProperties["zIndex"] | - | Root element `z-index` property |
#### Styles API
Dialog component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Dialog selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Dialog-root | Root element |
| closeButton | .mantine-Dialog-closeButton | Close button |
**Dialog CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --dialog-size | Controls `width` of the dialog |
--------------------------------------------------------------------------------
### Divider
Package: @mantine/core
Import: import { Divider } from '@mantine/core';
Description: Horizontal line with optional label or vertical divider
## Usage
```tsx
import { Text, Divider } from '@mantine/core';
function Demo() {
return (
<>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, officiis! Fugit minus ea,
perferendis eum consectetur quae vitae. Aliquid, quam reprehenderit? Maiores sed pariatur
aliquid commodi atque sunt officiis natus?
>
);
}
```
## Variants
```tsx
import { Divider } from '@mantine/core';
function Demo() {
return (
<>
>
);
}
```
## With label
```tsx
import { Divider, Box, Anchor } from '@mantine/core';
import { MagnifyingGlassIcon } from '@phosphor-icons/react';
function Demo() {
return (
<>
Search results
>
}
/>
Link label
}
/>
>
);
}
```
## Sizes
```tsx
import { Divider } from '@mantine/core';
function Demo() {
return (
<>
>
);
}
```
## Vertical orientation
```tsx
import { Divider, Group, Text } from '@mantine/core';
function Demo() {
return (
LabelLabelLabelLabelLabelLabel
);
}
```
#### Props
**Divider props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color value |
| label | React.ReactNode | - | Divider label, visible only with `orientation="horizontal"` |
| labelPosition | "center" \| "left" \| "right" | - | Label position |
| orientation | "horizontal" \| "vertical" | - | Divider orientation |
| size | MantineSize \| number | - | Controls width/height (depends on orientation) |
#### Styles API
Divider component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Divider selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Divider-root | Root element |
| label | .mantine-Divider-label | Label element |
**Divider CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --divider-border-style | Controls `border-style` |
| root | --divider-color | Controls `border-color` |
| root | --divider-size | Controls `border-width` |
**Divider data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-with-label | `label` prop is truthy | - |
| root | data-orientation | - | Value of `orientation` prop |
| label | data-position | - | Value of `labelPosition` prop |
--------------------------------------------------------------------------------
### Drawer
Package: @mantine/core
Import: import { Drawer } from '@mantine/core';
Description: Display overlay area at any side of the screen
## Usage
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Drawer content */}
>
);
}
```
## Position
Drawer can be placed on `left` (default), `top`, `right` and `bottom`. Control the drawer position with the `position` prop,
for example ``.
```tsx
function Demo() {
const [opened, setOpened] = useState(false);
const [position, setPosition] = useState<'top' | 'left' | 'right' | 'bottom'>('top');
const open = (p: typeof position) => {
setPosition(p);
setOpened(true);
};
return (
<>
setOpened(false)}
padding="md"
position={position}
withCloseButton={false}
>
Press escape to close the drawer
>
);
}
```
## Offset
Set the `offset` prop to change the drawer offset from the edge of the viewport:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Drawer content */}
>
);
}
```
## Customize overlay
`Drawer` uses the [Overlay](https://alpha.mantine.dev/llms/core-overlay.md) component. You can set any props that [Overlay](https://alpha.mantine.dev/llms/core-overlay.md)
supports with `overlayProps`:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Drawer content */}
>
);
}
```
## Sizes
You can change the drawer width/height (depends on `position`) by setting the `size` prop to a predefined size or any valid width,
for example, `size="55%"` or `size={200}`:
```tsx
import { Drawer } from '@mantine/core';
function Demo() {
return (
{}}>
{/* Drawer content */}
);
}
```
```tsx
function Demo() {
const [opened, setOpened] = useState(false);
const [size, setSize] = useState('top');
const open = (s: typeof size) => {
setSize(s);
setOpened(true);
};
const controls = (['xs', 'sm', 'md', 'lg', 'xl', '100%', '40rem', '25%'] as const).map((s) => (
));
return (
<>
setOpened(false)}
padding="md"
size={size}
withCloseButton={false}
>
Press escape to close the drawer
{controls}
>
);
}
```
## Remove header
To remove the header, set `withCloseButton={false}`
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
Drawer without header, press escape or click on overlay to close
>
);
}
```
## Drawer with scroll
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
const content = Array(100)
.fill(0)
.map((_, index) =>
Drawer with scroll
);
return (
<>
{content}
>
);
}
```
## Usage with ScrollArea
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button, ScrollArea } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
const content = Array(100)
.fill(0)
.map((_, index) =>
Drawer with scroll
);
return (
<>
{content}
>
);
}
```
## Change transition
`Drawer` is built with the [Transition](https://alpha.mantine.dev/llms/core-transition.md) component. Use the `transitionProps`
prop to customize any [Transition](https://alpha.mantine.dev/llms/core-transition.md) properties:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Drawer content */}
>
);
}
```
## onExitTransitionEnd and onEnterTransitionEnd
The `onExitTransitionEnd` and `onEnterTransitionEnd` props can be used to run code after
the exit/enter transition is finished. For example, this is useful when you want to clear
data after the drawer is closed:
```tsx
import { useState } from 'react';
import { Button, Group, Drawer } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [firstOpened, firstHandlers] = useDisclosure(false);
const [secondOpened, secondHandlers] = useDisclosure(false);
const [drawerData, setDrawerData] = useState({
title: '',
message: '',
});
return (
<>
{
firstHandlers.close();
setDrawerData({ title: '', message: '' });
}}
title={drawerData.title}
>
{drawerData.message}
setDrawerData({ title: '', message: '' })}
title={drawerData.title}
>
{drawerData.message}
>
);
}
```
## Initial focus
`Drawer` uses [FocusTrap](https://alpha.mantine.dev/llms/core-focus-trap.md) to trap focus. Add the `data-autofocus`
attribute to the element that should receive initial focus.
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button, TextInput } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
>
);
}
```
If you do not want to focus any elements when the drawer is opened, use the `FocusTrap.InitialFocus`
component to create a visually hidden element that will receive initial focus:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button, TextInput, FocusTrap } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
>
);
}
```
If you do not add the `data-autofocus` attribute and do not use `FocusTrap.InitialFocus`,
the drawer will focus the first focusable element inside it which is usually the close button.
## Control behavior
The following props can be used to control `Drawer` behavior.
In most cases it is not recommended to turn these features off β
it will make the component less accessible.
* `trapFocus` β determines whether focus should be trapped inside drawer
* `closeOnEscape` β determines whether the drawer should be closed when `Escape` key is pressed
* `closeOnClickOutside` β determines whether the drawer should be closed when user clicks on the overlay
* `returnFocus` β determines whether focus should be returned to the element that was focused before the drawer was opened
## react-remove-scroll settings
`Drawer` uses [react-remove-scroll](https://github.com/theKashey/react-remove-scroll)
package to lock scroll. You can pass props down to the `RemoveScroll` component
with `removeScrollProps`:
```tsx
import { Drawer } from '@mantine/core';
function Demo() {
return (
{}}
>
{/* Drawer content */}
);
}
```
## Change close icon
Use `closeButtonProps` to customize close button:
```tsx
import { XCircleIcon } from '@phosphor-icons/react';
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
,
}}
>
{/* Drawer content */}
>
);
}
```
## Compound components
You can use the following compound components to have full control over the `Drawer` rendering:
* `Drawer.Root` β context provider
* `Drawer.Overlay` β render [Overlay](https://alpha.mantine.dev/llms/core-overlay.md)
* `Drawer.Content` β main drawer element, should include all drawer content
* `Drawer.Header` β sticky header, usually contains `Drawer.Title` and `Drawer.CloseButton`
* `Drawer.Title` β `h2` element, `aria-labelledby` of `Drawer.Content` is pointing to this element, usually is rendered inside `Drawer.Header`
* `Drawer.CloseButton` β close button, usually rendered inside `Drawer.Header`
* `Drawer.Body` β a place for main content, `aria-describedby` of `Drawer.Content` is pointing to this element
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
Drawer titleDrawer content
>
);
}
```
## Drawer.Stack
Use `Drawer.Stack` component to render multiple drawers at the same time.
`Drawer.Stack` keeps track of opened drawers, manages z-index values, focus trapping
and `closeOnEscape` behavior. `Drawer.Stack` is designed to be used with `useDrawersStack` hook.
Differences from using multiple `Drawer` components:
* `Drawer.Stack` manages z-index values β drawers that are opened later will always have higher z-index value disregarding their order in the DOM
* `Drawer.Stack` disables focus trap and `Escape` key handling for all drawers except the one that is currently opened
* Drawers that are not currently opened are present in the DOM but are hidden with `opacity: 0` and `pointer-events: none`
* Only one overlay is rendered at a time
```tsx
import { Button, Group, Drawer, useDrawersStack } from '@mantine/core';
function Demo() {
const stack = useDrawersStack(['delete-page', 'confirm-action', 'really-confirm-action']);
return (
<>
Are you sure you want to delete this page? This action cannot be undone.
Are you sure you want to perform this action? This action cannot be undone. If you are
sure, press confirm button below.
Jokes aside. You have confirmed this action. This is your last chance to cancel it. After
you press confirm button below, action will be performed and cannot be undone. For real
this time. Are you sure you want to proceed?
>
);
}
```
Note that `Drawer.Stack` can only be used with `Drawer` component. Components built with `Drawer.Root`
and other compound components are not compatible with `Drawer.Stack`.
## useDrawersStack hook
`useDrawersStack` hook provides an easy way to control multiple drawers at the same time.
It accepts an array of unique drawers ids and returns an object with the following properties:
```tsx
interface UseDrawersStackReturnType {
// Current opened state of each drawer
state: Record;
// Opens drawer with the given id
open: (id: T) => void;
// Closes drawer with the given id
close: (id: T) => void;
// Toggles drawer with the given id
toggle: (id: T) => void;
// Closes all drawers within the stack
closeAll: () => void;
// Returns props for drawer with the given id
register: (id: T) => {
opened: boolean;
onClose: () => void;
stackId: T;
};
}
```
Example of using `useDrawersStack` with `Drawer` component:
```tsx
import { Drawer, useDrawersStack } from '@mantine/core';
function Demo() {
const stack = useDrawersStack(['first', 'second']);
return (
<>
FirstSecond
>
);
}
```
## Fixed elements offset
`Drawer` component uses [react-remove-scroll](https://github.com/theKashey/react-remove-scroll)
package to lock scroll. To properly size these `elements` add a `className` to them ([documentation](https://github.com/theKashey/react-remove-scroll#positionfixed-elements)):
```tsx
import { RemoveScroll } from '@mantine/core';
function Demo() {
return (
<>
width: 100%
right: 0
>
);
}
```
## Accessibility
`Drawer` component follows [WAI-ARIA recommendations](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/dialog) on accessibility.
Set `title` props to make component accessible, will add `aria-labelledby` to the content element:
```tsx
import { Drawer } from '@mantine/core';
function Demo() {
return {}} />;
}
```
To set close button `aria-label` use `closeButtonProps`:
```tsx
import { Drawer } from '@mantine/core';
function Demo() {
return (
{}}
/>
);
}
```
#### Props
**Drawer props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Drawer content |
| closeButtonProps | ModalBaseCloseButtonProps | - | Props passed down to the close button |
| closeOnClickOutside | boolean | - | If set, the modal/drawer is closed when user clicks on the overlay |
| closeOnEscape | boolean | - | If set, `onClose` is called when user presses the escape key |
| id | string | - | Id used to connect modal/drawer with body and title |
| keepMounted | boolean | - | If set modal/drawer is not unmounted from the DOM when hidden. `display: none` styles are applied instead. |
| lockScroll | boolean | - | If set, scroll is locked when `opened={true}` |
| offset | string \| number | - | Drawer container offset from the viewport end |
| onClose | () => void | required | Called when modal/drawer is closed |
| onEnterTransitionEnd | () => void | - | Called when enter transition ends |
| onExitTransitionEnd | () => void | - | Called when exit transition ends |
| opened | boolean | required | Controls opened state |
| overlayProps | ModalBaseOverlayProps | - | Props passed down to the `Overlay` component, can be used to configure opacity, `background-color`, styles and other properties |
| padding | MantineSpacing | - | Key of `theme.spacing` or any valid CSS value to set content, header and footer padding |
| portalProps | BasePortalProps | - | Props passed down to the Portal component when `withinPortal` is set |
| position | DrawerPosition | - | Side of the screen on which drawer will be opened |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem |
| removeScrollProps | RemoveScrollProps | - | Props passed down to react-remove-scroll, can be used to customize scroll lock behavior |
| returnFocus | boolean | - | If set, focus is returned to the last active element when `onClose` is called |
| scrollAreaComponent | ScrollAreaComponent | - | Scroll area component |
| shadow | MantineShadow | - | Key of `theme.shadows` or any valid CSS box-shadow value |
| size | MantineSize \| number | - | Controls width of the content area |
| stackId | string | - | Id of the drawer in the `Drawer.Stack` |
| title | React.ReactNode | - | Drawer title |
| transitionProps | TransitionProps | - | Props added to the `Transition` component that used to animate overlay and body, use to configure duration and animation type, `{ duration: 200, transition: 'fade-down' }` by default |
| trapFocus | boolean | - | If set, focus is trapped within the modal/drawer |
| withCloseButton | boolean | - | If set, the close button is displayed |
| withOverlay | boolean | - | If set, the overlay is displayed |
| withinPortal | boolean | - | If set, the component is rendered inside `Portal` |
| zIndex | string \| number | - | `z-index` CSS property of the root element |
#### Styles API
Drawer component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Drawer selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Drawer-root | Root element |
| inner | .mantine-Drawer-inner | Element used to center modal, has fixed position, takes entire screen |
| content | .mantine-Drawer-content | `Drawer.Content` root element |
| header | .mantine-Drawer-header | Contains title and close button |
| overlay | .mantine-Drawer-overlay | Overlay displayed under the `Drawer.Content` |
| title | .mantine-Drawer-title | Drawer title (h2 tag), displayed in the header |
| body | .mantine-Drawer-body | Drawer body, displayed after header |
| close | .mantine-Drawer-close | Close button |
**Drawer CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --drawer-offset | Controls `margin` of `Drawer.Content` |
| root | --drawer-size | Controls `width` of `Drawer.Content` |
| root | --drawer-flex | Controls `flex` property of `Drawer.Content` |
| root | --drawer-align | Controls `align-items` property of `Drawer.Content` |
| root | --drawer-justify | Controls `justify-content` property of `Drawer.Content` |
| root | --drawer-height | Controls `height` property of `Drawer.Content` |
--------------------------------------------------------------------------------
### Fieldset
Package: @mantine/core
Import: import { Fieldset } from '@mantine/core';
Description: Group related elements in a form
## Usage
```tsx
import { Fieldset, TextInput } from '@mantine/core';
function Demo() {
return (
);
}
```
## Disabled
`disabled` prop disables all inputs and buttons inside the fieldset:
```tsx
import { Fieldset, TextInput, Button, Group } from '@mantine/core';
function Demo() {
return (
);
}
```
#### Props
**Fieldset props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| legend | React.ReactNode | - | Fieldset legend |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
#### Styles API
Fieldset component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Fieldset selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Fieldset-root | Root element |
| legend | .mantine-Fieldset-legend | Legend element |
**Fieldset CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --fieldset-radius | Controls `border-radius` |
--------------------------------------------------------------------------------
### FileButton
Package: @mantine/core
Import: import { FileButton } from '@mantine/core';
Description: Open file picker with a button click
## Usage
```tsx
import { useState } from 'react';
import { FileButton, Button, Group, Text } from '@mantine/core';
function Demo() {
const [file, setFile] = useState(null);
return (
<>
{(props) => }
{file && (
Picked file: {file.name}
)}
>
);
}
```
## Multiple files
Set the `multiple` prop to allow picking multiple files:
```tsx
import { useState } from 'react';
import { FileButton, Button, Group, Text } from '@mantine/core';
function Demo() {
const [files, setFiles] = useState([]);
return (
<>
{(props) => }
{files.length > 0 && (
Picked files:
)}
{files.map((file, index) => (
{file.name}
))}
>
);
}
```
## Reset file
`resetRef` should be used to fix the issue with stale value on the hidden input element as input type file cannot be controlled.
Call `resetRef` when the user selection is cleared:
```tsx
import { useState, useRef } from 'react';
import { FileButton, Button, Group, Text } from '@mantine/core';
function Demo() {
const [file, setFile] = useState(null);
const resetRef = useRef<() => void>(null);
const clearFile = () => {
setFile(null);
resetRef.current?.();
};
return (
<>
{(props) => }
{file && (
Picked file: {file.name}
)}
>
);
}
```
## Server components
FileButton is not compatible with React Server Components as it uses useEffect and other client-side features. You can use it in client components only.
#### Props
**FileButton props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| accept | string | - | File input accept attribute, for example, `"image/png,image/jpeg"` |
| capture | boolean \| "user" \| "environment" | - | Specifies that, optionally, a new file should be captured, and which device should be used to capture that new media of a type defined by the accept attribute. |
| children | (props: { onClick: () => void; }) => ReactNode | required | Function that receives button props and returns react node that should be rendered |
| disabled | boolean | - | Disables file picker |
| form | string | - | Input form attribute |
| inputProps | React.ComponentProps<"input"> | - | Passes down props to the input element used to capture files |
| multiple | boolean | - | If set, user can pick more than one file |
| name | string | - | Input name attribute |
| onChange | (payload: Multiple extends true ? File[] : File \| null) => void | required | Called when files are picked |
| resetRef | Ref<() => void> | - | Reference of the function that should be called when value changes to null or empty array |
--------------------------------------------------------------------------------
### FileInput
Package: @mantine/core
Import: import { FileInput } from '@mantine/core';
Description: Capture files from user
## Usage
FileInput component supports [Input](https://mantine.dev/core/input) and [Input.Wrapper](https://mantine.dev/core/input) components features and all input element props. FileInput documentation does not include all features supported by the component β see [Input](https://mantine.dev/core/input) documentation to learn about all available features.
```tsx
import { FileInput } from '@mantine/core';
function Demo() {
return (
);
}
```
## Loading state
Set `loading` prop to display a loading indicator. By default, the loader is displayed on the right side of the input.
You can change the position with the `loadingPosition` prop to `'left'` or `'right'`. This is useful for async operations like API calls, searches, or validations:
```tsx
import { FileInput } from '@mantine/core';
function Demo() {
return ;
}
```
## Controlled
When `multiple` is `false`:
```tsx
import { useState } from 'react';
import { FileInput } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(null);
return ;
}
```
When `multiple` is `true`:
```tsx
import { useState } from 'react';
import { FileInput } from '@mantine/core';
function Demo() {
const [value, setValue] = useState([]);
return ;
}
```
## Uncontrolled
`FileInput` can be used with uncontrolled forms the same way as a native `input[type="file"]`.
Set the `name` attribute to include file input value in `FormData` object on form submission.
To control the initial value in uncontrolled forms, use the `defaultValue` prop.
Example usage of uncontrolled `FileInput` with `FormData`:
```tsx
import { FileInput } from '@mantine/core';
function Demo() {
return (
);
}
```
## Multiple
Set `multiple` to allow the user to pick more than one file:
```tsx
import { FileInput } from '@mantine/core';
function Demo() {
return ;
}
```
## Accept
Set the `accept` prop to restrict file selection to specific mime types:
```tsx
import { FileInput } from '@mantine/core';
function Demo() {
return (
);
}
```
## Clearable
Set the `clearable` prop to display a clear button in the right section of the input
when a file is selected. Note that if you define a custom right section, the clear button
will not be rendered.
```tsx
import { FileInput } from '@mantine/core';
function Demo() {
return ;
}
```
```tsx
import { CaretDownIcon } from '@phosphor-icons/react';
import { FileInput, Stack } from '@mantine/core';
function Demo() {
return (
}
clearSectionMode="both"
/>
}
clearSectionMode="rightSection"
/>
}
clearSectionMode="clear"
/>
);
}
```
## Custom value component
```tsx
import { FileInput, FileInputProps, Pill } from '@mantine/core';
const ValueComponent: FileInputProps['valueComponent'] = ({ value }) => {
if (value === null) {
return null;
}
if (Array.isArray(value)) {
return (
{value.map((file, index) => (
{file.name}
))}
);
}
return {value.name};
};
function Demo() {
return (
);
}
```
## Error state
```tsx
import { FileInput } from '@mantine/core';
function Demo() {
return (
<>
>
);
}
```
## FileInputProps type
`FileInputProps` type is a generic interface which accepts a single type argument:
the `multiple` value.
```tsx
import type { FileInputProps } from '@mantine/core';
type SingleInputProps = FileInputProps;
type MultipleInputProps = FileInputProps;
```
#### Props
**FileInput props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| accept | string | - | File input accept attribute, for example, `"image/png,image/jpeg"` |
| capture | boolean \| "user" \| "environment" | - | Specifies that, optionally, a new file should be captured, and which device should be used to capture that new media of a type defined by the accept attribute. |
| clearButtonProps | React.ComponentProps<"button"> | - | Props passed down to the clear button |
| clearSectionMode | ClearSectionMode | - | Determines how the clear button and rightSection are rendered |
| clearable | boolean | - | If set, the clear button is displayed in the right section |
| defaultValue | File \| File[] \| null | - | Uncontrolled component default value |
| description | React.ReactNode | - | Contents of `Input.Description` component. If not set, description is not displayed. |
| descriptionProps | InputDescriptionProps | - | Props passed down to the `Input.Description` component |
| disabled | boolean | - | Sets `disabled` attribute on the `input` element |
| error | React.ReactNode | - | Contents of `Input.Error` component. If not set, error is not displayed. |
| errorProps | InputErrorProps | - | Props passed down to the `Input.Error` component |
| fileInputProps | React.ComponentProps<"input"> | - | Props passed down to the hidden `input[type="file"]` |
| form | string | - | Input form attribute |
| inputContainer | (children: ReactNode) => ReactNode | - | Render function to wrap the input element. Useful for adding tooltips, popovers, or other wrappers around the input. |
| inputSize | string | - | HTML `size` attribute for the input element (number of visible characters) |
| inputWrapperOrder | ("input" \| "label" \| "description" \| "error")[] | - | Controls order and visibility of wrapper elements. Only elements included in this array will be rendered. |
| label | React.ReactNode | - | Contents of `Input.Label` component. If not set, label is not displayed. |
| labelProps | InputLabelProps | - | Props passed down to the `Input.Label` component |
| leftSection | React.ReactNode | - | Content section displayed on the left side of the input |
| leftSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `leftSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| leftSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `leftSection` element |
| leftSectionWidth | React.CSSProperties["width"] | - | Left section width, used to set `width` of the section and input `padding-left`, by default equals to the input height |
| loading | boolean | - | Displays loading indicator in the left or right section |
| loadingPosition | "left" \| "right" | - | Position of the loading indicator |
| multiple | boolean | - | If set, user can pick more than one file |
| name | string | - | Input name attribute |
| onChange | (payload: Multiple extends true ? File[] : File \| null) => void | - | Called when value changes |
| placeholder | React.ReactNode | - | Input placeholder |
| pointer | boolean | - | Determines whether the input should have `cursor: pointer` style. Use when input acts as a button-like trigger (e.g., `component="button"` for Select/DatePicker). |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem |
| readOnly | boolean | - | If set, the input value cannot be changed |
| required | boolean | - | Adds required attribute to the input and a red asterisk on the right side of label |
| resetRef | Ref<() => void> | - | Reference of the function that should be called when value changes to null or empty array |
| rightSection | React.ReactNode | - | Content section displayed on the right side of the input |
| rightSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `rightSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| rightSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `rightSection` element |
| rightSectionWidth | React.CSSProperties["width"] | - | Right section width, used to set `width` of the section and input `padding-right`, by default equals to the input height |
| size | MantineSize | - | Controls input `height`, horizontal `padding`, and `font-size` |
| value | File \| File[] \| null | - | Controlled component value |
| valueComponent | FC<{ value: File \| File[] \| null; }> | - | Value renderer. By default, displays file name. |
| withAsterisk | boolean | - | If set, the required asterisk is displayed next to the label. Overrides `required` prop. Does not add required attribute to the input. |
| withErrorStyles | boolean | - | Determines whether the input should have red border and red text color when the `error` prop is set |
| wrapperProps | WrapperProps | - | Props passed down to the root element |
#### Styles API
FileInput component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**FileInput selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| wrapper | .mantine-FileInput-wrapper | Root element of the Input |
| input | .mantine-FileInput-input | Input element |
| section | .mantine-FileInput-section | Left and right sections |
| root | .mantine-FileInput-root | Root element |
| label | .mantine-FileInput-label | Label element |
| required | .mantine-FileInput-required | Required asterisk element, rendered inside label |
| description | .mantine-FileInput-description | Description element |
| error | .mantine-FileInput-error | Error element |
| placeholder | .mantine-FileInput-placeholder | Placeholder text |
--------------------------------------------------------------------------------
### Flex
Package: @mantine/core
Import: import { Flex } from '@mantine/core';
Description: Compose elements in a flex container
## Usage
```tsx
import { Flex, Button } from '@mantine/core';
function Demo() {
return (
);
}
```
## Supported props
## Responsive props
`Flex` component props can have responsive values the same way as other [style props](https://alpha.mantine.dev/llms/styles-style-props.md):
```tsx
import { Flex, Button } from '@mantine/core';
function Demo() {
return (
);
}
```
## Difference from Group and Stack
The `Flex` component is an alternative to [Group](https://alpha.mantine.dev/llms/core-group.md) and [Stack](https://alpha.mantine.dev/llms/core-stack.md).
`Flex` is more flexible β it allows creating both horizontal and vertical flexbox layouts, but requires more configuration.
Unlike [Group](https://alpha.mantine.dev/llms/core-group.md) and [Stack](https://alpha.mantine.dev/llms/core-stack.md), `Flex` is [polymorphic](https://alpha.mantine.dev/llms/guides-polymorphic.md) and supports responsive props.
## Browser support
Flex component uses CSS flexbox gap to add spacing between children. Flexbox gap is supported by all modern browsers, but if you need to support older browsers, use Space component instead.
#### Props
**Flex props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| align | StyleProp | - | `align-items` CSS property |
| columnGap | StyleProp | - | `column-gap` CSS property |
| direction | StyleProp | - | `flex-direction` CSS property |
| gap | StyleProp | - | `gap` CSS property |
| justify | StyleProp | - | `justify-content` CSS property |
| rowGap | StyleProp | - | `row-gap` CSS property |
| wrap | StyleProp | - | `flex-wrap` CSS property |
#### Styles API
Flex component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Flex selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Flex-root | Root element |
--------------------------------------------------------------------------------
### FloatingIndicator
Package: @mantine/core
Import: import { FloatingIndicator } from '@mantine/core';
Description: Display a floating indicator over a group of elements
## Usage
`FloatingIndicator` is designed to highlight the active element in a group.
It can be used to create custom segmented controls, tabs and other similar components.
`FloatingIndicator` renders an element over the `target` element. To calculate the position, it is
required to pass a `parent` element. **The parent element must have `position: relative` CSS property** β
this is essential for correct positioning. The component returns `null` and renders nothing if either
`target` or `parent` is not provided.
By default, `FloatingIndicator` does not have any visible styles. You can use the `className` prop
or [Styles API](https://alpha.mantine.dev/llms/styles-styles-api.md) to apply styles. Note that the indicator's `transform`, `width`,
and `height` styles are set directly via JavaScript to enable smooth position transitions β these
cannot be overridden via the Styles API.
```tsx
import { useState } from 'react';
import { FloatingIndicator, UnstyledButton } from '@mantine/core';
import classes from './Demo.module.css';
const data = ['React', 'Vue', 'Angular', 'Svelte'];
function Demo() {
const [rootRef, setRootRef] = useState(null);
const [controlsRefs, setControlsRefs] = useState>({});
const [active, setActive] = useState(0);
const setControlRef = (index: number) => (node: HTMLButtonElement) => {
controlsRefs[index] = node;
setControlsRefs(controlsRefs);
};
const controls = data.map((item, index) => (
setActive(index)}
mod={{ active: active === index }}
>
{item}
));
return (
{controls}
);
}
```
## Multiple rows
`FloatingIndicator` can be used to highlight the active element in a group with multiple rows:
```tsx
import { useState } from 'react';
import { ArrowDownIcon, ArrowDownLeftIcon, ArrowDownRightIcon, ArrowLeftIcon, ArrowRightIcon, ArrowUpIcon, ArrowUpLeftIcon, ArrowUpRightIcon, CircleIcon } from '@phosphor-icons/react';
import { FloatingIndicator, UnstyledButton } from '@mantine/core';
import classes from './Demo.module.css';
function Demo() {
const [rootRef, setRootRef] = useState(null);
const [controlsRefs, setControlsRefs] = useState>({});
const [active, setActive] = useState('center');
const setControlRef = (name: string) => (node: HTMLButtonElement) => {
controlsRefs[name] = node;
setControlsRefs(controlsRefs);
};
return (
setActive('up-left')}
ref={setControlRef('up-left')}
mod={{ active: active === 'up-left' }}
>
setActive('up')}
ref={setControlRef('up')}
mod={{ active: active === 'up' }}
>
setActive('up-right')}
ref={setControlRef('up-right')}
mod={{ active: active === 'up-right' }}
>
setActive('left')}
ref={setControlRef('left')}
mod={{ active: active === 'left' }}
>
setActive('center')}
ref={setControlRef('center')}
mod={{ active: active === 'center' }}
>
setActive('right')}
ref={setControlRef('right')}
mod={{ active: active === 'right' }}
>
setActive('down-left')}
ref={setControlRef('down-left')}
mod={{ active: active === 'down-left' }}
>
setActive('down')}
ref={setControlRef('down')}
mod={{ active: active === 'down' }}
>
setActive('down-right')}
ref={setControlRef('down-right')}
mod={{ active: active === 'down-right' }}
>
);
}
```
## Example: Tabs
```tsx
// Demo.tsx
import { useState } from 'react';
import { FloatingIndicator, Tabs } from '@mantine/core';
import classes from './Demo.module.css';
function Demo() {
const [rootRef, setRootRef] = useState(null);
const [value, setValue] = useState('1');
const [controlsRefs, setControlsRefs] = useState>({});
const setControlRef = (val: string) => (node: HTMLButtonElement) => {
controlsRefs[val] = node;
setControlsRefs(controlsRefs);
};
return (
First tab
Second tab
Third tab
First tab contentSecond tab contentThird tab content
);
}
// Demo.module.css
.list {
position: relative;
margin-bottom: var(--mantine-spacing-md);
}
.indicator {
background-color: var(--mantine-color-white);
border-radius: var(--mantine-radius-md);
border: 1px solid var(--mantine-color-gray-2);
box-shadow: var(--mantine-shadow-sm);
@mixin dark {
background-color: var(--mantine-color-dark-6);
border-color: var(--mantine-color-dark-4);
}
}
.tab {
z-index: 1;
font-weight: 600;
transition: color 100ms ease;
color: var(--mantine-color-gray-7);
&[data-active] {
color: var(--mantine-color-black);
}
@mixin dark {
color: var(--mantine-color-dark-1);
&[data-active] {
color: var(--mantine-color-white);
}
}
}
```
#### Props
**FloatingIndicator props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| displayAfterTransitionEnd | boolean | - | Controls whether the indicator should be hidden initially and displayed after the parent's transition ends. Set to `true` when the parent container has CSS transitions (e.g., `transform: scale()`) to prevent the indicator from appearing at the wrong position during the parent's animation. |
| onTransitionEnd | () => void | - | Called when the indicator finishes transitioning to a new position |
| onTransitionStart | () => void | - | Called when the indicator starts transitioning to a new position |
| parent | HTMLElement \| null | required | Parent container element that must have `position: relative`. The indicator's position is calculated relative to this element. |
| target | HTMLElement \| null | required | Target element over which the indicator is displayed. The indicator will be positioned to match the target's size and position. |
| transitionDuration | string \| number | - | Transition duration in ms |
#### Styles API
FloatingIndicator component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**FloatingIndicator selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-FloatingIndicator-root | Indicator element that animates to match the target position and size |
**FloatingIndicator CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --transition-duration | Controls indicator transition duration |
**FloatingIndicator data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-initialized | Indicator has been initialized and transitions are enabled | - |
| root | data-hidden | Indicator is hidden (when displayAfterTransitionEnd is true) | - |
--------------------------------------------------------------------------------
### FloatingWindow
Package: @mantine/core
Import: import { FloatingWindow } from '@mantine/core';
Description: Draggable floating area
## Usage
`FloatingWindow` creates a draggable element with a fixed position:
```tsx
import { Button, CloseButton, FloatingWindow, Group, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [visible, handlers] = useDisclosure();
return (
<>
{visible && (
Usage demoThis is a floating window. You can drag it around.
)}
>
);
}
```
## Constrain to viewport
Use the `constrainToViewport` prop to restrict element movement to the viewport boundaries.
If you do not set the `constrainToViewport` prop, the element can be dragged outside the viewport:
```tsx
import { Button, CloseButton, FloatingWindow, Group, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [visible, handlers] = useDisclosure();
return (
<>
{visible && (
No constrain demo
The floating window is not constrained by the viewport, it can move out of bounds.
)}
>
);
}
```
## Constrain offset
Use the `constrainOffset` prop to set the offset from the viewport edges when constraining the element:
```tsx
import { Button, CloseButton, FloatingWindow, Group, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [visible, handlers] = useDisclosure();
return (
<>
{visible && (
Constrain offset demo
This floating window has 30px offset, it cannot move closer that 30px to the edge of the
viewport.
)}
>
);
}
```
## Drag handle selector
The `dragHandleSelector` prop allows specifying a selector of an element (or a group of elements) that should be used to drag the floating window.
If not specified, the entire root element is used as a drag target.
The `excludeDragHandleSelector` prop excludes elements within `dragHandleSelector` from the drag event.
In the following example, the close button is excluded from the drag event:
```tsx
import { Button, CloseButton, FloatingWindow, Group, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [visible, handlers] = useDisclosure();
return (
<>
{visible && (
Drag handle demo
Drag floating window around with drag handle element.
)}
>
);
}
```
## Enabled prop
Use the `enabled` option to enable or disable dragging:
```tsx
import { Button, Chip, CloseButton, FloatingWindow, Group, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [visible, handlers] = useDisclosure();
const [enabled, setEnabled] = useState(true);
return (
<>
setEnabled((e) => !e)}>
Drag {enabled ? 'enabled' : 'disabled'}
{visible && (
Enabled demoThis is a floating window. You can drag it around.
)}
>
);
}
```
## Set position
Call the `setPosition` function to set the position of the element programmatically.
This function accepts an object with `top`, `left`, `right` and `bottom` properties,
from which you should only specify two (for example, `top` and `left`, `bottom` and `right`).
```tsx
import { useRef } from 'react';
import { Button, CloseButton, FloatingWindow, Group, Text } from '@mantine/core';
import { SetFloatingWindowPosition, useDisclosure } from '@mantine/hooks';
function Demo() {
const [visible, handlers] = useDisclosure();
const setPositionRef = useRef(null);
const setPosition = () => {
setPositionRef.current?.({ bottom: 40, right: 40 });
};
return (
<>
{visible && (
Set position demo
You can control floating window position programmatically with setPositionRef.
)}
>
);
}
```
## Lock axis
Use the `axis` option to restrict movement to the specified axis:
```tsx
import { Button, CloseButton, FloatingWindow, Group, SegmentedControl, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [visible, handlers] = useDisclosure();
const [axis, setAxis] = useState<'x' | 'y'>('y');
return (
<>
setAxis(val as 'x')} value={axis} />
{visible && (
Axis demo
When you set axis prop, the floating window can be dragged only horizontally or
vertically.
)}
>
);
}
```
## use-floating-window hook
If you prefer the hook API, you can use the [useFloatingWindow](https://alpha.mantine.dev/llms/hooks-use-floating-window.md) hook.
It supports most of the `FloatingWindow` features:
```tsx
import { Button, CloseButton, Group, Paper, Portal, Text } from '@mantine/core';
import { useDisclosure, useFloatingWindow } from '@mantine/hooks';
function Demo() {
const [visible, handlers] = useDisclosure();
const floatingWindow = useFloatingWindow({
constrainToViewport: true,
constrainOffset: 20,
excludeDragHandleSelector: 'button',
initialPosition: { top: 300, left: 20 },
});
return (
<>
{visible && (
Usage demoThis is a floating window. You can drag it around.
)}
>
);
}
```
#### Props
**FloatingWindow props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| axis | "x" \| "y" | - | If set, restricts movement to the specified axis |
| constrainOffset | number | - | The offset from the viewport edges when constraining the element. Requires `constrainToViewport: true`. |
| constrainToViewport | boolean | - | If `true`, the element can only move within the current viewport boundaries. |
| dragHandleSelector | string | - | Selector of an element that should be used to drag floating window. If not specified, the entire root element is used as a drag target. |
| enabled | boolean | - | If `false`, the element can not be dragged. |
| excludeDragHandleSelector | string | - | Selector of an element within `dragHandleSelector` that should be excluded from the drag event. |
| initialPosition | FloatingWindowPositionConfig | - | Initial position. If not set, calculated from element styles. |
| onDragEnd | () => void | - | Called when the drag stops |
| onDragStart | () => void | - | Called when the drag starts |
| onPositionChange | (pos: FloatingWindowPosition) => void | - | Called when the element position changes |
| portalProps | Omit | - | Props passed down to `Portal` component |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius, numbers are converted to rem |
| setPositionRef | RefObject | - | Assigns ref to set position programmatically |
| shadow | MantineShadow | - | Key of `theme.shadows` or any valid CSS value to set `box-shadow` |
| withBorder | boolean | - | Adds border to the root element |
| withinPortal | boolean | - | Determines whether the window should be rendered inside `Portal` |
| zIndex | React.CSSProperties["zIndex"] | - | `z-index` of the root element |
#### Styles API
FloatingWindow component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**FloatingWindow selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-FloatingWindow-root | Root element |
**FloatingWindow data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-dragging | Window is being dragged | - |
--------------------------------------------------------------------------------
### FocusTrap
Package: @mantine/core
Import: import { FocusTrap } from '@mantine/core';
Description: Trap focus at child node
## Usage
FocusTrap is a component implementation of the [use-focus-trap](https://alpha.mantine.dev/llms/hooks-use-focus-trap.md) hook.
It is used in all Mantine components that require focus trap ([Modal](https://alpha.mantine.dev/llms/core-modal.md), [DatePicker](https://alpha.mantine.dev/llms/dates-date-picker.md), [Popover](https://alpha.mantine.dev/llms/core-popover.md), etc.).
```tsx
import { useDisclosure } from '@mantine/hooks';
import { FocusTrap, TextInput, Button, Box } from '@mantine/core';
function Demo() {
const [active, { toggle }] = useDisclosure(false);
return (
);
}
```
## Initial focus
To define the element that will receive initial focus, set the `data-autofocus` attribute:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { FocusTrap, TextInput, Button, Box } from '@mantine/core';
function Demo() {
const [active, { toggle }] = useDisclosure(false);
return (
);
}
```
## FocusTrap.InitialFocus
`FocusTrap.InitialFocus` is a special component that adds a visually hidden
element which will receive the focus when the focus trap is activated.
Once `FocusTrap.InitialFocus` loses focus, it is removed from the tab order.
For example, it is useful if you do not want to focus any elements inside the [Modal](https://alpha.mantine.dev/llms/core-modal.md) when it is opened:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button, TextInput, FocusTrap } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
>
);
}
```
## Focus trapping logic
* Focus is trapped within the child node if the `active` prop is `true`
* When the FocusTrap component is mounted or when the `active` prop changes from `false` to `true`, the first element with the `data-autofocus` attribute is focused
* If there are no elements with the `data-autofocus` attribute, then the first element that supports keyboard interaction is focused
* If the target element does not have focusable elements or does not support `ref`, then the focus trap will not work
* Trap stops working when an element outside of the `FocusTrap` child is focused
#### Props
**FocusTrap props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| active | boolean | - | If set to `false`, disables focus trap |
| children | any | required | Element to trap focus at, must support ref prop |
| innerRef | Ref | - | Ref to combine with the focus trap ref |
| refProp | string | - | Prop that is used to access element ref |
**FocusTrap..InitialFocus props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
**FocusTrap.InitialFocus props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
--------------------------------------------------------------------------------
### Grid
Package: @mantine/core
Import: import { Grid } from '@mantine/core';
Description: Responsive 12 columns grid system
## Usage
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
123
);
}
```
## Columns span
The `Grid.Col` `span` prop controls the ratio of column width to the total width of the row.
By default, grid uses a 12 columns layout, so the `span` prop can be any number from 1 to 12.
Examples:
* `` β 3 / 12 = 25% of row width
* `` β 4 / 12 = 33% of row width
* `` β 6 / 12 = 50% of row width
* `` β 12 / 12 = 100% of row width
The `span` prop also supports object syntax to change column width based on viewport width.
It accepts `xs`, `sm`, `md`, `lg` and `xl` keys and values from 1 to 12. The syntax
is the same as in [style props](https://alpha.mantine.dev/llms/styles-style-props.md).
In the following example `span={{ base: 12, md: 6, lg: 3 }}`:
* `base` β 12 / 12 = 100% of row width when viewport width is less than `md` breakpoint
* `md` β 6 / 12 = 50% of row width when viewport width is between `md` and `lg` breakpoints
* `lg` β 3 / 12 = 25% of row width when viewport width is greater than `lg` breakpoint
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
1234
);
}
```
## Gap
Set the `gap` prop to control spacing between columns and rows. The prop works the same
way as [style props](https://alpha.mantine.dev/llms/styles-style-props.md) β you can reference `theme.spacing` values
with `xs`, `sm`, `md`, `lg` and `xl` strings and use object syntax to change gap
based on viewport width:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
123
);
}
```
## Row and column gap
Use `rowGap` and `columnGap` props to set different spacing for rows and columns.
`rowGap` and `columnGap` override `gap` prop if both are set:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
12345678
);
}
```
## Grow
If the `grow` prop is set, the column will grow to fill the remaining space in the row:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
12345
);
}
```
## Column offset
Set the `offset` prop on the `Grid.Col` component to add gaps to the grid. The `offset` prop
supports the same syntax as the `span` prop: a number from 1 to 12 or an object with `xs`, `sm`, `md`, `lg` and `xl` keys and values from 1 to 12.
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
123
);
}
```
## Order
Set the `order` prop on the `Grid.Col` component to change the order of columns. The `order` prop
supports the same syntax as the `span` prop: a number from 1 to 12 or an object with `xs`, `sm`, `md`, `lg` and `xl` keys and values from 1 to 12.
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
231
);
}
```
## Multiple rows
Once the columns' `span` and `offset` sum exceeds the `columns` prop (12 by default),
columns are moved to the next row:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
1234
);
}
```
## Justify and align
You can control the `justify-content` and `align-items` CSS properties with the `justify` and `align` props on the `Grid` component:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
123
);
}
```
## Column alignment
Use the `align` prop on individual `Grid.Col` components to control the `align-self` CSS property
for each column. This allows you to override the grid's `align` prop for specific columns:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
flex-start
center
flex-end
);
}
```
## Auto sized columns
All columns in a row with `span="auto"` grow as much as they can to fill the row.
In the following example, the second column takes up 50% of the row while the other two columns automatically resize to fill the remaining space:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
123
);
}
```
## Fit column content
If you set `span="content"`, the column's size will automatically adjust to match the width of its content:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
fit content2
);
}
```
## Change columns count
By default, grid uses a 12 columns layout. You can change it by setting the `columns` prop on the `Grid` component.
Note that in this case, columns span and offset will be calculated relative to this value.
In the following example, the first column takes 50% with 12 span (12/24), second and third take 25% (6/24):
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
123
);
}
```
## Container queries
To use [container queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries)
instead of media queries, set `type="container"`. With container queries, all responsive values
are adjusted based on the container width, not the viewport width.
Note that, when using container queries, it is also required to set `breakpoints` prop
to the exact container width values.
To see how the grid changes, resize the root element of the demo
with the resize handle located at the bottom right corner of the demo:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
// Wrapper div is added for demonstration purposes only.
// It is not required in real projects.
1234
);
}
```
## Browser support
Grid component uses flexbox with native `gap` for layout, which is supported in all modern browsers.
### Container queries
When using `type="container"`, the Grid component uses [CSS container queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries).
Container queries are supported in the following browsers:
* Chrome 105+
* Safari 16+
* Firefox 110+
* Edge 105+
If you need to support older browsers, use the default `type="media"` which uses standard media queries
instead of container queries.
Example with media queries (default):
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
12
);
}
```
Example with container queries:
```tsx
import { Grid } from '@mantine/core';
function Demo() {
return (
12
);
}
```
#### Props
**Grid props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| align | AlignItems | - | Sets `align-items` |
| breakpoints | GridBreakpoints | - | Breakpoints values, only used with `type="container"` |
| columnGap | StyleProp | - | Column gap, overrides `gap` for horizontal spacing |
| columns | number | - | Number of columns in each row |
| gap | StyleProp | - | Gap between columns and rows, key of `theme.spacing` or any valid CSS value |
| grow | boolean | - | If set, columns in the last row expand to fill all available space |
| justify | JustifyContent | - | Sets `justify-content` |
| overflow | Overflow | - | Sets `overflow` CSS property on the root element |
| rowGap | StyleProp | - | Row gap, overrides `gap` for vertical spacing |
| type | "media" \| "container" | - | Type of queries used for responsive styles |
**Grid.Col props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| align | StyleProp | - | Vertical alignment of the column, controls `align-self` CSS property |
| offset | StyleProp | - | Column start offset β number of empty columns before this column |
| order | StyleProp | - | Column order, use to reorder columns at different viewport sizes |
| span | StyleProp | - | Column span |
#### Styles API
Grid component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Grid selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| container | .mantine-Grid-container | Container element, only used with `type="container"` prop |
| root | .mantine-Grid-root | Root element |
| inner | .mantine-Grid-inner | Columns wrapper |
| col | .mantine-Grid-col | `Grid.Col` root element |
**Grid CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --grid-overflow | Controls `overflow` property |
| root | --grid-align | Controls `align-items` property |
| root | --grid-justify | Controls `justify-content` property |
**Grid data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-with-gap | CSS variables for gap, rowGap, and columnGap are set. Variables include: --grid-gap, --grid-row-gap, --grid-column-gap, --grid-margin, --grid-col-padding-x, --grid-col-padding-y | true |
| col | data-with-col-vars | CSS variables for column layout are set. Variables include: --col-flex-grow, --col-flex-basis, --col-width, --col-max-width, --col-offset, --col-order, --col-align-self | true |
--------------------------------------------------------------------------------
### Group
Package: @mantine/core
Import: import { Group } from '@mantine/core';
Description: Compose elements and components in a horizontal flex container
## Usage
`Group` is a horizontal flex container. If you need a vertical flex container, use the [Stack](https://alpha.mantine.dev/llms/core-stack.md)
component instead. If you need to have full control over flex container properties, use the [Flex](https://alpha.mantine.dev/llms/core-flex.md) component.
```tsx
import { Group, Button } from '@mantine/core';
function Demo() {
return (
);
}
```
## preventGrowOverflow
The `preventGrowOverflow` prop allows you to control how `Group` children should behave when there is not enough
space to fit them all on one line. By default, children are not allowed to take more space than
`(1 / children.length) * 100%` of parent width (`preventGrowOverflow` is set to `true`). To change
this behavior, set `preventGrowOverflow` to `false` and children will be allowed to grow and take
as much space as they need.
```tsx
import { Group, Button, Box, Text } from '@mantine/core';
function Demo() {
return (
preventGrowOverflow: true β each child width is always limited to 33% of parent width
(since there are 3 children)
preventGrowOverflow: false β children will grow based on their content, they can take more
than 33% of parent width
);
}
```
## Group children
**!important** `Group` works correctly only with React elements.
Strings, numbers, fragments may have incorrect styles if the `grow` prop is set:
```tsx
// Invalid Group usage, do not do this
import { Group } from '@mantine/core';
function InvalidDemo() {
return (
First string
<>
element inside fragment
another inside fragment
>
{20}
);
}
```
## Browser support
Flex component uses CSS flexbox gap to add spacing between children. Flexbox gap is supported by all modern browsers, but if you need to support older browsers, use Space component instead.
#### Props
**Group props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| align | AlignItems | - | Controls `align-items` CSS property |
| gap | MantineSpacing | - | Key of `theme.spacing` or any valid CSS value for `gap`, numbers are converted to rem |
| grow | boolean | - | Determines whether each child element should have `flex-grow: 1` style |
| justify | JustifyContent | - | Controls `justify-content` CSS property |
| preventGrowOverflow | boolean | - | Determines whether children should take only dedicated amount of space (`max-width` style is set based on the number of children) |
| wrap | FlexWrap | - | Controls `flex-wrap` CSS property |
#### Styles API
Group component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Group selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Group-root | Root element |
**Group CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --group-align | Controls `align-items` property |
| root | --group-justify | Controls `justify-content` property |
| root | --group-gap | Controls `gap` property |
| root | --group-wrap | Controls `flex-wrap` property |
**Group data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-grow | `grow` prop is set | - |
--------------------------------------------------------------------------------
### Highlight
Package: @mantine/core
Import: import { Highlight } from '@mantine/core';
Description: Highlight given part of a string with mark
## Usage
Use the Highlight component to highlight substrings within text using the HTML `` element.
Pass the text as children and specify which substring(s) to highlight with the `highlight` prop.
Matching is **case-insensitive** and highlights all occurrences of the matched substring.
```tsx
import { Highlight } from '@mantine/core';
function Demo() {
return (
{{children}}
);
}
```
## Matching behavior
* **Case-insensitive**: 'hello' matches 'Hello', 'HELLO', 'hElLo', etc.
* **All occurrences**: Every instance of the matched substring is highlighted
* **Special characters**: Regex special characters like `[`, `]`, `(`, `)` are automatically escaped and treated as literal text
* **Whitespace**: Leading and trailing whitespace in highlight strings is trimmed and ignored
* **Empty strings**: Empty or whitespace-only highlight strings are ignored
## Highlight multiple substrings
To highlight multiple substrings, provide an array of values.
When multiple substrings are provided, longer matches take precedence to avoid partial overlaps.
```tsx
import { Highlight } from '@mantine/core';
function Demo() {
return Highlight this and also that;
}
```
## Custom colors per term
You can assign different colors to different highlighted terms by providing an array of objects with `text` and `color` properties:
```tsx
import { Highlight } from '@mantine/core';
function Demo() {
return (
Error: Invalid input. Warning: Check this field. Success: All tests passed.
);
}
```
## Whole word matching
Use the `wholeWord` prop to match only complete words. When enabled, 'the' will not match 'there' or 'theme':
```tsx
import { Highlight, Stack, Text } from '@mantine/core';
function Demo() {
return (
With whole word matching (wholeWord={'{'}true{'}'})
The theme is there
Without whole word matching (default)
The theme is there
);
}
```
## Change highlight styles
Default [Mark](https://alpha.mantine.dev/llms/core-mark.md) styles can be overwritten with the `highlightStyles` prop,
which accepts either an object with styles or a function that receives the theme as a parameter and returns styles:
```tsx
import { Highlight } from '@mantine/core';
function Demo() {
return (
You can change styles of highlighted part if you do not like default styles
);
}
```
## Text props
Highlight is based on the [Text](https://alpha.mantine.dev/llms/core-text.md) component - all Text props except `color` are available.
Use the `color` prop to change the highlight background color, not the text color.
```tsx
import { Highlight } from '@mantine/core';
function Demo() {
return (
Mantine website
);
}
```
#### Props
**Highlight props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | string | required | String in which to highlight substrings |
| color | string \| (string & {}) | - | Default background color for all highlighted text. Key of `theme.colors` or any valid CSS color, passed to `Mark` component. Can be overridden per term when using HighlightTerm objects. |
| gradient | MantineGradient | - | Gradient configuration, ignored when `variant` is not `gradient` |
| highlight | string \| string[] \| HighlightTerm[] | required | Substring(s) to highlight in `children`. Can be: - string: single term - string[]: multiple terms with same color - HighlightTerm[]: multiple terms with custom colors per term - Matching is case-insensitive - Regex special characters are automatically escaped - When multiple substrings are provided, longer matches take precedence - Empty strings and whitespace-only strings are ignored |
| highlightStyles | CSSProperties \| ((theme: MantineTheme) => CSSProperties) | - | Styles applied to `mark` elements |
| inherit | boolean | - | Determines whether font properties should be inherited from the parent |
| inline | boolean | - | Sets `line-height` to 1 for centering |
| lineClamp | number | - | Number of lines after which Text will be truncated |
| size | MantineSize \| (string & {}) | - | Controls `font-size` and `line-height` |
| span | boolean | - | Shorthand for `component="span"` |
| truncate | TextTruncate | - | Side on which Text must be truncated, if `true`, text is truncated from the start |
| wholeWord | boolean | - | Only match whole words (adds word boundaries to regex). When enabled, 'the' will not match 'there'. |
#### Styles API
Highlight component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Highlight selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Highlight-root | Root element |
--------------------------------------------------------------------------------
### HoverCard
Package: @mantine/core
Import: import { HoverCard } from '@mantine/core';
Description: Display popover section when target element is hovered
## Usage
```tsx
import { HoverCard, Button, Text, Group } from '@mantine/core';
function Demo() {
return (
Hover card is revealed when user hovers over target element, it will be hidden once
mouse is not over both target and dropdown elements
);
}
```
## Delays
Set open and close delays in ms with the `openDelay` and `closeDelay` props:
```tsx
import { HoverCard, Button, Text, Group } from '@mantine/core';
function Demo() {
return (
Opened with 1000ms delayWill close with 1000ms delay
);
}
```
## HoverCard delay group
Use the `HoverCard.Group` component to sync open and close delays of multiple `HoverCard` components:
```tsx
import { HoverCard, Button, Text, Group } from '@mantine/core';
function Demo() {
return (
First hover card contentSecond hover card contentThird hover card content
);
}
```
## With interactive elements
`HoverCard` is displayed only when the mouse is over the target element or dropdown.
You can use anchors and buttons within dropdowns, using inputs is not recommended:
```tsx
import { HoverCard, Avatar, Text, Group, Anchor, Stack } from '@mantine/core';
function Demo() {
return (
Mantine
@mantinedev
Customizable React components and hooks library with focus on usability, accessibility
and developer experience
0 Following
1,174 Followers
);
}
```
## Target component
The target element determines where the HoverCard will be positioned relative to.
## Accessibility
`HoverCard` is ignored by screen readers and cannot be activated with the keyboard. Use it to display only additional information
that is not required to understand the context.
#### Props
**HoverCard props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| arrowOffset | number | - | Arrow offset in px |
| arrowPosition | 'center' \| 'side' | - | Arrow position |
| arrowRadius | number | - | Arrow `border-radius` in px |
| arrowSize | number | - | Arrow size in px |
| children | React.ReactNode | - | `Popover.Target` and `Popover.Dropdown` components |
| clickOutsideEvents | string[] | - | Events that trigger outside clicks |
| closeDelay | number | - | Delay in ms before the dropdown closes after mouse leaves the target or dropdown. Overridden by HoverCard.Group delay if used within a group. |
| closeOnClickOutside | boolean | - | Determines whether dropdown should be closed on outside clicks |
| closeOnEscape | boolean | - | Determines whether dropdown should be closed when `Escape` key is pressed |
| defaultOpened | boolean | - | Initial opened state for uncontrolled component |
| disabled | boolean | - | If set, popover dropdown will not be rendered |
| floatingStrategy | FloatingStrategy | - | Changes floating ui [position strategy](https://floating-ui.com/docs/usefloating#strategy) |
| hideDetached | boolean | - | If set, the dropdown is hidden when the element is hidden with styles or not visible on the screen |
| id | string | - | Id base to create accessibility connections |
| initiallyOpened | boolean | - | Initial opened state |
| keepMounted | boolean | - | If set, the dropdown is not unmounted from the DOM when hidden. `display: none` styles are added instead. |
| middlewares | PopoverMiddlewares | - | Floating ui middlewares to configure position handling |
| offset | number \| FloatingAxesOffsets | - | Offset of the dropdown element |
| onClose | () => void | - | Called when the dropdown is closed |
| onDismiss | () => void | - | Called when the popover is dismissed by clicking outside or by pressing escape |
| onEnterTransitionEnd | () => void | - | Called when enter transition ends |
| onExitTransitionEnd | () => void | - | Called when exit transition ends |
| onOpen | () => void | - | Called when the dropdown is opened |
| onPositionChange | (position: FloatingPosition) => void | - | Called when dropdown position changes |
| openDelay | number | - | Delay in ms before the dropdown opens after mouse enters the target. Overridden by HoverCard.Group delay if used within a group. |
| overlayProps | OverlayProps & ElementProps<"div"> | - | Props passed down to `Overlay` component |
| portalProps | BasePortalProps | - | Props to pass down to the `Portal` when `withinPortal` is true |
| position | FloatingPosition | - | Dropdown position relative to the target element |
| preventPositionChangeWhenVisible | boolean | - | Prevents popover from flipping/shifting when it the dropdown is visible |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius |
| returnFocus | boolean | - | Determines whether focus should be automatically returned to control when dropdown closes |
| shadow | MantineShadow | - | Key of `theme.shadows` or any other valid CSS `box-shadow` value |
| transitionProps | TransitionProps | - | Props passed down to the `Transition` component. Use to configure duration and animation type. |
| trapFocus | boolean | - | Determines whether focus should be trapped within dropdown |
| width | PopoverWidth | - | Dropdown width, or `'target'` to make dropdown width the same as target element |
| withArrow | boolean | - | Determines whether component should have an arrow |
| withOverlay | boolean | - | Determines whether the overlay should be displayed when the dropdown is opened |
| withRoles | boolean | - | Determines whether dropdown and target elements should have accessible roles |
| withinPortal | boolean | - | Determines whether dropdown should be rendered within the `Portal` |
| zIndex | string \| number | - | Dropdown `z-index` |
**HoverCard..Target props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | Target element |
| eventPropsWrapperName | string | - | Name of the prop to wrap event listeners in. Use when the target component expects event listeners in a nested object. For example, some components expect `componentProps={{ onMouseEnter, onMouseLeave }}`. |
| popupType | string | - | Popup accessible type |
| refProp | string | - | Key of the prop that should be used to access element ref |
**HoverCard..Dropdown props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Dropdown content |
**HoverCard..Group props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | `HoverCard` components |
| closeDelay | number | - | Close delay in ms |
| openDelay | number | - | Open delay in ms |
**HoverCard.Target props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | Target element |
| eventPropsWrapperName | string | - | Name of the prop to wrap event listeners in. Use when the target component expects event listeners in a nested object. For example, some components expect `componentProps={{ onMouseEnter, onMouseLeave }}`. |
| popupType | string | - | Popup accessible type |
| refProp | string | - | Key of the prop that should be used to access element ref |
**HoverCard.Group props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | `HoverCard` components |
| closeDelay | number | - | Close delay in ms |
| openDelay | number | - | Open delay in ms |
--------------------------------------------------------------------------------
### HueSlider
Package: @mantine/core
Import: import { HueSlider } from '@mantine/core';
Description: Slider component for selecting hue channel in color pickers (0 β 360 degrees)
## Usage
Use `HueSlider` component to allow users to select hue value of a color.
It accepts values from `0` to `360`. `HueSlider` is a part of [ColorPicker](https://alpha.mantine.dev/llms/core-color-picker.md) component,
but can also be used separately.
```tsx
import { useState } from 'react';
import { HueSlider, Text } from '@mantine/core';
function Demo() {
const [value, onChange] = useState(250);
return (
<>
Hue value: {value}
>
);
}
```
#### Props
**HueSlider props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| focusable | boolean | - | If set, slider thumb can be focused |
| onChange | (value: number) => void | - | Called when value changes |
| onChangeEnd | (value: number) => void | - | Called when user stops dragging the slider or uses keyboard to change value |
| onScrubEnd | () => void | - | Called when user stops dragging the slider |
| onScrubStart | () => void | - | Called when user starts dragging the slider |
| size | MantineSize | - | Slider size |
| value | number | required | Controlled component value |
#### Styles API
HueSlider component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**HueSlider selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| slider | .mantine-HueSlider-slider | Root element |
| sliderOverlay | .mantine-HueSlider-sliderOverlay | Element used to display various overlays over hue slider |
| thumb | .mantine-HueSlider-thumb | Thumb of the hue slider |
--------------------------------------------------------------------------------
### Image
Package: @mantine/core
Import: import { Image } from '@mantine/core';
Description: Image with optional fallback
## Usage
`Image` is a wrapper for `img` with minimal styles. By default, the image
will take 100% of the parent width. The image size can be controlled with `w`
and `h` [style props](https://alpha.mantine.dev/llms/styles-style-props.md).
```tsx
import { Image } from '@mantine/core';
function Demo() {
return (
);
}
```
## Image height
In most cases, you will need to set the image height to prevent layout jumps when
the image is loading. You can do so with the `h` [style props](https://alpha.mantine.dev/llms/styles-style-props.md).
```tsx
import { Image } from '@mantine/core';
function Demo() {
return (
);
}
```
## Image fit
By default the image has `object-fit: cover` style - it will
resize to cover the parent element. To change this behavior, set `w="auto"` and `fit="contain"` props.
```tsx
import { Image } from '@mantine/core';
function Demo() {
return (
);
}
```
## Fallback image
Set the `fallbackSrc` prop to display a fallback image when the image fails to load:
```tsx
import { Image } from '@mantine/core';
function Demo() {
return (
);
}
```
## Usage with Next.js Image
The `Image` component is a [polymorphic component](https://alpha.mantine.dev/llms/guides-polymorphic.md), its root element can be changed with the `component` prop.
You can use it with `next/image` and other similar components.
```tsx
import NextImage from 'next/image';
import { Image } from '@mantine/core';
import myImage from './my-image.jpg';
function Demo() {
return ;
}
```
#### Props
**Image props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| fallbackSrc | string | - | Image url used as a fallback if the image cannot be loaded |
| fit | ObjectFit | - | Controls `object-fit` style |
| onError | (event: SyntheticEvent) => void | - | Called when image fails to load |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| src | any | - | Image url |
#### Styles API
Image component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Image selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Image-root | Root element |
**Image CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --image-object-fit | Controls `object-fit` property |
| root | --image-radius | Controls `border-radius` property |
**Image data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-fallback | Image failed to load | - |
--------------------------------------------------------------------------------
### Indicator
Package: @mantine/core
Import: import { Indicator } from '@mantine/core';
Description: Display element at the corner of another element
## Usage
```tsx
import { Indicator, Avatar } from '@mantine/core';
function Demo() {
return (
);
}
```
## Inline
When the target element has a fixed width, set the `inline` prop to add `display: inline-block;` styles to
the Indicator container. Alternatively, you can set width and height with the `style` prop if you still want the root
element to keep `display: block`.
```tsx
import { Avatar, Indicator } from '@mantine/core';
function Demo() {
return (
);
}
```
## Offset
Set `offset` to change the indicator position. It is useful when the Indicator component is
used with children that have border-radius. You can provide a number for uniform offset or an
object with `x` and `y` properties for separate horizontal and vertical offsets:
```tsx
import { Avatar, Indicator } from '@mantine/core';
function Demo() {
return (
);
}
```
## Processing animation
```tsx
import { Avatar, Indicator } from '@mantine/core';
function Demo() {
return (
);
}
```
## Disabled
Set `disabled` to hide the indicator:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Avatar, Indicator, Button, Stack } from '@mantine/core';
function Demo() {
const [visible, { toggle }] = useDisclosure();
return (
);
}
```
## Max value
Set `maxValue` prop to display `{maxValue}+` when the label exceeds the maximum value. This is useful for
notification counters that should not show exact large numbers:
```tsx
import { Avatar, Group, Indicator } from '@mantine/core';
function Demo() {
return (
);
}
```
## Show zero
By default, the indicator is displayed when the label is `0`. Set `showZero={false}` to hide the indicator
when the label is `0`:
```tsx
import { Avatar, Group, Indicator } from '@mantine/core';
function Demo() {
return (
);
}
```
## Auto contrast
Set `autoContrast` prop to automatically adjust text color based on the background color to ensure
readable contrast:
```tsx
import { Avatar, Group, Indicator } from '@mantine/core';
function Demo() {
return (
);
}
```
#### Props
**Indicator props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoContrast | boolean | - | If set, adjusts text color based on background color |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color value |
| disabled | boolean | - | Hides the indicator when set |
| inline | boolean | - | Changes container display from block to inline-block, use when wrapping elements with fixed width |
| label | React.ReactNode | - | Label displayed inside the indicator, for example, notification count |
| maxValue | number | - | Maximum value to display. If label is a number greater than this value, it will be displayed as `{maxValue}+` |
| offset | number \| { x: number; y: number; } | - | Distance in pixels to offset the indicator from its default position, useful for elements with border-radius. Can be a number for uniform offset or an object with `x` and `y` properties for separate horizontal and vertical offsets |
| position | "bottom-end" \| "bottom-start" \| "top-end" \| "top-start" \| "bottom-center" \| "top-center" \| "middle-center" \| "middle-end" \| "middle-start" | - | Indicator position relative to the target element |
| processing | boolean | - | If set, the indicator has processing animation |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| showZero | boolean | - | Determines whether indicator with label `0` should be displayed |
| size | string \| number | - | Indicator width and height |
| withBorder | boolean | - | Adds border to the root element |
| zIndex | string \| number | - | Indicator z-index |
#### Styles API
Indicator component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Indicator selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Indicator-root | Root element |
| indicator | .mantine-Indicator-indicator | Indicator element |
**Indicator CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --indicator-bottom | Controls `bottom` style |
| root | --indicator-left | Controls `left` style |
| root | --indicator-right | Controls `right` style |
| root | --indicator-top | Controls `top` style |
| root | --indicator-radius | Controls `border-radius` |
| root | --indicator-size | Controls `min-width` and `height` |
| root | --indicator-translate-x | Controls `translateX` style, used for positioning |
| root | --indicator-translate-y | Controls `translateY` style, used for positioning |
| root | --indicator-z-index | Controls `z-index` style |
| root | --indicator-color | Controls `background-color` |
| root | --indicator-text-color | Controls `color` |
**Indicator data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-inline | `inline` prop is set | - |
| indicator | data-with-label | `label` prop is set | - |
| indicator | data-with-border | `withBorder` prop is set | - |
| indicator | data-processing | `processing` prop is set | - |
--------------------------------------------------------------------------------
### Input
Package: @mantine/core
Import: import { Input } from '@mantine/core';
Description: Base component to create custom inputs
## Disclaimer
**!important:** In most cases, you should not use `Input` in your application.
`Input` is a base for other inputs and was not designed to be used directly.
Use `Input` to create custom inputs. For other cases, prefer [TextInput](https://alpha.mantine.dev/llms/core-text-input.md)
or another component.
```tsx
import { Input, TextInput } from '@mantine/core';
// Incorrect usage, input is not accessible
function Incorrect() {
return (
);
}
// Use TextInput instead of Input everywhere you want to use Input,
// it is accessible by default and includes Input.Wrapper
function Correct() {
return (
);
}
```
## Usage
The `Input` component is used as a base for some other inputs ([NativeSelect](https://alpha.mantine.dev/llms/core-native-select.md), [TextInput](https://alpha.mantine.dev/llms/core-text-input.md), [Textarea](https://alpha.mantine.dev/llms/core-textarea.md), etc.).
The purpose of the `Input` is to provide shared styles and features to other inputs.
```tsx
import { Input } from '@mantine/core';
function Demo() {
return ;
}
```
## Loading state
Set `loading` prop to display a loading indicator. By default, the loader is displayed on the right side of the input.
You can change the position with the `loadingPosition` prop to `'left'` or `'right'`. This is useful for async operations like API calls, searches, or validations:
```tsx
import { Input } from '@mantine/core';
function Demo() {
return ;
}
```
## Input sections
Input supports left and right sections to display icons, buttons or other content alongside the input.
```tsx
import { useState } from 'react';
import { Input } from '@mantine/core';
import { AtIcon } from '@phosphor-icons/react';
function Demo() {
const [value, setValue] = useState('Clear me');
return (
<>
} />
setValue(event.currentTarget.value)}
rightSectionPointerEvents="all"
mt="md"
rightSection={
value ? (
setValue('')}
/>
) : null
}
/>
>
);
}
```
## Change input element
Input is a [polymorphic component](https://alpha.mantine.dev/llms/guides-polymorphic.md), the default root element is `input`,
but it can be changed to any other element or component.
Example of using `Input` as `button` and `select`:
```tsx
import { Input } from '@mantine/core';
import { CaretDownIcon } from '@phosphor-icons/react';
function Demo() {
return (
<>
Button input
}
pointer
mt="md"
>
>
);
}
```
Example of using [react-imask](https://github.com/uNmAnNeR/imaskjs/tree/master/packages/react-imask) with `Input`:
```tsx
import { Input } from '@mantine/core';
import { IMaskInput } from 'react-imask';
function Demo() {
return ;
}
```
## Input.Wrapper component
The `Input.Wrapper` component is used in all other inputs
([TextInput](https://alpha.mantine.dev/llms/core-text-input.md), [NativeSelect](https://alpha.mantine.dev/llms/core-native-select.md), [Textarea](https://alpha.mantine.dev/llms/core-textarea.md), etc.)
under the hood. You *do not need to wrap your inputs with it, as it is already included in all of them*.
Use `Input.Wrapper` only when you want to create custom inputs.
```tsx
import { Input } from '@mantine/core';
function Wrapper() {
return (
);
}
```
## inputWrapperOrder
`inputWrapperOrder` allows configuring the order of `Input.Wrapper` parts.
It accepts an array of four elements: `label`, `input`, `error` and `description`.
Note that it is not required to include all of them β you can use only those that you need.
Parts that are not included will not be rendered.
```tsx
import { TextInput } from '@mantine/core';
function Demo() {
return (
<>
>
);
}
```
## inputContainer
With the `inputContainer` prop, you can enhance inputs that use `Input.Wrapper` under the hood.
For example, you can add a [Tooltip](https://alpha.mantine.dev/llms/core-tooltip.md) to the [TextInput](https://alpha.mantine.dev/llms/core-text-input.md) when
the input is focused:
```tsx
import { useState } from 'react';
import { TextInput, Tooltip } from '@mantine/core';
function Demo() {
const [focused, setFocused] = useState(false);
return (
setFocused(true)}
onBlur={() => setFocused(false)}
inputContainer={(children) => (
{children}
)}
/>
);
}
```
## required and withAsterisk props
All components that are based on `Input.Wrapper` support `required` and `withAsterisk` props.
When set to true, both of these props will add a red asterisk to the end of the label.
The only difference is whether the input element will have the `required` attribute. Example with
the [TextInput](https://alpha.mantine.dev/llms/core-text-input.md) component:
```tsx
import { TextInput } from '@mantine/core';
// Will display required asterisk and add `required` attribute to the input element
function RequiredDemo() {
return ;
}
// Will only display the asterisk, `required` attribute is not added to the input element
function AsteriskDemo() {
return ;
}
```
## error prop
All inputs that use `Input.Wrapper` under the hood support the `error` prop.
When set to `true`, it will add a red border to the input. You can also pass a React node to display
an error message below the input. To only display an error message without a red border, set the `error` prop
to a React node and `withErrorStyles={false}`:
```tsx
import { TextInput } from '@mantine/core';
import { WarningCircleIcon } from '@phosphor-icons/react';
function Demo() {
return (
<>
}
/>
>
);
}
```
## Input.Label, Input.Description and Input.Error components
`Input.Label`, `Input.Error` and `Input.Description` components can be used to create custom
form layouts if the default `Input.Wrapper` layout does not meet your requirements.
```tsx
import { Input } from '@mantine/core';
function Demo() {
return (
<>
Input labelInput descriptionInput error
>
);
}
```
## Input.Placeholder component
`Input.Placeholder` component can be used to add a placeholder to `Input` and `InputBase` components that are based on the `button` element
or do not support the placeholder property natively:
```tsx
import { Input } from '@mantine/core';
function Demo() {
return (
Placeholder content
);
}
```
## Input.ClearButton component
Use the `Input.ClearButton` component to add a clear button to custom inputs
based on the `Input` component. The `size` of the clear button is automatically
inherited from the input:
```tsx
import { Input } from '@mantine/core';
function Demo(){
const [value, setValue] = useState('clearable');
return (
setValue(event.currentTarget.value)}
rightSection={value !== '' ? setValue('')} /> : undefined}
rightSectionPointerEvents="auto"
size="sm"
/>
);
}
```
## Default props on theme
You can add [default props](https://alpha.mantine.dev/llms/theming-default-props.md) on the [theme](https://alpha.mantine.dev/llms/theming-theme-object.md)
to `Input` and `Input.Wrapper` components. These default props will be inherited by all inputs
that use `Input` and `Input.Wrapper` under the hood ([TextInput](https://alpha.mantine.dev/llms/core-text-input.md), [NativeSelect](https://alpha.mantine.dev/llms/core-native-select.md), [Textarea](https://alpha.mantine.dev/llms/core-textarea.md), etc.):
```tsx
import { TextInput, NativeSelect, MantineProvider, createTheme, Input } from '@mantine/core';
const theme = createTheme({
components: {
Input: Input.extend({
defaultProps: {
variant: 'filled',
},
}),
InputWrapper: Input.Wrapper.extend({
defaultProps: {
inputWrapperOrder: ['label', 'input', 'description', 'error'],
},
}),
},
});
function Demo() {
return (
);
}
```
## Styles on theme
Same as with default props, you can use `Input` and `Input.Wrapper` [Styles API](https://alpha.mantine.dev/llms/styles-styles-api.md)
on the [theme](https://alpha.mantine.dev/llms/theming-theme-object.md) to add styles to all inputs:
```tsx
// Demo.tsx
import { TextInput, NativeSelect, MantineProvider, createTheme, Input } from '@mantine/core';
import classes from './Demo.module.css';
const theme = createTheme({
components: {
Input: Input.extend({
classNames: {
input: classes.input,
},
}),
InputWrapper: Input.Wrapper.extend({
classNames: {
label: classes.label,
},
}),
},
});
function Demo() {
return (
);
}
// Demo.module.css
.label {
background-color: var(--mantine-color-blue-light);
}
.input {
border: 1px solid var(--mantine-color-violet-filled);
}
```
## Change focus styles
Use `&:focus-within` selector to change inputs focus styles. You can apply these styles to
one component with `classNames` prop or to all inputs with [Styles API](https://alpha.mantine.dev/llms/styles-styles-api.md)
on [theme](https://alpha.mantine.dev/llms/theming-theme-object.md).
```tsx
// Demo.module.css
.input {
transition: none;
&:focus-within {
outline: 2px solid var(--mantine-color-blue-filled);
border-color: transparent;
}
}
// Demo.tsx
import { Input, TextInput } from '@mantine/core';
import classes from './Demo.module.css';
function Demo() {
return (
<>
>
);
}
```
## InputBase component
`InputBase` component combines `Input` and `Input.Wrapper` components and supports `component` prop:
```tsx
import { InputBase } from '@mantine/core';
import { IMaskInput } from 'react-imask';
function Demo() {
return (
<>
>
);
}
```
## Accessibility
If you use `Input` component without associated label element, set `aria-label`:
```tsx
import { Input } from '@mantine/core';
// ok β the input is labelled by the aria-label
function WithAriaLabel() {
return ;
}
// ok β the input is labelled by the label element
function WithLabel() {
return (
<>
>
);
}
```
When you use `Input` with `Input.Wrapper` it is required to set `id` on both components
to connect label and other elements with the input:
```tsx
import { Input } from '@mantine/core';
function Demo() {
return (
);
}
```
You can use [use-id](https://alpha.mantine.dev/llms/hooks-use-id.md) to generate unique ids:
```tsx
import { Input } from '@mantine/core';
import { useId } from '@mantine/hooks';
function Demo() {
const id = useId();
return (
);
}
```
#### Props
**Input props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| disabled | boolean | - | Sets `disabled` attribute on the `input` element |
| error | React.ReactNode | - | Determines whether the input should have error styles and `aria-invalid` attribute |
| id | string | - | Input element id |
| inputSize | string | - | HTML `size` attribute for the input element (number of visible characters) |
| leftSection | React.ReactNode | - | Content section displayed on the left side of the input |
| leftSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `leftSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| leftSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `leftSection` element |
| leftSectionWidth | React.CSSProperties["width"] | - | Left section width, used to set `width` of the section and input `padding-left`, by default equals to the input height |
| loading | boolean | - | Displays loading indicator in the left or right section |
| loadingPosition | "left" \| "right" | - | Position of the loading indicator |
| multiline | boolean | - | Adjusts padding and sizing calculations for multiline inputs (use with `component="textarea"`). Does not make the input multiline by itself. |
| pointer | boolean | - | Determines whether the input should have `cursor: pointer` style. Use when input acts as a button-like trigger (e.g., `component="button"` for Select/DatePicker). |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem |
| required | boolean | - | Sets `required` attribute on the `input` element |
| rightSection | React.ReactNode | - | Content section displayed on the right side of the input |
| rightSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `rightSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| rightSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `rightSection` element |
| rightSectionWidth | React.CSSProperties["width"] | - | Right section width, used to set `width` of the section and input `padding-right`, by default equals to the input height |
| size | MantineSize | - | Controls input `height`, horizontal `padding`, and `font-size` |
| withAria | boolean | - | Determines whether `aria-` and other accessibility attributes should be added to the input. Only disable when implementing custom accessibility handling. |
| withErrorStyles | boolean | - | Determines whether the input should have red border and red text color when the `error` prop is set |
| wrapperProps | WrapperProps | - | Props passed down to the root element of the `Input` component |
**Input.Base props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| description | React.ReactNode | - | Contents of `Input.Description` component. If not set, description is not displayed. |
| descriptionProps | InputDescriptionProps | - | Props passed down to the `Input.Description` component |
| disabled | boolean | - | Sets `disabled` attribute on the `input` element |
| error | React.ReactNode | - | Contents of `Input.Error` component. If not set, error is not displayed. |
| errorProps | InputErrorProps | - | Props passed down to the `Input.Error` component |
| inputContainer | (children: ReactNode) => ReactNode | - | Render function to wrap the input element. Useful for adding tooltips, popovers, or other wrappers around the input. |
| inputSize | string | - | HTML `size` attribute for the input element (number of visible characters) |
| inputWrapperOrder | ("input" \| "label" \| "description" \| "error")[] | - | Controls order and visibility of wrapper elements. Only elements included in this array will be rendered. |
| label | React.ReactNode | - | Contents of `Input.Label` component. If not set, label is not displayed. |
| labelProps | InputLabelProps | - | Props passed down to the `Input.Label` component |
| leftSection | React.ReactNode | - | Content section displayed on the left side of the input |
| leftSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `leftSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| leftSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `leftSection` element |
| leftSectionWidth | React.CSSProperties["width"] | - | Left section width, used to set `width` of the section and input `padding-left`, by default equals to the input height |
| loading | boolean | - | Displays loading indicator in the left or right section |
| loadingPosition | "left" \| "right" | - | Position of the loading indicator |
| multiline | boolean | - | If set, the input can have multiple lines, for example when `component="textarea"` |
| pointer | boolean | - | Determines whether the input should have `cursor: pointer` style. Use when input acts as a button-like trigger (e.g., `component="button"` for Select/DatePicker). |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem |
| required | boolean | - | Adds required attribute to the input and a red asterisk on the right side of label |
| rightSection | React.ReactNode | - | Content section displayed on the right side of the input |
| rightSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `rightSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| rightSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `rightSection` element |
| rightSectionWidth | React.CSSProperties["width"] | - | Right section width, used to set `width` of the section and input `padding-right`, by default equals to the input height |
| size | MantineSize | - | Controls input `height`, horizontal `padding`, and `font-size` |
| withAria | boolean | - | If set, `aria-` and other accessibility attributes are added to the input |
| withAsterisk | boolean | - | If set, the required asterisk is displayed next to the label. Overrides `required` prop. Does not add required attribute to the input. |
| withErrorStyles | boolean | - | Determines whether the input should have red border and red text color when the `error` prop is set |
| wrapperProps | React.ComponentProps<"div"> | - | Props passed down to the root element (`Input.Wrapper` component) |
**Input.Label props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| labelElement | "div" \| "label" | - | Root element of the label |
| required | boolean | - | If set, the required asterisk is displayed next to the label |
| size | MantineFontSize | - | Controls label `font-size` |
**Input.Wrapper props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| description | React.ReactNode | - | Contents of `Input.Description` component. If not set, description is not displayed. |
| descriptionProps | InputDescriptionProps | - | Props passed down to the `Input.Description` component |
| error | React.ReactNode | - | Contents of `Input.Error` component. If not set, error is not displayed. |
| errorProps | InputErrorProps | - | Props passed down to the `Input.Error` component |
| id | string | - | Static id used as base to generate `aria-` attributes, by default generates random id |
| inputContainer | (children: ReactNode) => ReactNode | - | Render function to wrap the input element. Useful for adding tooltips, popovers, or other wrappers around the input. |
| inputWrapperOrder | ("input" \| "label" \| "description" \| "error")[] | - | Controls order and visibility of wrapper elements. Only elements included in this array will be rendered. |
| label | React.ReactNode | - | Contents of `Input.Label` component. If not set, label is not displayed. |
| labelElement | "div" \| "label" | - | Root element for the label. Use `'div'` when wrapper contains multiple input elements and you need to handle `htmlFor` manually. |
| labelProps | InputLabelProps | - | Props passed down to the `Input.Label` component |
| required | boolean | - | Adds required attribute to the input and a red asterisk on the right side of label |
| size | MantineFontSize | - | Controls size of `Input.Label`, `Input.Description` and `Input.Error` components |
| withAsterisk | boolean | - | If set, the required asterisk is displayed next to the label. Overrides `required` prop. Does not add required attribute to the input. |
**Input.Description props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| size | MantineFontSize | - | Controls description `font-size` |
**Input.Error props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| size | MantineFontSize | - | Controls error `font-size` |
#### Styles API
Input component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Input selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| wrapper | .mantine-Input-wrapper | Root element of the Input |
| input | .mantine-Input-input | Input element |
| section | .mantine-Input-section | Left and right sections |
**Input CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| wrapper | --input-fz | `font-size` of the input element |
| wrapper | --input-left-section-width | `width` of the left section |
| wrapper | --input-right-section-width | `width` of the right section |
| wrapper | --input-padding-y | `padding-top` and `padding-bottom` of the input element |
| wrapper | --input-radius | `border-radius` of the input element |
| wrapper | --input-left-section-pointer-events | Controls `pointer-events` of the left section |
| wrapper | --input-right-section-pointer-events | Controls `pointer-events` of the right section |
**Inputwrapper selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Inputwrapper-root | Root element |
| label | .mantine-Inputwrapper-label | Label element |
| required | .mantine-Inputwrapper-required | Required asterisk element, rendered inside label |
| description | .mantine-Inputwrapper-description | Description element |
| error | .mantine-Inputwrapper-error | Error element |
**Inputwrapper CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| label | --input-label-size | Controls label `font-size` |
| label | --input-asterisk-color | Controls label asterisk text `color` |
**Inputbase selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| wrapper | .mantine-Inputbase-wrapper | Root element of the Input |
| input | .mantine-Inputbase-input | Input element |
| section | .mantine-Inputbase-section | Left and right sections |
| root | .mantine-Inputbase-root | Root element |
| label | .mantine-Inputbase-label | Label element |
| required | .mantine-Inputbase-required | Required asterisk element, rendered inside label |
| description | .mantine-Inputbase-description | Description element |
| error | .mantine-Inputbase-error | Error element |
--------------------------------------------------------------------------------
### JsonInput
Package: @mantine/core
Import: import { JsonInput } from '@mantine/core';
Description: Capture json data from user
## Usage
`JsonInput` is based on the [Textarea](https://alpha.mantine.dev/llms/core-textarea.md) component.
It includes JSON validation logic and an option to format the input value on blur:
```tsx
import { JsonInput } from '@mantine/core';
function Demo() {
return (
);
}
```
## Loading state
Set `loading` prop to display a loading indicator. By default, the loader is displayed on the right side of the input.
You can change the position with the `loadingPosition` prop to `'left'` or `'right'`. This is useful for async operations like API calls, searches, or validations:
```tsx
import { JsonInput } from '@mantine/core';
function Demo() {
return ;
}
```
## Controlled
```tsx
import { useState } from 'react';
import { JsonInput } from '@mantine/core';
function Demo() {
const [value, setValue] = useState('');
return ;
}
```
## Uncontrolled
`JsonInput` can be used with uncontrolled forms the same way as a native `textarea` element.
Set the `name` attribute to include json input value in `FormData` object on form submission.
To control the initial value in uncontrolled forms, use the `defaultValue` prop.
Example usage of uncontrolled `JsonInput` with `FormData`:
```tsx
import { JsonInput } from '@mantine/core';
function Demo() {
return (
);
}
```
## Custom serialization
You can provide custom `serialize` and `deserialize` functions to support data formats beyond standard JSON.
This is useful when you need to handle types like `Date`, `Map`, `Set`, `undefined`, or other non-JSON-serializable values.
The example below shows how to use [superjson](https://github.com/blitz-js/superjson) library to handle extended data types:
```tsx
import { useState } from 'react';
import { JsonInput } from '@mantine/core';
import superjson from 'superjson';
function Demo() {
const [value, setValue] = useState(
superjson.stringify(
{
name: 'John Doe',
createdAt: new Date(),
tags: new Set(['admin', 'user']),
metadata: new Map([['role', 'developer']]),
},
null,
2
)
);
return (
superjson.stringify(val, null, 2)}
deserialize={superjson.parse}
validationError="Invalid extended JSON format"
formatOnBlur
autosize
minRows={6}
/>
);
}
```
The `deserialize` function must throw an error when the input is invalid. Both `serialize` and `deserialize`
functions are used for formatting when `formatOnBlur` is enabled.
## Input props
JsonInput component supports [Input](https://mantine.dev/core/input) and [Input.Wrapper](https://mantine.dev/core/input) components features and all textarea element props. JsonInput documentation does not include all features supported by the component β see [Input](https://mantine.dev/core/input) documentation to learn about all available features.
```tsx
import { JsonInput } from '@mantine/core';
function Demo() {
return (
);
}
```
#### Props
**JsonInput props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autosize | boolean | - | If set, enables textarea height growing with its content |
| defaultValue | string | - | Uncontrolled component default value |
| description | React.ReactNode | - | Contents of `Input.Description` component. If not set, description is not displayed. |
| descriptionProps | InputDescriptionProps | - | Props passed down to the `Input.Description` component |
| deserialize | ((text: string, reviver?: ((this: any, key: string, value: any) => any)) => any) \| undefined | - | Function to deserialize string value for formatting and validation. Must throw an error if the string is invalid JSON. |
| disabled | boolean | - | Sets `disabled` attribute on the `input` element |
| error | React.ReactNode | - | Contents of `Input.Error` component. If not set, error is not displayed. |
| errorProps | InputErrorProps | - | Props passed down to the `Input.Error` component |
| formatOnBlur | boolean | - | Determines whether the value should be formatted on blur |
| indentSpaces | number | - | Number of spaces to use as white space for formatting. Passed as the third argument to `serialize` function. |
| inputContainer | (children: ReactNode) => ReactNode | - | Render function to wrap the input element. Useful for adding tooltips, popovers, or other wrappers around the input. |
| inputSize | string | - | HTML `size` attribute for the input element (number of visible characters) |
| inputWrapperOrder | ("input" \| "label" \| "description" \| "error")[] | - | Controls order and visibility of wrapper elements. Only elements included in this array will be rendered. |
| label | React.ReactNode | - | Contents of `Input.Label` component. If not set, label is not displayed. |
| labelProps | InputLabelProps | - | Props passed down to the `Input.Label` component |
| leftSection | React.ReactNode | - | Content section displayed on the left side of the input |
| leftSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `leftSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| leftSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `leftSection` element |
| leftSectionWidth | React.CSSProperties["width"] | - | Left section width, used to set `width` of the section and input `padding-left`, by default equals to the input height |
| loading | boolean | - | Displays loading indicator in the left or right section |
| loadingPosition | "left" \| "right" | - | Position of the loading indicator |
| maxRows | number | - | Maximum rows for autosize textarea to grow, ignored if `autosize` prop is not set |
| minRows | number | - | Minimum rows of autosize textarea, ignored if `autosize` prop is not set |
| onChange | (value: string) => void | - | Called when value changes |
| pointer | boolean | - | Determines whether the input should have `cursor: pointer` style. Use when input acts as a button-like trigger (e.g., `component="button"` for Select/DatePicker). |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem |
| required | boolean | - | Adds required attribute to the input and a red asterisk on the right side of label |
| resize | Resize | - | Controls `resize` CSS property |
| rightSection | React.ReactNode | - | Content section displayed on the right side of the input |
| rightSectionPointerEvents | React.CSSProperties["pointerEvents"] | - | Sets `pointer-events` styles on the `rightSection` element. Use `'all'` when section contains interactive elements (buttons, links). |
| rightSectionProps | React.ComponentProps<"div"> | - | Props passed down to the `rightSection` element |
| rightSectionWidth | React.CSSProperties["width"] | - | Right section width, used to set `width` of the section and input `padding-right`, by default equals to the input height |
| serialize | { (value: any, replacer?: ((this: any, key: string, value: any) => any), space?: string \| number \| undefined): string; (value: any, replacer?: (string \| number)[] \| null \| undefined, space?: string \| ... 1 more ... \| undefined): string; } \| undefined | - | Function to serialize value into a string for formatting. Called with (value, null, 2) where 2 is the indentation level. |
| size | MantineSize | - | Controls input `height`, horizontal `padding`, and `font-size` |
| validationError | React.ReactNode | - | Error message shown when the input value is invalid JSON (checked on blur). If not provided, a generic error state is shown. Takes precedence over the `error` prop when validation fails. |
| value | string | - | Controlled component value |
| withAsterisk | boolean | - | If set, the required asterisk is displayed next to the label. Overrides `required` prop. Does not add required attribute to the input. |
| withErrorStyles | boolean | - | Determines whether the input should have red border and red text color when the `error` prop is set |
| wrapperProps | WrapperProps | - | Props passed down to the root element |
#### Styles API
JsonInput component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**JsonInput selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| wrapper | .mantine-JsonInput-wrapper | Root element of the Input |
| input | .mantine-JsonInput-input | Input element |
| section | .mantine-JsonInput-section | Left and right sections |
| root | .mantine-JsonInput-root | Root element |
| label | .mantine-JsonInput-label | Label element |
| required | .mantine-JsonInput-required | Required asterisk element, rendered inside label |
| description | .mantine-JsonInput-description | Description element |
| error | .mantine-JsonInput-error | Error element |
--------------------------------------------------------------------------------
### Kbd
Package: @mantine/core
Import: import { Kbd } from '@mantine/core';
Description: Display keyboard key
## Usage
```tsx
import { Kbd } from '@mantine/core';
function Demo() {
return (
β + Shift + M
);
}
```
## Size
```tsx
import { Kbd } from '@mantine/core';
function Demo() {
return Shift;
}
```
#### Props
**Kbd props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| size | MantineSize \| number | - | Controls `font-size` and `padding` |
#### Styles API
Kbd component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Kbd selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Kbd-root | Root element |
**Kbd CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --kbd-fz | Controls `font-size` |
--------------------------------------------------------------------------------
### List
Package: @mantine/core
Import: import { List } from '@mantine/core';
Description: Display ordered or unordered list
## Usage
```tsx
import { List } from '@mantine/core';
function Demo() {
return (
Clone or download repository from GitHubInstall dependencies with yarnTo start development server run npm start commandRun tests to make sure your changes do not break the buildSubmit a pull request once you are done
);
}
```
## With icons
You can replace list bullets with an icon. To do so, provide the following props:
* `icon` on the List component will be used as the default icon for all list elements
* `icon` on the List.Item component will override the context icon from List
* `spacing` β spacing between list items from the theme or any valid CSS value to set spacing, defaults to `0`
* `center` β center item content with the icon
* `size` β set font size from the theme
```tsx
import { List, ThemeIcon } from '@mantine/core';
import { CheckCircleIcon, CircleDashedIcon } from '@phosphor-icons/react';
function Demo() {
return (
}
>
Clone or download repository from GitHubInstall dependencies with yarnTo start development server run npm start commandRun tests to make sure your changes do not break the build
}
>
Submit a pull request once you are done
);
}
```
## Nested lists
Set the `withPadding` prop to offset nested lists and `listStyleType` to control the bullet type:
```tsx
import { List } from '@mantine/core';
function Demo() {
return (
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
First order item
First order item with list
Nested itemNested item
Nested item with list
Even more nestedEven more nestedNested itemFirst order item
);
}
```
## Ordered list numbering
### Start from specific number
Use the `start` prop to begin numbering from a specific value:
```tsx
import { List } from '@mantine/core';
function Demo() {
return (
This is item #5This is item #6This is item #7This is item #8
);
}
```
### Reversed numbering
Use the `reversed` prop to create countdown lists:
```tsx
import { List } from '@mantine/core';
function Demo() {
return (
This is item #3This is item #2This is item #1
);
}
```
### Custom item values
Use the `value` prop on individual `List.Item` components to set specific numbers:
```tsx
import { List } from '@mantine/core';
function Demo() {
return (
First itemThis item is #5This item is #6 (continues from previous)This item is #10This item is #11
);
}
```
#### Props
**List props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| center | boolean | - | Vertically centers list items with their icons |
| children | React.ReactNode | - | `List.Item` components |
| icon | React.ReactNode | - | Icon to replace default list markers. Applied to all items unless overridden on individual List.Item components |
| listStyleType | ListStyleType | - | Controls CSS `list-style-type` property. Overrides the default list marker style based on list type |
| reversed | boolean | - | Reverses the order of list items (only works with type="ordered") |
| size | MantineSize | - | Controls `font-size` and `line-height` |
| spacing | MantineSpacing | - | Key of `theme.spacing` or any valid CSS value to set spacing between items |
| start | number | - | Starting value for ordered list numbering (only works with type="ordered") |
| type | "ordered" \| "unordered" | - | List type |
| withPadding | boolean | - | Adds extra horizontal padding to the list, useful for nested lists |
**List.Item props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Item content |
| icon | React.ReactNode | - | Icon to replace item bullet |
#### Styles API
List component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**List selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-List-root | Root element |
| item | .mantine-List-item | ListItem root element |
| itemIcon | .mantine-List-itemIcon | ListItem icon |
| itemLabel | .mantine-List-itemLabel | ListItem content |
| itemWrapper | .mantine-List-itemWrapper | ListItem wrapper element, container, icon and content |
**List CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --list-fz | Controls `font-size` |
| root | --list-lh | Controls `line-height` |
| root | --list-spacing | Controls spacing between items |
**List data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-with-padding | `withPadding` prop is set | - |
| item | data-centered | `center` prop is set on List component | - |
| item | data-with-icon | `icon` prop is set on ListItem component | - |
--------------------------------------------------------------------------------
### Loader
Package: @mantine/core
Import: import { Loader } from '@mantine/core';
Description: Indicate loading state
## Usage
The `Loader` component supports 3 types of loaders by default: `oval`, `bars`, and `dots`. All
loaders are animated with CSS for better performance.
```tsx
import { Loader } from '@mantine/core';
function Demo() {
return ;
}
```
## Size prop
You can pass any valid CSS values or numbers to the `size` prop. Numbers are treated as px, but
converted to [rem](https://alpha.mantine.dev/llms/styles-rem.md). For example, `size={32}` will produce the
`--loader-size: 2rem` CSS variable.
```tsx
import { Loader } from '@mantine/core';
function Demo() {
return ;
}
```
## Adding custom loaders
The `Loader` component is used in other components ([Button](https://alpha.mantine.dev/llms/core-button.md), [ActionIcon](https://alpha.mantine.dev/llms/core-action-icon.md), [LoadingOverlay](https://alpha.mantine.dev/llms/core-loading-overlay.md), etc.).
You can change the loader type with [default props](https://alpha.mantine.dev/llms/theming-default-props.md) by setting `type`.
You can also add a custom CSS or SVG loader with the `loaders` [default prop](https://alpha.mantine.dev/llms/theming-default-props.md).
### Custom CSS only loader
Note that in order for the `size` and `color` props to work with custom loaders, you need to
use the `--loader-size` and `--loader-color` CSS variables in your loader styles.
```tsx
import { MantineProvider, Loader } from '@mantine/core';
import { CssLoader } from './CssLoader';
const theme = createTheme({
components: {
Loader: Loader.extend({
defaultProps: {
loaders: { ...Loader.defaultLoaders, custom: CssLoader },
type: 'custom',
},
}),
},
});
function Demo() {
return (
);
}
```
### Custom SVG loader
It is recommended to use CSS-only loaders, as SVG-based animations may have the following issues:
* High CPU usage β the loader may look glitchy on low-end devices
* Loader animation may not start playing until JS is loaded β users may see a static loader
In your SVG loader, you need to use the `--loader-size` and `--loader-color` variables the same
way as in CSS-only custom loaders in order for the `size` and `color` props to work. Usually,
you would need to set `width` and `height` to `var(--loader-size)` and `fill`/`stroke` to
`var(--loader-color)`.
```tsx
import { MantineProvider, Loader } from '@mantine/core';
import { RingLoader } from './RingLoader';
const theme = createTheme({
components: {
Loader: Loader.extend({
defaultProps: {
loaders: { ...Loader.defaultLoaders, ring: RingLoader },
type: 'ring',
},
}),
},
});
function Demo() {
return (
);
}
```
## children prop
The `Loader` supports the `children` prop. If you pass anything to `children`, it will be rendered
instead of the loader. This is useful when you want to control the `Loader` representation
in components that use `loaderProps`, for example [Button](https://alpha.mantine.dev/llms/core-button.md), [LoadingOverlay](https://alpha.mantine.dev/llms/core-loading-overlay.md), [Dropzone](https://alpha.mantine.dev/llms/x-dropzone.md).
```tsx
import { useDisclosure } from '@mantine/hooks';
import { LoadingOverlay, Button, Group, Box } from '@mantine/core';
function Demo() {
const [visible, { toggle }] = useDisclosure(false);
return (
<>
{/* ...other content */}
>
);
}
```
#### Props
**Loader props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Overrides default loader with given content |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
| loaders | Partial> | - | Object of loaders components, can be customized via default props or inline. |
| size | MantineSize \| number | - | Controls `width` and `height` of the loader. `Loader` has predefined `xs`-`xl` values. Numbers are converted to rem. |
| type | (string & {}) \| "bars" \| "dots" \| "oval" | - | Loader type, key of `loaders` prop |
#### Styles API
Loader component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Loader selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Loader-root | Root element |
**Loader CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --loader-color | Control loader color |
--------------------------------------------------------------------------------
### LoadingOverlay
Package: @mantine/core
Import: import { LoadingOverlay } from '@mantine/core';
Description: An overlay with centered loader
## Usage
`LoadingOverlay` renders an overlay with a loader over the parent element with relative position.
It is usually used to indicate the loading state of forms.
Note that elements under the overlay are still focusable with the keyboard, so remember to add additional logic to handle this case.
The `LoadingOverlay` rendering is controlled by the `visible` prop:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { LoadingOverlay, Button, Group, Box } from '@mantine/core';
function Demo() {
const [visible, { toggle }] = useDisclosure(false);
// Note that position: relative is required
return (
<>
{/* ...other content */}
>
);
}
```
## Loader props
You can pass props down to the [Loader](https://alpha.mantine.dev/llms/core-loader.md) component with `loaderProps`:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { LoadingOverlay, Button, Group, Box } from '@mantine/core';
function Demo() {
const [visible, { toggle }] = useDisclosure(true);
// Note that position: relative is required
return (
<>
{/* ...other content */}
>
);
}
```
## Custom inline loaders
To replace the default loader with any custom content, set `loaderProps={{ children:
Your content
}}`.
You can put any React node inside `loaderProps.children`:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { LoadingOverlay, Button, Group, Box } from '@mantine/core';
function Demo() {
const [visible, { toggle }] = useDisclosure(false);
return (
<>
{/* ...other content */}
>
);
}
```
#### Props
**LoadingOverlay props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| loaderProps | LoaderProps | - | Props passed down to `Loader` component |
| onEnter | () => void | - | Called when transition starts |
| onEntered | () => void | - | Called when transition ends |
| onExit | () => void | - | Called when exit transition starts |
| onExited | () => void | - | Called when exit transition ends |
| overlayProps | OverlayProps | - | Props passed down to `Overlay` component. Use to customizing blur, opacity, color and other properties. |
| transitionProps | TransitionProps | - | Props passed down to `Transition` component. Set `duration` to create custom transition or override default transition. |
| visible | boolean | - | Controls overlay visibility. Typically used with state (useState, useDisclosure). |
| zIndex | string \| number | - | Controls `z-index` of both the overlay and loader. The loader receives `z-index + 1`. |
#### Styles API
LoadingOverlay component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**LoadingOverlay selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-LoadingOverlay-root | Root element |
| overlay | .mantine-LoadingOverlay-overlay | `Overlay` component |
| loader | .mantine-LoadingOverlay-loader | `Loader` component |
**LoadingOverlay CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --lo-z-index | Controls `z-index` of the overlay and loader |
--------------------------------------------------------------------------------
### Mark
Package: @mantine/core
Import: import { Mark } from '@mantine/core';
Description: Highlight part of the text
## Usage
```tsx
import { Text, Mark } from '@mantine/core';
function Demo() {
return (
Highlight this chunk of the text
);
}
```
#### Props
**Mark props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
#### Styles API
Mark component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Mark selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Mark-root | Root element |
**Mark CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --mark-bg-dark | Controls `background-color` in dark color scheme |
| root | --mark-bg-light | Controls `background-color` for light color scheme |
--------------------------------------------------------------------------------
### Marquee
Package: @mantine/core
Import: import { Marquee } from '@mantine/core';
Description: Create continuous scrolling animation for content
## Usage
`Marquee` component creates a continuous scrolling animation for its children.
It is commonly used for displaying logos, testimonials, or any repeating content.
```tsx
import { Marquee } from '@mantine/core';
import { MantineLogo } from '@mantinex/mantine-logo';
function Demo() {
return (
);
}
```
## Pause on hover
Set `pauseOnHover` prop to pause the animation when the user hovers over the component:
```tsx
import { Marquee } from '@mantine/core';
import { MantineLogo } from '@mantinex/mantine-logo';
function Demo() {
return (
);
}
```
## Vertical orientation
Set `orientation="vertical"` to scroll content vertically. Note that you need to set
a fixed height on the container for vertical scrolling:
```tsx
import { Marquee } from '@mantine/core';
import { MantineLogo } from '@mantinex/mantine-logo';
function Demo() {
return (
);
}
```
## Multiple rows
You can combine multiple `Marquee` components with different directions to create
more complex layouts:
```tsx
import { Marquee, Stack } from '@mantine/core';
import { MantineLogo } from '@mantinex/mantine-logo';
function Demo() {
return (
);
}
```
## Fade edges
By default, `Marquee` displays gradient fade on edges to create a smooth transition effect.
You can customize the fade using the following props:
* `fadeEdges` β enables/disables fade gradient (default: `true`)
* `fadeEdgeColor` β color of the fade gradient (default: `var(--mantine-color-body)`)
* `fadeEdgeSize` β size of the fade area (default: `5%`)
```tsx
import { Marquee, Stack, Text } from '@mantine/core';
import { MantineLogo } from '@mantinex/mantine-logo';
function Demo() {
return (
Default fade (5%)
Larger fade (15%)
Custom fade color
No fade
);
}
```
## Customization
Use the following props to customize the marquee behavior:
* `reverse` β reverses animation direction
* `pauseOnHover` β pauses animation on hover
* `orientation` β `horizontal` (default) or `vertical` scroll direction
* `repeat` β number of times children are repeated for seamless scrolling (default: 4)
* `duration` β animation duration in ms (default: 40000)
* `gap` β gap between repeated children, key of `theme.spacing` or any valid CSS value
```tsx
import { Marquee } from '@mantine/core';
import { MantineLogo } from '@mantinex/mantine-logo';
function Demo() {
return (
);
}
```
#### Props
**Marquee props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | Content to scroll |
| duration | number | - | Animation duration in ms |
| fadeEdgeColor | string | - | Color of the fade gradient, |
| fadeEdgeSize | string | - | Size of the fade gradient, |
| fadeEdges | boolean | - | Whether to show gradient fade on edges, |
| gap | MantineSpacing | - | Gap between repeated children, key of `theme.spacing` or any valid CSS value |
| orientation | "horizontal" \| "vertical" | - | Scroll orientation |
| pauseOnHover | boolean | - | Pauses animation on hover |
| repeat | number | - | Number of times children are repeated inline for seamless scrolling |
| reverse | boolean | - | Reverses animation direction |
#### Styles API
Marquee component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Marquee selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Marquee-root | Root element |
| content | .mantine-Marquee-content | Animated scrolling container |
| group | .mantine-Marquee-group | Repeated children wrapper |
**Marquee CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --marquee-duration | Controls animation duration |
| root | --marquee-gap | Controls gap between items |
| root | --marquee-repeat | Number of times content is repeated |
| root | --marquee-fade-color | Controls the fade edge gradient color |
| root | --marquee-fade-size | Controls the size of the fade gradient |
**Marquee data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-orientation | Value depends on `orientation` prop | horizontal \| vertical |
| root | data-reverse | `reverse` prop is set | - |
| root | data-pause-on-hover | `pauseOnHover` prop is set | - |
| root | data-fade-edges | `fadeEdges` prop is `true` (default) | - |
--------------------------------------------------------------------------------
### Menu
Package: @mantine/core
Import: import { Menu } from '@mantine/core';
Description: Combine a list of secondary actions into single interactive area
## Usage
```tsx
import { Menu, Button, Text } from '@mantine/core';
import { GearSixIcon, MagnifyingGlassIcon, ImageIcon, ChatCircleIcon, TrashIcon, IconArrowsLeftRight } from '@phosphor-icons/react';
function Demo() {
return (
);
}
```
## Submenus
```tsx
import { Button, Menu } from '@mantine/core';
function Demo() {
return (
);
}
```
## Controlled
The dropdown's opened state can be controlled with the `opened` and `onChange` props:
```tsx
import { useState } from 'react';
import { Menu } from '@mantine/core';
function Demo() {
const [opened, setOpened] = useState(false);
return (
);
}
```
## Show menu on hover
Set `trigger="hover"` to reveal the dropdown when hovering over the menu target and dropdown.
The `closeDelay` and `openDelay` props can be used to control open and close delay in ms.
Note that:
* If you set `closeDelay={0}` then the menu will close before the user reaches the dropdown, so set `offset={0}` to remove space between the target element and dropdown.
* Menu with `trigger="hover"` is not accessible β users that navigate with the keyboard will not be able to use it. If you need both hover and click triggers, use `trigger="click-hover"`.
```tsx
import { Menu } from '@mantine/core';
function Demo() {
return (
);
}
```
To make a `Menu` that is revealed on hover accessible on all devices, use `trigger="click-hover"` instead.
The dropdown will be revealed on hover on desktop and on click on mobile devices.
```tsx
import { Menu } from '@mantine/core';
function Demo() {
return (
);
}
```
## Disabled items
```tsx
import { Menu, Button } from '@mantine/core';
import { MagnifyingGlassIcon } from '@phosphor-icons/react';
function Demo() {
return (
);
}
```
## Dropdown position
```tsx
import { Menu } from '@mantine/core';
function Demo() {
return (
);
}
```
## Transitions
The Menu dropdown can be animated with any of the premade transitions from the [Transition](https://alpha.mantine.dev/llms/core-transition.md) component:
```tsx
import { Menu } from '@mantine/core';
function Demo() {
return (
);
}
```
## Custom component as Menu.Item
By default, `Menu.Item` renders as a button element. To change that, set the `component` prop:
```tsx
import { Menu, Button } from '@mantine/core';
import { ArrowSquareOutIcon } from '@phosphor-icons/react';
function Demo() {
return (
);
}
```
Note that the component you pass to the `component` prop should allow spreading props to its root element:
```tsx
import { Menu } from '@mantine/core';
// β Will not work with Menu.Item
function IncorrectItem() {
return ;
}
// β Will work correctly with Menu.Item
const CorrectItem = ({ ref, ...props }) => (
);
function Demo() {
// β Will not work
const incorrect = ;
// β Will work
const correct = ;
}
```
## Accessibility
Menu follows [WAI-ARIA recommendations](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-links/):
* Dropdown element has `role="menu"` and `aria-labelledby="target-id"` attributes
* Target element has `aria-haspopup="menu"`, `aria-expanded`, `aria-controls="dropdown-id"` attributes
* Menu item has `role="menuitem"` attribute
Whilst the dropdown is unopened, the `aria-controls` attribute will be undefined
### Supported target elements
An uncontrolled Menu with `trigger="click"` (default) will be accessible only when used with a `button` element or component that renders it ([Button](https://alpha.mantine.dev/llms/core-button.md), [ActionIcon](https://alpha.mantine.dev/llms/core-action-icon.md), etc.).
Other elements will not support `Space` and `Enter` key presses.
### Hover menu
Menu with `trigger="hover"` is not accessible β it cannot be accessed with the keyboard. Use it only if you do not care about accessibility. If you need both hover and click triggers, use `trigger="click-hover"`.
### Navigation
If you are using the Menu to build navigation, you can use the options from the demo below to follow the [WAI-ARIA recommendations for navigation](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/).
```tsx
import { Group, Menu } from '@mantine/core';
function Demo() {
const menus = Array(4)
.fill(0)
.map((e, i) => (
));
return {menus};
}
```
### Keyboard interactions
If you also need to support `Tab` and `Shift + Tab` then set `menuItemTabIndex={0}`.
#### Props
**Menu props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| arrowOffset | number | - | Arrow offset in px |
| arrowPosition | 'center' \| 'side' | - | Arrow position |
| arrowRadius | number | - | Arrow `border-radius` in px |
| arrowSize | number | - | Arrow size in px |
| children | React.ReactNode | - | Menu children |
| clickOutsideEvents | string[] | - | Events that trigger outside click detection. Includes mousedown for desktop clicks, touchstart for mobile, and keydown for Escape key handling |
| closeDelay | number | - | Close delay in ms, applicable only to `trigger="hover"` variant |
| closeOnClickOutside | boolean | - | If set, the dropdown is closed on outside clicks |
| closeOnEscape | boolean | - | If set, the dropdown is closed when the `Escape` key is pressed |
| closeOnItemClick | boolean | - | If set, the Menu is closed when one of the items is clicked. Can be overridden per item with `closeMenuOnClick` prop |
| defaultOpened | boolean | - | Uncontrolled menu initial opened state |
| disabled | boolean | - | If set, popover dropdown will not be rendered |
| floatingStrategy | FloatingStrategy | - | Changes floating ui [position strategy](https://floating-ui.com/docs/usefloating#strategy) |
| hideDetached | boolean | - | If set, the dropdown is hidden when the element is hidden with styles or not visible on the screen |
| id | string | - | Id base to create accessibility connections |
| keepMounted | boolean | - | If set, the dropdown is not unmounted from the DOM when hidden. `display: none` styles are added instead. |
| loop | boolean | - | If set, arrow key presses wrap around from last item to first and vice versa |
| menuItemTabIndex | 0 \| -1 | - | Set the `tabindex` on all menu items. Use `0` to allow Tab key navigation through menu items (required for navigation menus following WAI-ARIA disclosure pattern). |
| middlewares | PopoverMiddlewares | - | Floating ui middlewares to configure position handling |
| offset | number \| FloatingAxesOffsets | - | Offset of the dropdown element |
| onChange | (opened: boolean) => void | - | Called when menu opened state changes |
| onClose | () => void | - | Called when Menu is closed |
| onDismiss | () => void | - | Called when the popover is dismissed by clicking outside or by pressing escape |
| onEnterTransitionEnd | () => void | - | Called when enter transition ends |
| onExitTransitionEnd | () => void | - | Called when exit transition ends |
| onOpen | () => void | - | Called when Menu is opened |
| onPositionChange | (position: FloatingPosition) => void | - | Called when dropdown position changes |
| openDelay | number | - | Open delay in ms, applicable only to `trigger="hover"` variant |
| opened | boolean | - | Controlled menu opened state |
| overlayProps | OverlayProps & ElementProps<"div"> | - | Props passed down to `Overlay` component |
| portalProps | BasePortalProps | - | Props to pass down to the `Portal` when `withinPortal` is true |
| position | FloatingPosition | - | Dropdown position relative to the target element |
| preventPositionChangeWhenVisible | boolean | - | Prevents popover from flipping/shifting when it the dropdown is visible |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius |
| returnFocus | boolean | - | Determines whether focus should be automatically returned to control when dropdown closes |
| shadow | MantineShadow | - | Key of `theme.shadows` or any other valid CSS `box-shadow` value |
| transitionProps | TransitionProps | - | Props passed down to the `Transition` component. Use to configure duration and animation type. |
| trapFocus | boolean | - | If set, focus is trapped within the menu dropdown when it is opened |
| trigger | "hover" \| "click" \| "click-hover" | - | Event trigger to open menu. Note: 'hover' is not keyboard accessible; prefer 'click-hover' for accessible hover menus |
| width | PopoverWidth | - | Dropdown width, or `'target'` to make dropdown width the same as target element |
| withArrow | boolean | - | Determines whether component should have an arrow |
| withInitialFocusPlaceholder | boolean | - | Adds a hidden focusable element at the start of the dropdown to prevent unexpected focus jumps when opening with keyboard. Set to false if you need custom focus management. |
| withOverlay | boolean | - | Determines whether the overlay should be displayed when the dropdown is opened |
| withinPortal | boolean | - | Determines whether dropdown should be rendered within the `Portal` |
| zIndex | string \| number | - | Dropdown `z-index` |
**Menu.Item props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Item label |
| closeMenuOnClick | boolean | - | Controls whether the menu closes when this item is clicked. When undefined, inherits from Menu's `closeOnItemClick` prop. When true or false, overrides the Menu-level setting |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
| disabled | boolean | - | Sets disabled attribute, applies disabled styles |
| leftSection | React.ReactNode | - | Section displayed at the start of the label |
| rightSection | React.ReactNode | - | Section displayed at the end of the label |
**Menu.Target props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | Target element |
| refProp | string | - | Key of the prop used to get element ref, useful for forwarding refs to custom components |
**Menu.Sub props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| arrowOffset | number | - | Arrow offset in px |
| arrowPosition | 'center' \| 'side' | - | Arrow position |
| arrowRadius | number | - | Arrow `border-radius` in px |
| arrowSize | number | - | Arrow size in px |
| closeDelay | number | - | Close delay in ms, applicable when hover trigger is used |
| disabled | boolean | - | If set, popover dropdown will not be rendered |
| floatingStrategy | FloatingStrategy | - | Changes floating ui [position strategy](https://floating-ui.com/docs/usefloating#strategy) |
| hideDetached | boolean | - | If set, the dropdown is hidden when the element is hidden with styles or not visible on the screen |
| keepMounted | boolean | - | If set, the dropdown is not unmounted from the DOM when hidden. `display: none` styles are added instead. |
| middlewares | PopoverMiddlewares | - | Floating ui middlewares to configure position handling |
| offset | number \| FloatingAxesOffsets | - | Offset of the dropdown element |
| onChange | (opened: boolean) => void | - | Called with current state when dropdown opens or closes |
| onClose | () => void | - | Called when dropdown closes |
| onDismiss | () => void | - | Called when the popover is dismissed by clicking outside or by pressing escape |
| onEnterTransitionEnd | () => void | - | Called when enter transition ends |
| onExitTransitionEnd | () => void | - | Called when exit transition ends |
| onOpen | () => void | - | Called when dropdown opens |
| onPositionChange | (position: FloatingPosition) => void | - | Called when dropdown position changes |
| openDelay | number | - | Open delay in ms, applicable when hover trigger is used |
| overlayProps | OverlayProps & ElementProps<"div"> | - | Props passed down to `Overlay` component |
| portalProps | BasePortalProps | - | Props to pass down to the `Portal` when `withinPortal` is true |
| position | FloatingPosition | - | Dropdown position relative to the target element |
| preventPositionChangeWhenVisible | boolean | - | Prevents popover from flipping/shifting when it the dropdown is visible |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set border-radius |
| returnFocus | boolean | - | Determines whether focus should be automatically returned to control when dropdown closes |
| shadow | MantineShadow | - | Key of `theme.shadows` or any other valid CSS `box-shadow` value |
| transitionProps | TransitionProps | - | Props passed down to the `Transition` component that used to animate dropdown presence, use to configure duration and animation type |
| width | PopoverWidth | - | Dropdown width, or `'target'` to make dropdown width the same as target element |
| withArrow | boolean | - | Determines whether component should have an arrow |
| withOverlay | boolean | - | Determines whether the overlay should be displayed when the dropdown is opened |
| withinPortal | boolean | - | Determines whether dropdown should be rendered within the `Portal` |
| zIndex | string \| number | - | Dropdown `z-index` |
**Menu.Sub.Target props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | Target element |
| refProp | string | - | Key of the prop used to get element ref |
**Menu.Sub.Dropdown props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
**Menu.Sub.Item props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Item label |
| closeMenuOnClick | boolean | - | If set, the menu is closed when the item is clicked. Overrides `closeOnItemClick` prop on the `Menu` component. |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
| disabled | boolean | - | Sets disabled attribute, applies disabled styles |
| leftSection | React.ReactNode | - | Section displayed at the start of the label |
| rightSection | React.ReactNode | - | Section displayed at the end of the label |
**Menu.SubItem props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Item label |
| closeMenuOnClick | boolean | - | If set, the menu is closed when the item is clicked. Overrides `closeOnItemClick` prop on the `Menu` component. |
| color | MantineColor | - | Key of `theme.colors` or any valid CSS color |
| disabled | boolean | - | Sets disabled attribute, applies disabled styles |
| leftSection | React.ReactNode | - | Section displayed at the start of the label |
| rightSection | React.ReactNode | - | Section displayed at the end of the label |
**Menu.SubTarget props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | required | Target element |
| refProp | string | - | Key of the prop used to get element ref |
#### Styles API
Menu component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Menu selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| dropdown | .mantine-Menu-dropdown | Dropdown element |
| arrow | .mantine-Menu-arrow | Dropdown arrow |
| overlay | .mantine-Menu-overlay | Overlay element |
| divider | .mantine-Menu-divider | `Menu.Divider` root element |
| label | .mantine-Menu-label | `Menu.Label` root element |
| item | .mantine-Menu-item | `Menu.Item` root element |
| itemLabel | .mantine-Menu-itemLabel | Label of `Menu.Item` |
| itemSection | .mantine-Menu-itemSection | Left and right sections of `Menu.Item` |
| chevron | .mantine-Menu-chevron | Sub menu chevron |
**Menu data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| item | data-disabled | `disabled` prop is set on `Menu.Item` | - |
--------------------------------------------------------------------------------
### Modal
Package: @mantine/core
Import: import { Modal } from '@mantine/core';
Description: An accessible overlay dialog
## Usage
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Modal content */}
>
);
}
```
## Center modal vertically
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Modal content */}
>
);
}
```
## Remove header
To remove the header, set `withCloseButton={false}`:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
Modal without header, press escape or click on overlay to close
>
);
}
```
## Change size
You can change the modal width by setting the `size` prop to a predefined size or any valid width, for example, `55%` or `50rem`.
The `Modal` width cannot exceed `100vw`.
```tsx
function Demo() {
const [opened, setOpened] = useState(false);
const [size, setSize] = useState('md');
const buttons = SIZES.map((s) => (
));
return (
<>
setOpened(false)}
title="Introduce yourself!"
size={size}
>
{buttons}
>
);
}
```
## Size auto
`Modal` with `size="auto"` will have width that fits its content:
```tsx
import { useDisclosure, useCounter } from '@mantine/hooks';
import { Modal, Button, Group, Text, Badge } from '@mantine/core';
function Demo() {
const [opened, { close, open }] = useDisclosure(false);
const [count, { increment, decrement }] = useCounter(3, { min: 0 });
const badges = Array(count)
.fill(0)
.map((_, index) => Badge {index});
return (
<>
Modal with size auto will fits its content
{badges}
>
);
}
```
## Fullscreen
A fullscreen modal will take the entire screen. It is usually better to change the transition to `fade`
when the `fullScreen` prop is set:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Modal content */}
>
);
}
```
To switch Modal to fullscreen on devices with small screens only, use the [use-media-query](https://alpha.mantine.dev/llms/hooks-use-media-query.md) hook.
The `size` prop is ignored if the `fullScreen` prop is set:
```tsx
import { useDisclosure, useMediaQuery } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
const isMobile = useMediaQuery('(max-width: ${em(800)})');
return (
<>
The Modal will be full screen only on mobile
>
);
}
```
## Customize overlay
`Modal` uses the [Overlay](https://alpha.mantine.dev/llms/core-overlay.md) component. You can set any props that [Overlay](https://alpha.mantine.dev/llms/core-overlay.md)
supports with `overlayProps`:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Modal content */}
>
);
}
```
## Modal with scroll
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
const content = Array(100)
.fill(0)
.map((_, index) =>
Modal with scroll
);
return (
<>
{content}
>
);
}
```
## Usage with ScrollArea
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button, ScrollArea } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
const content = Array(100)
.fill(0)
.map((_, index) =>
Modal with scroll
);
return (
<>
{content}
>
);
}
```
## Change offsets
Use `xOffset`/`yOffset` to configure the horizontal/vertical content offsets:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
{/* Modal content */}
>
);
}
```
## Change transitions
`Modal` is built with the [Transition](https://alpha.mantine.dev/llms/core-transition.md) component. Use the `transitionProps`
prop to customize any [Transition](https://alpha.mantine.dev/llms/core-transition.md) properties:
```tsx
import { useState } from 'react';
import { Modal, Group, Button } from '@mantine/core';
function Demo() {
const [noTransitionOpened, setNoTransitionOpened] = useState(false);
const [slowTransitionOpened, setSlowTransitionOpened] = useState(false);
return (
<>
setSlowTransitionOpened(false)}
title="Please consider this"
transitionProps={{ transition: 'rotate-left' }}
>
rotate-left transition
setNoTransitionOpened(false)}
title="Please consider this"
transitionProps={{ transition: 'fade', duration: 600, timingFunction: 'linear' }}
>
fade transition 600ms linear transition
>
);
}
```
## onExitTransitionEnd and onEnterTransitionEnd
The `onExitTransitionEnd` and `onEnterTransitionEnd` props can be used to run code after
the exit/enter transition is finished. For example, this is useful when you want to clear
data after the modal is closed:
```tsx
import { useState } from 'react';
import { Button, Group, Modal } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [firstOpened, firstHandlers] = useDisclosure(false);
const [secondOpened, secondHandlers] = useDisclosure(false);
const [modalData, setModalData] = useState({
title: '',
message: '',
});
return (
<>
{
firstHandlers.close();
setModalData({ title: '', message: '' });
}}
title={modalData.title}
>
{modalData.message}
setModalData({ title: '', message: '' })}
title={modalData.title}
>
{modalData.message}
>
);
}
```
## Initial focus
Modal uses [FocusTrap](https://alpha.mantine.dev/llms/core-focus-trap.md) to trap focus. Add the `data-autofocus`
attribute to the element that should receive initial focus.
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button, TextInput } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
>
);
}
```
If you do not want to focus any elements when the modal is opened, use the `FocusTrap.InitialFocus`
component to create a visually hidden element that will receive initial focus:
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button, TextInput, FocusTrap } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
>
);
}
```
If you do not add the `data-autofocus` attribute and do not use `FocusTrap.InitialFocus`,
the modal will focus the first focusable element inside it, which is usually the close button.
## Control behavior
The following props can be used to control `Modal` behavior.
In most cases, it is not recommended to turn these features off β
it will make the component less accessible.
* `trapFocus` β determines whether focus should be trapped inside the modal
* `closeOnEscape` β determines whether the modal should be closed when the `Escape` key is pressed
* `closeOnClickOutside` β determines whether the modal should be closed when the user clicks on the overlay
* `returnFocus` β determines whether focus should be returned to the element that was focused before the modal was opened
## react-remove-scroll settings
`Modal` uses the [react-remove-scroll](https://github.com/theKashey/react-remove-scroll)
package to lock scroll. You can pass props down to the `RemoveScroll` component
with `removeScrollProps`:
```tsx
import { Modal } from '@mantine/core';
function Demo() {
return (
{}}
/>
);
}
```
## Change close icon
Use `closeButtonProps` to customize the close button:
```tsx
import { XCircleIcon } from '@phosphor-icons/react';
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
,
}}
>
{/* Modal content */}
>
);
}
```
## Compound components
You can use the following compound components to have full control over the `Modal` rendering:
* `Modal.Root` β context provider
* `Modal.Overlay` β render [Overlay](https://alpha.mantine.dev/llms/core-overlay.md)
* `Modal.Content` β main modal element, should include all modal content
* `Modal.Header` β sticky header, usually contains `Modal.Title` and `Modal.CloseButton`
* `Modal.Title` β `h2` element, the `aria-labelledby` of `Modal.Content` is pointing to this element, usually rendered inside `Modal.Header`
* `Modal.CloseButton` β close button, usually rendered inside `Modal.Header`
* `Modal.Body` β a place for main content, the `aria-describedby` of `Modal.Content` is pointing to this element
```tsx
import { useDisclosure } from '@mantine/hooks';
import { Modal, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
Modal titleModal content
>
);
}
```
## Modal.Stack
Use the `Modal.Stack` component to render multiple modals at the same time.
`Modal.Stack` keeps track of opened modals, manages z-index values, focus trapping,
and `closeOnEscape` behavior. `Modal.Stack` is designed to be used with the `useModalsStack` hook.
Differences from using multiple `Modal` components:
* `Modal.Stack` manages z-index values β modals that are opened later will always have a higher z-index value regardless of their order in the DOM
* `Modal.Stack` disables focus trap and `Escape` key handling for all modals except the one that is currently opened
* Modals that are not currently opened are present in the DOM but are hidden with `opacity: 0` and `pointer-events: none`
* Only one overlay is rendered at a time
```tsx
import { Button, Group, Modal, useModalsStack } from '@mantine/core';
function Demo() {
const stack = useModalsStack(['delete-page', 'confirm-action', 'really-confirm-action']);
return (
<>
Are you sure you want to delete this page? This action cannot be undone.
Are you sure you want to perform this action? This action cannot be undone. If you are
sure, press confirm button below.
Jokes aside. You have confirmed this action. This is your last chance to cancel it. After
you press confirm button below, action will be performed and cannot be undone. For real
this time. Are you sure you want to proceed?
>
);
}
```
Note that `Modal.Stack` can only be used with the `Modal` component. Components built with `Modal.Root`
and other compound components are not compatible with `Modal.Stack`.
## useModalsStack hook
The `useModalsStack` hook provides an easy way to control multiple modals at the same time.
It accepts an array of unique modal IDs and returns an object with the following properties:
```tsx
interface UseModalsStackReturnType {
// Current opened state of each modal
state: Record;
// Opens modal with the given id
open: (id: T) => void;
// Closes modal with the given id
close: (id: T) => void;
// Toggles modal with the given id
toggle: (id: T) => void;
// Closes all modals within the stack
closeAll: () => void;
// Returns props for modal with the given id
register: (id: T) => {
opened: boolean;
onClose: () => void;
stackId: T;
};
}
```
Example of using `useModalsStack` with the `Modal` component:
```tsx
import { Modal, useModalsStack } from '@mantine/core';
function Demo() {
const stack = useModalsStack(['first', 'second']);
return (
<>
FirstSecond
>
);
}
```
## Fixed elements offset
The `Modal` component uses the [react-remove-scroll](https://github.com/theKashey/react-remove-scroll)
package to lock scroll. To properly size these elements, add a `className` to them ([documentation](https://github.com/theKashey/react-remove-scroll#positionfixed-elements)):
```tsx
import { RemoveScroll } from '@mantine/core';
function Demo() {
return (
<>
width: 100%
right: 0
>
);
}
```
## Accessibility
The `Modal` component follows [WAI-ARIA recommendations](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/dialog) on accessibility.
Set the `title` prop to make the component accessible, which will add `aria-labelledby` to the content element:
```tsx
import { Modal } from '@mantine/core';
function Demo() {
return {}} />;
}
```
To set the close button's `aria-label`, use `closeButtonProps`:
```tsx
import { Modal } from '@mantine/core';
function Demo() {
return (
{}}
/>
);
}
```
#### Props
**Modal props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| centered | boolean | - | If set, the modal is centered vertically |
| children | React.ReactNode | - | Modal content |
| closeButtonProps | ModalBaseCloseButtonProps | - | Props passed down to the close button |
| closeOnClickOutside | boolean | - | If set, the modal/drawer is closed when user clicks on the overlay |
| closeOnEscape | boolean | - | If set, `onClose` is called when user presses the escape key |
| fullScreen | boolean | - | If set, the modal takes the entire screen |
| id | string | - | Id used to connect modal/drawer with body and title |
| keepMounted | boolean | - | If set modal/drawer is not unmounted from the DOM when hidden. `display: none` styles are applied instead. |
| lockScroll | boolean | - | If set, scroll is locked when `opened={true}` |
| onClose | () => void | required | Called when modal/drawer is closed |
| onEnterTransitionEnd | () => void | - | Called when enter transition ends |
| onExitTransitionEnd | () => void | - | Called when exit transition ends |
| opened | boolean | required | Controls opened state |
| overlayProps | ModalBaseOverlayProps | - | Props passed down to the `Overlay` component, use to configure opacity, `background-color`, styles and other properties |
| padding | MantineSpacing | - | Key of `theme.spacing` or any valid CSS value to set content, header and footer padding |
| portalProps | BasePortalProps | - | Props passed down to the Portal component when `withinPortal` is set |
| radius | MantineRadius \| number | - | Key of `theme.radius` or any valid CSS value to set `border-radius` |
| removeScrollProps | RemoveScrollProps | - | Props passed down to react-remove-scroll, can be used to customize scroll lock behavior |
| returnFocus | boolean | - | If set, focus is returned to the last active element when `onClose` is called |
| scrollAreaComponent | ScrollAreaComponent | - | Scroll area component |
| shadow | MantineShadow | - | Key of `theme.shadows` or any valid CSS box-shadow value |
| size | MantineSize \| number | - | Controls width of the content area |
| stackId | string | - | Id of the modal in the `Modal.Stack` |
| title | React.ReactNode | - | Modal title |
| transitionProps | TransitionProps | - | Props added to the `Transition` component that used to animate overlay and body, use to configure duration and animation type, `{ duration: 200, transition: 'fade-down' }` by default |
| trapFocus | boolean | - | If set, focus is trapped within the modal/drawer |
| withCloseButton | boolean | - | If set, the close button is rendered |
| withOverlay | boolean | - | If set, the overlay is rendered |
| withinPortal | boolean | - | If set, the component is rendered inside `Portal` |
| xOffset | MarginLeft | - | Left/right modal offset |
| yOffset | MarginTop | - | Top/bottom modal offset |
| zIndex | string \| number | - | `z-index` CSS property of the root element |
**Modal.Base props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Modal/drawer content |
| closeOnClickOutside | boolean | - | If set, the modal/drawer is closed when user clicks on the overlay |
| closeOnEscape | boolean | - | If set, `onClose` is called when user presses the escape key |
| id | string | - | Id used to connect modal/drawer with body and title |
| keepMounted | boolean | - | If set modal/drawer is not unmounted from the DOM when hidden. `display: none` styles are applied instead. |
| lockScroll | boolean | - | If set, scroll is locked when `opened={true}` |
| onClose | () => void | required | Called when modal/drawer is closed |
| onEnterTransitionEnd | () => void | - | Called when enter transition ends |
| onExitTransitionEnd | () => void | - | Called when exit transition ends |
| opened | boolean | required | Controls opened state |
| padding | MantineSpacing | - | Key of `theme.spacing` or any valid CSS value to set content, header and footer padding |
| portalProps | BasePortalProps | - | Props passed down to the Portal component when `withinPortal` is set |
| removeScrollProps | RemoveScrollProps | - | Props passed down to react-remove-scroll, can be used to customize scroll lock behavior |
| returnFocus | boolean | - | If set, focus is returned to the last active element when `onClose` is called |
| shadow | MantineShadow | - | Key of `theme.shadows` or any valid CSS box-shadow value |
| size | MantineSize \| number | - | Controls width of the content area |
| transitionProps | TransitionProps | - | Props added to the `Transition` component that used to animate overlay and body, use to configure duration and animation type, `{ duration: 200, transition: 'fade-down' }` by default |
| trapFocus | boolean | - | If set, focus is trapped within the modal/drawer |
| withinPortal | boolean | - | If set, the component is rendered inside `Portal` |
| zIndex | string \| number | - | `z-index` CSS property of the root element |
**Modal.sProvider props**
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | React.ReactNode | - | Your app |
| labels | ConfirmLabels | - | Confirm modal labels |
| modalProps | ModalSettings | - | Shared Modal component props, applied for every modal |
| modals | Record>> | - | Predefined modals |
#### Styles API
Modal component supports Styles API. With Styles API, you can customize styles of any inner element. Follow the documentation to learn how to use CSS modules, CSS variables and inline styles to get full control over component styles.
**Modal selectors**
| Selector | Static selector | Description |
|----------|----------------|-------------|
| root | .mantine-Modal-root | Root element |
| inner | .mantine-Modal-inner | Element used to center modal, has fixed position, takes entire screen |
| content | .mantine-Modal-content | `Modal.Content` root element |
| header | .mantine-Modal-header | Contains title and close button |
| overlay | .mantine-Modal-overlay | Overlay displayed under the `Modal.Content` |
| title | .mantine-Modal-title | Modal title (h2 tag), displayed in the header |
| body | .mantine-Modal-body | Modal body, displayed after header |
| close | .mantine-Modal-close | Close button |
**Modal CSS variables**
| Selector | Variable | Description |
|----------|----------|-------------|
| root | --modal-radius | Controls `border-radius` of `Modal.Content` |
| root | --modal-size | Controls `width` of `Modal.Content` |
**Modal data attributes**
| Selector | Attribute | Condition | Value |
|----------|-----------|-----------|-------|
| root | data-full-screen | `fullScreen` prop is set | - |
| root | data-centered | `centered` prop is set | - |
--------------------------------------------------------------------------------
### MultiSelect
Package: @mantine/core
Import: import { MultiSelect } from '@mantine/core';
Description: Custom searchable multi select
## Usage
`MultiSelect` provides a way to enter multiple values.
`MultiSelect` is similar to [TagsInput](https://alpha.mantine.dev/llms/core-tags-input.md), but it does not allow entering custom values.
```tsx
import { MultiSelect } from '@mantine/core';
function Demo() {
return (
);
}
```
## Loading state
Set `loading` prop to display a loading indicator. By default, the loader is displayed on the right side of the input.
You can change the position with the `loadingPosition` prop to `'left'` or `'right'`. This is useful for async operations like API calls, searches, or validations:
```tsx
import { MultiSelect } from '@mantine/core';
function Demo() {
return (
);
}
```
## Controlled
The `MultiSelect` value must be an array of strings; other types are not supported.
The `onChange` function is called with an array of strings as a single argument.
```tsx
import { useState } from 'react';
import { MultiSelect } from '@mantine/core';
function Demo() {
const [value, setValue] = useState([]);
return ;
}
```
## Clearable
Set the `clearable` prop to display the clear button in the right section. The button is not displayed
when:
* The component does not have a value
* The component is disabled
* The component is read only
```tsx
import { MultiSelect } from '@mantine/core';
function Demo() {
return (
);
}
```
```tsx
import { CaretDownIcon } from '@phosphor-icons/react';
import { MultiSelect, Stack } from '@mantine/core';
function Demo() {
return (
}
clearSectionMode="both"
/>
}
clearSectionMode="rightSection"
/>
}
clearSectionMode="clear"
/>
);
}
```
## Searchable
Set the `searchable` prop to allow filtering options by user input:
```tsx
import { MultiSelect } from '@mantine/core';
function Demo() {
return (
);
}
```
## Controlled search value
You can control the search value with the `searchValue` and `onSearchChange` props:
```tsx
import { useState } from 'react';
import { MultiSelect } from '@mantine/core';
function Demo() {
const [searchValue, setSearchValue] = useState('');
return (
);
}
```
## Nothing found
Set the `nothingFoundMessage` prop to display a given message when no options match the search query
or there is no data available. If the `nothingFoundMessage` prop is not set, the `MultiSelect` dropdown will be hidden.
```tsx
import { MultiSelect } from '@mantine/core';
function Demo() {
return (
);
}
```
## Checked option icon
Set `checkIconPosition` prop to `left` or `right` to control position of check icon in active option.
To remove the check icon, set `withCheckIcon={false}`. To align unchecked labels with checked ones, set `withAlignedLabels` prop.
```tsx
import { MultiSelect } from '@mantine/core';
function Demo() {
return (
);
}
```
## Max selected values
You can limit the number of selected values with the `maxValues` prop. This will not allow adding more values
once the limit is reached.
```tsx
import { MultiSelect } from '@mantine/core';
function Demo() {
return (
);
}
```
## Hide selected options
To remove selected options from the list of available options, set the `hidePickedOptions` prop:
```tsx
import { MultiSelect } from '@mantine/core';
function Demo() {
return (
);
}
```
## Data prop
Data that is used in MultiSelect must be an array of strings or objects with value and label properties. You can also specify additional properties that will be available in renderOption function.
## Value type
`MultiSelect` supports primitive values (strings, numbers, booleans) as value type. `MultiSelect` automatically
infers the value type. If you want to set the value type explicitly, pass type argument:
```tsx
import { MultiSelect } from '@mantine/core';
type MultiSelectValue = 'React' | 'Angular' | 'Svelte' | number;
function Demo() {
return data={['React', 'Angular', 'Svelte', 100]} />;
}
```
## Filtering
MultiSelect provides built-in filtering functionality. You can control filtering behavior with filter prop or implement custom filtering logic.
```tsx
import { MultiSelect, ComboboxItem, OptionsFilter } from '@mantine/core';
const optionsFilter: OptionsFilter = ({ options, search }) => {
const splittedSearch = search.toLowerCase().trim().split(' ');
return (options as ComboboxItem[]).filter((option) => {
const words = option.label.toLowerCase().trim().split(' ');
return splittedSearch.every((searchWord) => words.some((word) => word.includes(searchWord)));
});
};
function Demo() {
return (
);
}
```
## Sort options
By default, options are sorted by their position in the data array. You can change this behavior
with the `filter` function:
```tsx
import { MultiSelect, ComboboxItem, OptionsFilter } from '@mantine/core';
const optionsFilter: OptionsFilter = ({ options, search }) => {
const filtered = (options as ComboboxItem[]).filter((option) =>
option.label.toLowerCase().trim().includes(search.toLowerCase().trim())
);
filtered.sort((a, b) => a.label.localeCompare(b.label));
return filtered;
};
function Demo() {
return (
);
}
```
## Fuzzy search with fuse.js
You can implement fuzzy search using the [fuse.js](https://fusejs.io/) library to match options
even with typos or partial matches:
```tsx
import { MultiSelect, ComboboxItem, OptionsFilter } from '@mantine/core';
import Fuse from 'fuse.js';
const optionsFilter: OptionsFilter = ({ options, search }) => {
if (!search.trim()) {
return options;
}
const fuse = new Fuse(options as ComboboxItem[], {
keys: ['label'],
threshold: 0.3,
minMatchCharLength: 1,
});
return fuse.search(search).map((result) => result.item);
};
function Demo() {
return (
);
}
```
## Large datasets
MultiSelect can handle large datasets efficiently. Consider implementing virtualization for datasets with thousands of items to improve performance.
```tsx
import { MultiSelect } from '@mantine/core';
const largeData = Array(100_000)
.fill(0)
.map((_, index) => `Option ${index}`);
function Demo() {
return (
);
}
```
## renderOption
The `renderOption` callback allows you to customize option rendering. It is called with the option object and
checked state. The function must return a React node.
```tsx
import { MultiSelect, MultiSelectProps, Avatar, Group, Text } from '@mantine/core';
const usersData: Record = {
'Emily Johnson': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-7.png',
email: 'emily92@gmail.com',
},
'Ava Rodriguez': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-8.png',
email: 'ava_rose@gmail.com',
},
'Olivia Chen': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-4.png',
email: 'livvy_globe@gmail.com',
},
'Ethan Barnes': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-1.png',
email: 'ethan_explorer@gmail.com',
},
'Mason Taylor': {
image: 'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-2.png',
email: 'mason_musician@gmail.com',
},
};
const renderMultiSelectOption: MultiSelectProps['renderOption'] = ({ option }) => (