primaryShade on theme

New theme.primaryShade property is used to determine which shade will be used for the components that have color prop, it defaults to 6. Note that for some variants with dark color scheme primaryShade will not be used as it will cause contrast issues.

import { MantineProvider, Group, Button } from '@mantine/core';
function Demo() {
return (
<MantineProvider theme={{ primaryShade: 6 }}>
<Group position="center">
<Button variant="filled">Filled button</Button>
<Button variant="light">Light button</Button>
<Button variant="outline">Outline button</Button>
</Group>
</MantineProvider>
);
}

primaryShade can also be customized for dark and light color scheme separately:

import { MantineProvider } from '@mantine/core';
function Demo() {
return (
<MantineProvider theme={{ primaryShade: { light: 6, dark: 8 } }}>
<App />
</MantineProvider>
);
}

Indicator component

New Indicator component:

Color
Radius
xs
sm
md
lg
xl
import { Indicator, Avatar, Group } from '@mantine/core';
function Demo() {
return (
<Group position="center">
<Indicator >
<Avatar
size="lg"
src="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=250&q=80"
/>
</Indicator>
</Group>
);
}

use-focus-within hook

New use-focus-within hook detects if any element within has focus, it works the same way as :focus-within CSS selector:

One of elements has focus: false
import { useFocusWithin } from '@mantine/hooks';
import { TextInput, Button, Box, Text } from '@mantine/core';
function Demo() {
const { ref, focused } = useFocusWithin();
return (
<div ref={ref}>
<Box
sx={(theme) => ({
backgroundColor: focused
? theme.fn.variant({ variant: 'light' }).background
: 'transparent',
padding: theme.spacing.xl,
})}
>
<Text size="sm">One of elements has focus: {focused.toString()}</Text>
<TextInput label="Focus this input" placeholder="Styles will be added to parent" />
<Button mt="md">Button</Button>
</Box>
</div>
);
}

use-network hook

New use-network hook returns current connection status:

PropertyValue
Online
Online
rtt
downlink
effectiveType
saveData
false

New features

Calendar component now supports multiple selected dates:

Mo
Tu
We
Th
Fr
Sa
Su
import { useState } from 'react';
import { Calendar } from '@mantine/dates';
function Demo() {
const [value, setValue] = useState<Date[]>([]);
return <Calendar multiple value={value} onChange={setValue} />;
}

Modal and Drawer components now support setting overlay blur:

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>
);
}

Calendar, Month and DatePicker components now support custom day renderer with renderDay function:

Mo
Tu
We
Th
Fr
Sa
Su
import { useState } from 'react';
import { Calendar } from '@mantine/dates';
import { Indicator } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(null);
return (
<Calendar
value={value}
onChange={setValue}
renderDay={(date) => {
const day = date.getDate();
return (
<Indicator size={6} color="red" offset={8} disabled={day !== 16}>
<div>{day}</div>
</Indicator>
);
}}
/>
);
}

SegmentedControl component now supports disabled items:

Disabled control
Disabled option
import { SegmentedControl } from '@mantine/core';
function Demo() {
return (
<>
{/* Disabled control */}
<SegmentedControl disabled={true} />
{/* Disabled option */}
<SegmentedControl
data={[
{ value: 'preview', label: 'Preview', disabled: true },
{ value: 'code', label: 'Code' },
{ value: 'export', label: 'Export' },
]}
/>
</>
);
}

Other changes