Modal

Modal with optional header
Import

Usage

import { useState } from 'react';
import { Modal, Button, Group } from '@mantine/core';
function Demo() {
const [opened, setOpened] = useState(false);
return (
<>
<Modal
opened={opened}
onClose={() => setOpened(false)}
title="Introduce yourself!"
>
{/* Modal content */}
</Modal>
<Group position="center">
<Button onClick={() => setOpened(true)}>Open Modal</Button>
</Group>
</>
);
}

Remove title and close button

You can remove modal title and close button. It will still be possible to close modal by clicking on overlay or pressing escape.

import { Modal } from '@mantine/core';
function Demo() {
return (
<Modal withCloseButton={false}>
Modal without header, press escape or click on overlay to close
</Modal>
);
}

Center modal vertically

import { Modal } from '@mantine/core';
function Demo() {
return <Modal centered /* ...other props */ />;
};

Change size

You can change modal width by setting size prop to predefined size or any valid width, for example, 55% or 200px. Size controls modal width, max-width is set to 100% with spacing on left and right, no matter what size is passed 100% will not be exceeded:

<Modal size="sm" /> // -> predefined small size
<Modal size={378} /> // -> size in px
<Modal size="55%" /> // -> size in %
<Modal size="calc(100vw - 87px)" /> // -> size with calc
<Modal size="255%" /> // -> max-width is set to 100%, won't work

Size auto

Modal with size="auto" will have width to fit its content:

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 key={index}>Badge {index}</Badge>);
return (
<>
<Modal opened={opened} onClose={close} size="auto" title="Modal size auto">
<Text>Modal with size auto will fits its content</Text>
<Group noWrap mt="md">
{badges}
</Group>
<Group mt="xl">
<Button variant="outline" onClick={increment}>
Add badge
</Button>
<Button variant="outline" onClick={decrement}>
Remove badge
</Button>
</Group>
</Modal>
<Group position="center">
<Button onClick={open}>Open modal</Button>
</Group>
</>
);
}

Fullscreen

Fullscreen modal will take the entire screen:

import { useState } from 'react';
import { Modal, Button, Group } from '@mantine/core';
function Demo() {
const [opened, setOpened] = useState(false);
return (
<>
<Modal
opened={opened}
onClose={() => setOpened(false)}
title="This is fullscreen modal!"
fullScreen
>
{/* Modal content */}
</Modal>
<Group position="center">
<Button onClick={() => setOpened(true)}>Open Modal</Button>
</Group>
</>
);
}

To switch Modal to fullscreen on devices with small screens only use use-media-query hook. size prop is ignored if fullScreen prop is set:

import { Modal } from '@mantine/core';
import { useMediaQuery } from '@mantine/hooks';
function Demo() {
const isMobile = useMediaQuery('(max-width: 600px)');
return <Modal size="md" fullScreen={isMobile} />;
}

Customize overlay

Modal uses Overlay component, you can change overlay opacity, blur and color:

import { Modal, useMantineTheme } from '@mantine/core';
function Demo() {
const theme = useMantineTheme();
return (
<Modal
overlayColor={theme.colorScheme === 'dark' ? theme.colors.dark[9] : theme.colors.gray[2]}
overlayOpacity={0.55}
overlayBlur={3}
>
{/* Modal content */}
</Modal>
);
}

Modal with overflow

You can control modal vertical overflow behavior by setting overflow prop:

// (default) – overflow is handled by modal wrapper
<Modal overflow="outside" />
// overflow is handled by modal body
<Modal overflow="inside" />

Change transitions

Modal is built with Transition component.

You can change transitions with props:

  • transition – predefined transition name or transition object
  • transitionDuration – enter transition duration in ms, defaults to 300ms. Note that, modal has two elements which are animated: overlay and modal body. Overlay changes opacity during transition and its animation is twice as fast as modal body.
  • exitTransitionDuration – exit transition duration in ms, defaults to 0ms
  • transitionTimingFunction – timing function, defaults to theme.transitionTimingFunction
import { Modal } from '@mantine/core';
function Demo() {
return (
<Modal
transition="fade"
transitionDuration={600}
transitionTimingFunction="ease"
/>
);
}

Initial focus

Modal uses use-focus-trap to manage focus. To specify initial focus element add data-autofocus attribute:

<Modal>
<input />
{/* Second input in modal will have initial focus */}
<input data-autofocus />
<input />
</Modal>

Control behavior

The following props can be used to control Modal behavior. In most cases you should not turn these features off as it will make your modal less accessible.

  • trapFocus – defines whether focus should be trapped inside modal
  • closeOnEscape – defines whether modal should be closed when user presses Escape key
  • closeOnClickOutside – defines whether modal should be closed when user clicks outside of modal body

Accessibility and usability

  • When modal is opened, focus is trapped inside and vertical scroll is locked at current position
  • When user clicks on overlay or presses escape modal closes
  • Modal transitions are disabled if user prefers to reduce motion
  • Modal wrapper has aria-modal="true" and role="dialog" attributes
  • Modal wrapper has aria-labelledby and aria-describedby pointing to modal title and body

For better screen reader support set closeButtonLabel prop:

// sets title attribute on close button
<Modal closeButtonLabel="Close authentication modal" />

Modal component props

NameTypeDescription
centered
boolean
Controls if modal should be centered
closeButtonLabel
string
Close button aria-label
closeOnClickOutside
boolean
Should modal be closed when outside click was registered?
closeOnEscape
boolean
Should modal be closed when escape is pressed?
exitTransitionDuration
number
Exit transition duration in ms, 0 by default
fullScreen
boolean
Determines whether the modal should take the entire screen
id
string
id base, used to generate ids to connect modal title and body with aria- attributes, defaults to random id
lockScroll
boolean
Determines whether scroll should be locked when modal is opened, defaults to true
onClose *
() => void
Called when close button clicked and when escape key is pressed
opened *
boolean
Mounts modal if true
overflow
"inside" | "outside"
Control vertical overflow behavior
overlayBlur
number
Overlay blur in px
overlayColor
string
Overlay color
overlayOpacity
number
Overlay opacity
padding
number | "xs" | "sm" | "md" | "lg" | "xl"
Modal padding from theme or number value for padding in px
radius
number | "xs" | "sm" | "md" | "lg" | "xl"
Modal radius
shadow
MantineShadow
Modal shadow from theme or css value
size
string | number
Modal body width
target
string | HTMLElement
Target element or selector where modal portal should be rendered
title
ReactNode
Modal title, displayed in header before close button
transition
MantineTransition
Modal body transition
transitionDuration
number
Duration in ms of modal transitions, set to 0 to disable all animations
transitionTimingFunction
string
Modal body transitionTimingFunction, defaults to theme.transitionTimingFunction
trapFocus
boolean
Disables focus trap
withCloseButton
boolean
Hides close button if set to false, modal still can be closed with escape key and by clicking outside
withFocusReturn
boolean
Determines whether focus should be returned to the last active element when drawer is closed
withinPortal
boolean
Determines whether modal should be rendered within Portal, defaults to true
zIndex
ZIndex
Modal z-index property

Modal component Styles API

NameStatic selectorDescription
root.mantine-Modal-rootRoot element, contains modal and overlay
inner.mantine-Modal-innerModal wrapper, centers modal
modal.mantine-Modal-modalModal root
header.mantine-Modal-headerModal header, contains close button and title
overlay.mantine-Modal-overlayOverlay
title.mantine-Modal-titleModal title
body.mantine-Modal-bodyModal body, displayed after header
close.mantine-Modal-closeClose button