A fully featured React components library
MIT License
Bot releases are hidden (Show)
Published by rtivital 8 months ago
View changelog with demos on mantine.dev website
You can now use container queries
with Mantine components. rem
and em
functions from postcss-preset-mantine
are available in container queries staring from [email protected]
.
.root {
min-width: rem(200px);
max-width: 100%;
min-height: rem(120px);
container-type: inline-size;
overflow: auto;
resize: horizontal;
}
.child {
background-color: var(--mantine-color-dimmed);
color: var(--mantine-color-white);
padding: var(--mantine-spacing-md);
@container (max-width: rem(500px)) {
background-color: var(--mantine-color-blue-filled);
}
@container (max-width: rem(300px)) {
background-color: var(--mantine-color-red-filled);
}
}
New RadarChart component:
import { RadarChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return (
<RadarChart
h={300}
data={multiData}
dataKey="product"
withPolarRadiusAxis
series={[
{ name: 'sales_january', color: 'lime.4', opacity: 0.1 },
{ name: 'sales_february', color: 'cyan.4', opacity: 0.1 },
]}
/>
);
}
FocusTrap.InitialFocus is a new 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 when it is opened:
import { Button, FocusTrap, Modal, TextInput } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
<Modal opened={opened} onClose={close} title="Focus demo">
<FocusTrap.InitialFocus />
<TextInput label="First input" placeholder="First input" />
<TextInput
data-autofocus
label="Input with initial focus"
placeholder="It has data-autofocus attribute"
mt="md"
/>
</Modal>
<Button onClick={open}>Open modal</Button>
</>
);
}
MantineProvider now includes more props to control how styles
are generated and injected. These props are useful if you use Mantine as a headless library
and in test environments.
deduplicateCssVariables
prop determines whether CSS variables should be deduplicated: if CSS variable has the same value as in default theme, it is not added in the runtime.
By default, it is set to true
. If set to false
, all Mantine CSS variables will be added in <style />
tag
even if they have the same value as in the default theme.
import { MantineProvider } from '@mantine/core';
function Demo() {
return (
<MantineProvider deduplicateCssVariables={false}>
<App />
</MantineProvider>
);
}
withStaticClasses
determines whether components should have static classes, for example, mantine-Button-root
.
By default, static classes are enabled, to disable them set withStaticClasses
to false
:
import { MantineProvider } from '@mantine/core';
function Demo() {
return (
<MantineProvider withStaticClasses={false}>
<App />
</MantineProvider>
);
}
withGlobalClasses
determines whether global classes should be added with <style />
tag.
Global classes are required for hiddenFrom
/visibleFrom
and lightHidden
/darkHidden
props to work.
By default, global classes are enabled, to disable them set withGlobalClasses
to false
. Note that
disabling global classes may break styles of some components.
import { MantineProvider } from '@mantine/core';
function Demo() {
return (
<MantineProvider withGlobalClasses={false}>
<App />
</MantineProvider>
);
}
HeadlessMantineProvider
is an alternative to MantineProvider
that should be used when you want to use Mantine as a headless UI library. It removes all
features that are related to Mantine styles:
style
attributeLimitations of HeadlessMantineProvider
:
color
, radius
, size
, etc.) will have no effect.lightHidden
/darkHidden
, visibleFrom
/hiddenFrom
props will not work.mt="xs"
will not work, but mt={5}
will.To use HeadlessMantineProvider
, follow getting started guide and replace MantineProvider
with HeadlessMantineProvider
.
Note that you do not need to use ColorSchemeScript in your application, it will not have any effect,
you can ignore this part of the guide.
import { HeadlessMantineProvider } from '@mantine/core';
function App() {
return <HeadlessMantineProvider>{/* Your application */}</HeadlessMantineProvider>;
}
Sparkline now supports trendColors
prop to change chart color depending on the trend.
The prop accepts an object with positive
, negative
and neutral
properties:
positive
- color for positive trend (first value is less than the last value in data
array)negative
- color for negative trend (first value is greater than the last value in data
array)neutral
- color for neutral trend (first and last values are equal)neutral
is optional, if not provided, the color will be the same as positive
.
import { Sparkline } from '@mantine/charts';
import { Stack, Text } from '@mantine/core';
const positiveTrend = [10, 20, 40, 20, 40, 10, 50];
const negativeTrend = [50, 40, 20, 40, 20, 40, 10];
const neutralTrend = [10, 20, 40, 20, 40, 10, 50, 5, 10];
function Demo() {
return (
<Stack gap="sm">
<Text>Positive trend:</Text>
<Sparkline
w={200}
h={60}
data={positiveTrend}
trendColors={{ positive: 'teal.6', negative: 'red.6', neutral: 'gray.5' }}
fillOpacity={0.2}
/>
<Text mt="md">Negative trend:</Text>
<Sparkline
w={200}
h={60}
data={negativeTrend}
trendColors={{ positive: 'teal.6', negative: 'red.6', neutral: 'gray.5' }}
fillOpacity={0.2}
/>
<Text mt="md">Neutral trend:</Text>
<Sparkline
w={200}
h={60}
data={neutralTrend}
trendColors={{ positive: 'teal.6', negative: 'red.6', neutral: 'gray.5' }}
fillOpacity={0.2}
/>
</Stack>
);
}
RichTextEditor now supports tasks tiptap extension:
import TaskItem from '@tiptap/extension-task-item';
import { useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import { getTaskListExtension, RichTextEditor } from '@mantine/tiptap';
function Demo() {
const editor = useEditor({
extensions: [
StarterKit,
getTaskListExtension(TipTapTaskList),
TaskItem.configure({
nested: true,
HTMLAttributes: {
class: 'test-item',
},
}),
],
content: `
<ul data-type="taskList">
<li data-type="taskItem" data-checked="true">A list item</li>
<li data-type="taskItem" data-checked="false">And another one</li>
</ul>
`,
});
return (
<div style={{ padding: 40 }}>
<RichTextEditor editor={editor}>
<RichTextEditor.Toolbar>
<RichTextEditor.ControlsGroup>
<RichTextEditor.TaskList />
<RichTextEditor.TaskListLift />
<RichTextEditor.TaskListSink />
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>
</div>
);
}
Select, MultiSelect, TagsInput and Autocomplete
components now support renderOption
prop that allows to customize option rendering:
import {
IconAlignCenter,
IconAlignJustified,
IconAlignLeft,
IconAlignRight,
IconCheck,
} from '@tabler/icons-react';
import { Group, Select, SelectProps } from '@mantine/core';
const iconProps = {
stroke: 1.5,
color: 'currentColor',
opacity: 0.6,
size: 18,
};
const icons: Record<string, React.ReactNode> = {
left: <IconAlignLeft {...iconProps} />,
center: <IconAlignCenter {...iconProps} />,
right: <IconAlignRight {...iconProps} />,
justify: <IconAlignJustified {...iconProps} />,
};
const renderSelectOption: SelectProps['renderOption'] = ({ option, checked }) => (
<Group flex="1" gap="xs">
{icons[option.value]}
{option.label}
{checked && <IconCheck style={{ marginInlineStart: 'auto' }} {...iconProps} />}
</Group>
);
function Demo() {
return (
<Select
label="Select with renderOption"
placeholder="Select text align"
data={[
{ value: 'left', label: 'Left' },
{ value: 'center', label: 'Center' },
{ value: 'right', label: 'Right' },
{ value: 'justify', label: 'Justify' },
]}
renderOption={renderSelectOption}
/>
);
}
All Mantine components have been migrated to logical CSS properties
(as a replacement for rtl styles) and :where pseudo-class
(as a replacement for private CSS variables). These changes
should not impact the usage of Mantine components, but now Mantine CSS files have smaller size. For example,
@mantine/core/styles.css
now has ~ 8% smaller size (192kb -> 177kb).
You can now pass props down to recharts Bar, Area and Line components
with barProps
, areaProps
and lineProps
props on BarChart, AreaChart and LineChart components.
All props accepts either an object with props or a function that receives
series data as an argument and returns an object with props.
PieChart now supports percent
labels:
import { BarChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return (
<BarChart
h={200}
data={data}
dataKey="month"
orientation="vertical"
yAxisProps={{ width: 80 }}
barProps={{ radius: 10 }}
series={[{ name: 'Smartphones', color: 'blue.6' }]}
/>
);
}
New articles added to the help center:
swap
handlerform.setFieldValue
now supports callback function as an argumentpx
, py
, mx
and my
style props now use logical CSS properties padding-inline
, padding-block
, margin-inline
and margin-block
instead of padding-left
, padding-right
, etc.me
, ms
, ps
, pe
style props to set margin-inline-end
, margin-inline-start
, padding-inline-start
and padding-inline-end
CSS propertiesPopover
now support floatingStrategy
prop to control Floating UI strategy
@mantine/charts
components now support children
prop which passes children to the root recharts componentonClear
prop, the function is called when clear button is clickedonRemove
prop, the function is called with removed item value when one of the items is deselectedPublished by rtivital 8 months ago
[@mantine/core]
NumberInput: Fix double border between controls appeared on low resolution screens (#5753)[@mantine/hooks]
use-hotkeys: Fix incorrect HotkeyItem
type (#5705)[@mantine/hooks]
use-resize-observer: Fix incorrect ref type (#5759)[@mantine/core]
ScrollArea: Fix offsetScrollbars
not working on y-axis (#5762)[@mantine/core]
NavLink: Add collapse
Styles API selector (#5776)[@mantine/hooks]
Fixed initial value of the online
attribute returned by useNetwork()
in Firefox (#5766)[@mantine/core]
PinInput: Fix inputs not being updated with length
prop changes[@mantine/core]
PinInput: Fix incorrect onComplete
behavior (#5774, #5771)[@mantine/core]
Card: Fix incorrect margins in first and last sections when CardSection
component is used instead of Card.Section
(#5742)[@mantine/core]
Tooltip: Fix multiline prop not working correctly in Tooltip.Floating
componentFull Changelog: https://github.com/mantinedev/mantine/compare/7.5.2...7.5.3
Published by rtivital 8 months ago
[@mantine/core]
ActionIcon: Fix icon width and height defined in % not working correctly[@mantine/core]
ScrollArea: Fix offsetScrollbars
not working (#5733)[@mantine/tiptap]
Fix initialExternal
on RichTextEditor.Link
control not working correctly[@mantine/core]
FileInput: Fix incorrect extend
function type[@mantine/core]
PinInput: Fix various issues related to user input and pasting into the input (#5704)[@mantine/form]
Add callback argument support to form.setFieldValue
handler (#5696)[@mantine/core]
Add explicit extension to exports to support NodeNext TypeScript resolution (#5697)[@mantine/hooks]
use-list-state: Add swap
handler support (#5716)[@mantine/core]
Fix NodeNext TypeScript resolution not working correctly for PolymorphicComponentProps and PolymorphicRef types (#5730)[@mantine/core]
Fix cjs builds unable to resolve third-party dependencies with certain TypeScript settings (#5741)[@mantine/core]
Transition: Fix skew-up transition not working (#5714)[@mantine/core]
Select: Fix active option not being scrolled into view when the dropdown opens[@mantine/core]
Menu: Fix unexpected focus trap when keepMounted is false (#4502)[@mantine/core]
ScrollArea: Fix style
prop not being passed to the element when used in viewportProps
(#5594)[@mantine/core]
Divider: Fix poor color contrast with light color scheme[@mantine/core]
Modal: Fix incorrect content border-radius when fullScreen
prop is set[@mantine/core]
Modal: Fix scroll container not working correctly when ScrollArea is used as a scroll container for a full screen modal[@mantine/notifications]
Fix notifications handlers not allowing passing data-* attributes (#5640)Full Changelog: https://github.com/mantinedev/mantine/compare/7.5.1...7.5.2
Published by rtivital 9 months ago
[@mantine/core]
Indicator: Improve processing animation for lo-resolution monitors (#5682)[@mantine/hooks]
use-debounced-state: Fix incorrect type definition (#5665)[@mantine/hooks]
use-session-storage: Fix default value not being set in the storage on initial render (#5663)[@mantine/core]
Combobox: Fix incorrect dropdown styles with custom ScrollArea component (#5677)[@mantine/form]
Fix incorrect touch and dirty state handling in form.initialize
(#5623)[@mantine/core]
Chip: Fix error thrown when page is modified with Google Translate (#5586)[@mantine/form]
Add previous value as second argument to onValuesChange
(#5649)[@mantine/core]
Fix autoContrast
defined on theme not working in some components (#5655)[@mantine/core]
Fix broken alignment in Checkbox, Radio and Switch (#5648)[@mantine/core-highlight]
Add withCopyButton
prop support to CodeHighlightTabs (#5608)[@mantine/core]
Update useComputedColorScheme
types to match definition with other similar hooks (#5588)[@mantine/core]
MultiSelect: Forbid select item removal if associated item becomes disabled (#5630)Full Changelog: https://github.com/mantinedev/mantine/compare/7.5.0...7.5.1
Published by rtivital 9 months ago
View changelog with demos on mantine.dev website
New DonutChart component:
import { DonutChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return <DonutChart data={data} />;
}
New PieChart component:
import { PieChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return <PieChart data={data} />;
}
DatePickerInput, MonthPickerInput and
YearPickerInput now support valueFormatter
prop.
valueFormatter
is a more powerful alternative to valueFormat
prop.
It allows formatting value label with a custom function.
The function is the same for all component types (default
, multiple
and range
)
– you need to perform additional checks inside the function to handle different types.
Example of using a custom formatter function with type="multiple"
:
import dayjs from 'dayjs';
import { useState } from 'react';
import { DateFormatter, DatePickerInput } from '@mantine/dates';
const formatter: DateFormatter = ({ type, date, locale, format }) => {
if (type === 'multiple' && Array.isArray(date)) {
if (date.length === 1) {
return dayjs(date[0]).locale(locale).format(format);
}
if (date.length > 1) {
return `${date.length} dates selected`;
}
return '';
}
return '';
};
function Demo() {
const [value, setValue] = useState<Date[]>([]);
return (
<DatePickerInput
label="Pick 2 dates or more"
placeholder="Pick 2 dates or more"
value={value}
onChange={setValue}
type="multiple"
valueFormatter={formatter}
/>
);
}
You can now force each month to have 6 weeks by setting consistentWeeks: true
on
DatesProvider. This is useful if you want to avoid layout
shifts when month changes.
import { DatePicker, DatesProvider } from '@mantine/dates';
function Demo() {
return (
<DatesProvider settings={{ consistentWeeks: true }}>
<DatePicker />
</DatesProvider>
);
}
It is now possible to change series labels with label
property
in series
object. This feature is supported in AreaChart,
BarChart and LineChart components.
import { AreaChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return (
<AreaChart
h={300}
data={data}
dataKey="date"
type="stacked"
withLegend
legendProps={{ verticalAlign: 'bottom' }}
series={[
{ name: 'Apples', label: 'Apples sales', color: 'indigo.6' },
{ name: 'Oranges', label: 'Oranges sales', color: 'blue.6' },
{ name: 'Tomatoes', label: 'Tomatoes sales', color: 'teal.6' },
]}
/>
);
}
All @mantine/charts
components now support valueFormatter
prop, which allows
formatting value that is displayed on the y axis and inside the tooltip.
import { AreaChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return (
<AreaChart
h={300}
data={data}
dataKey="date"
type="stacked"
valueFormatter={(value) => new Intl.NumberFormat('en-US').format(value)}
series={[
{ name: 'Apples', color: 'indigo.6' },
{ name: 'Oranges', color: 'blue.6' },
{ name: 'Tomatoes', color: 'teal.6' },
]}
/>
);
}
New Title textWrap
prop sets text-wrap
CSS property. It controls how text inside an element is wrapped.
import { Title } from '@mantine/core';
function Demo() {
return (
<Title order={3} textWrap="wrap">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quasi voluptatibus inventore iusto
cum dolore molestiae perspiciatis! Totam repudiandae impedit maxime!
</Title>
);
}
You can also set textWrap
on theme:
import { createTheme, MantineProvider } from '@mantine/core';
const theme = createTheme({
headings: {
textWrap: 'wrap',
},
});
function Demo() {
return (
<MantineProvider theme={theme}>
<Title>Some very long title that should wrap</Title>
</MantineProvider>
);
}
If set on theme, textWrap
is also applied to headings in TypographyStylesProvider
All components now support mod
prop, which allows adding data attributes to
the root element:
import { Box } from '@mantine/core';
<Box mod="data-button" />;
// -> <div data-button />
<Box mod={{ opened: true }} />;
// -> <div data-opened />
<Box mod={{ opened: false }} />;
// -> <div />
<Box mod={['button', { opened: true }]} />;
// -> <div data-button data-opened />
<Box mod={{ orientation: 'horizontal' }} />;
// -> <div data-orientation="horizontal" />
shift
and flip
middlewares documentationNew articles added to the help center:
readOnly
proploading
state animationwithItemsBorder
prop which allows removing border between itemstransitionDuration
prop which controls section width animation durationresize
prop, which allows setting resize
CSS property on the input@mantine/hooks
package now exports readLocalStorageValue and readSessionStorageValue function to get value from storage outside of React componentsPublished by rtivital 9 months ago
[@mantine/modals]
Fix onClose
throwing error if trapFocus: false
is passed to one of the modals (#5577)[@mantine/dates]
Add missing placeholder
styles api selector to DatePickerInput, MonthPickerInput and YearPickerInput components[@mantine/tiptap]
Fix incorrect disabled controls in dark color scheme[@mantine/core]
MultiSelect: Fix combobox.closeDropdown()
called twice in onBlur
method[@mantine/tiptap]
Fix incorrect peer dependencies[@mantine/core]
Fix incorrect colors resolving logic for bg
style prop[@mantine/core]
Remove global height styles from body and html[@mantine/hooks]
use-media-query: Fix getInitialValueInEffect
not working correctly when initial value is provided (#5575, #5549)[@mantine/core]
Divider: Change default colors to match other components (#5480)[@mantine/core]
Fix incorrect forceColorScheme={undefined}
handling (#4959)[@mantine/core]
Menu: Remove duplicated static class on the dropdown element (#5537)[@mantine/core]
Add /
support for rgba calculations (#5544)Full Changelog: https://github.com/mantinedev/mantine/compare/7.4.1...7.4.2
Published by rtivital 9 months ago
[@mantine/core]
Combobox: Fix numpad enter not working (#5526)[@mantine/core]
Combobox: Fix onClose
prop not working (#5509)[@mantine/core]
AppShell: Fix header height 0 not working (#5514)[@mantine/core]
ColorPicker: Fix incorrect background gradient in AlphaSlider (#5518)[@mantine/core]
Indicator: Fix autoContrast
being passed to the dom node as attribute (#5508)[@mantine/core]
NumberInput: Fix allowLeadingZeros
prop not working[@mantine/core]
NumberInput: Fix incorrect controls border color in disabled state[@mantine/core]
NumberInput: Fix incorrect -0.0, -0.00, -0.000 ... inputs handling[@mantine/core]
Popover: Improve width
prop type[@mantine/core]
Improve types of data
prop in Autocomplete and TagsInput components[@mantine/core]
MultiSelect: Fix required
prop not displaying required asterisk[@mantine/hooks]
use-scroll-into-view: Improve types (#5426)[@mantine/core]
MultiSelect: Fix incorrect pointer-events
style on the right section (#5472)[@mantine/core]
Fix breakpoints defined in px being transformed into em when visibleFrom
and hiddenFrom
props are used (#5457)[@mantine/core]
Rating: Improve size
type (#5470)[@mantine/core]
ScrollArea: Fix ScrollArea.Autosize working incorrectly with some tables (#5481)[@mantine/core]
NumberInput: Add support for numbers that are larger than Number.MAX_SAFE_INTEGER (#5471)[@mantine/core]
Combobox: Fix readonly data array not being supported (#5477)[@mantine/charts]
Fix incorrect y-axis styles in RTL (#5505)Full Changelog: https://github.com/mantinedev/mantine/compare/7.4.0...7.4.1
Published by rtivital 10 months ago
View changelog with demos on mantine.dev website
New @mantine/charts package provides a set of components
to build charts and graphs. All components are based on recharts.
Currently, the package provides AreaChart, BarChart,
LineChart and Sparkline components.
More components will be added in the next minor releases.
New AreaChart component:
import { AreaChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return (
<AreaChart
h={300}
data={data}
dataKey="date"
type="stacked"
series={[
{ name: 'Apples', color: 'indigo.6' },
{ name: 'Oranges', color: 'blue.6' },
{ name: 'Tomatoes', color: 'teal.6' },
]}
/>
);
}
New LineChart component:
import { LineChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return (
<LineChart
h={300}
data={data}
dataKey="date"
withLegend
series={[
{ name: 'Apples', color: 'indigo.6' },
{ name: 'Oranges', color: 'blue.6' },
{ name: 'Tomatoes', color: 'teal.6' },
]}
/>
);
}
New BarChart component:
import { BarChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return (
<BarChart
h={300}
data={data}
dataKey="month"
type="stacked"
orientation="vertical"
yAxisProps={{ width: 80 }}
series={[
{ name: 'Smartphones', color: 'violet.6' },
{ name: 'Laptops', color: 'blue.6' },
{ name: 'Tablets', color: 'teal.6' },
]}
/>
);
}
New Sparkline component:
import { Sparkline } from '@mantine/charts';
function Demo() {
return (
<Sparkline
w={200}
h={60}
data={[10, 20, 40, 20, 40, 10, 50]}
curveType="linear"
color="blue"
fillOpacity={0.6}
strokeWidth={2}
/>
);
}
You can now use OKLCH colors in theme.colors
.
OKLCH color model has 88.18% browser support,
it is supported in all modern browsers. OKLCH model provides 30% more colors than HSL model and
has several other advantages.
Example of adding OKLCH color to the theme:
import { Button, createTheme, Group, MantineProvider } from '@mantine/core';
const theme = createTheme({
colors: {
'oklch-blue': [
'oklch(96.27% 0.0217 238.66)',
'oklch(92.66% 0.0429 240.01)',
'oklch(86.02% 0.0827 241.66)',
'oklch(78.2% 0.13 243.83)',
'oklch(71.8% 0.1686 246.06)',
'oklch(66.89% 0.1986 248.32)',
'oklch(62.59% 0.2247 250.29)',
'oklch(58.56% 0.2209 251.26)',
'oklch(54.26% 0.2067 251.67)',
'oklch(49.72% 0.1888 251.59)',
],
},
});
function Demo() {
return (
<MantineProvider theme={theme}>
<Group>
<Button color="oklch-blue">Filled</Button>
<Button color="oklch-blue" variant="outline">
Outline
</Button>
<Button color="oklch-blue" variant="light">
Light
</Button>
</Group>
</MantineProvider>
);
}
New theme.autoContrast
property controls whether text color should be changed based on the given color
prop
in the following components:
variant="filled"
onlyvariant="filled"
onlyvariant="filled"
onlyvariant="filled"
onlyvariant="filled"
onlyvariant="filled"
onlyvariant="filled"
onlyvariant="filled"
onlyvariant="filled"
onlyvariant="filled"
onlyvariant="pills"
onlyautoContrast
can be set globally on the theme level or individually for each component via autoContrast
prop,
except for Spotlight and @mantine/dates components, which only support global theme setting.
import { Button, Code, Group } from '@mantine/core';
function Demo() {
return (
<>
<Code>autoContrast: true</Code>
<Group mt="xs" mb="lg">
<Button color="lime.4" autoContrast>
Lime.4 button
</Button>
<Button color="blue.2" autoContrast>
Blue.2 button
</Button>
<Button color="orange.3" autoContrast>
Orange.3 button
</Button>
</Group>
<Code>autoContrast: false</Code>
<Group mt="xs">
<Button color="lime.4">Lime.4 button</Button>
<Button color="blue.2">Blue.2 button</Button>
<Button color="orange.3">Orange.3 button</Button>
</Group>
</>
);
}
autoContrast
checks whether the given color luminosity is above or below the luminanceThreshold
value
and changes text color to either theme.white
or theme.black
accordingly:
import { Button, createTheme, MantineProvider, Stack } from '@mantine/core';
const theme = createTheme({
autoContrast: true,
luminanceThreshold: 0.3,
});
function Wrapper(props: any) {
const buttons = Array(10)
.fill(0)
.map((_, index) => (
<Button key={index} color={`blue.${index}`}>
Button
</Button>
));
return (
<MantineProvider theme={theme}>
<Stack>{buttons}</Stack>
</MantineProvider>
);
}
alpha
, lighten
and darken
functions now support CSS variables (with color-mix) and OKLCH colors.
All functions are available both in @mantine/core
(.ts
/.js
files) and postcss-preset-mantine (.css
files, requires version 1.12.0 or higher).
In .css
files:
.demo-alpha {
color: alpha(var(--mantine-color-red-4), 0.5);
border: 1px solid alpha(#ffc, 0.2);
}
.demo-lighten-darken {
color: lighten(var(--mantine-color-red-4), 0.5);
border: 1px solid darken(#ffc, 0.2);
}
Will be transformed to:
.demo-alpha {
color: color-mix(in srgb, var(--mantine-color-red-4), transparent 50%);
border: 1px solid color-mix(in srgb, #ffc, transparent 80%);
}
.demo-lighten-darken {
color: color-mix(in srgb, var(--mantine-color-red-4), white 50%);
border: 1px solid color-mix(in srgb, #ffc, black 20%);
}
In .ts
/.js
files:
import { alpha, lighten } from '@mantine/core';
alpha('#4578FC', 0.45); // -> rgba(69, 120, 252, 0.45)
alpha('var(--mantine-color-gray-4)', 0.74);
// -> color-mix(in srgb, var(--mantine-color-gray-4), transparent 26%)
lighten('#4578FC', 0.45); // -> #a3c1ff
lighten('var(--mantine-color-gray-4)', 0.74);
// -> color-mix(in srgb, var(--mantine-color-gray-4), white 74%)
Note that alpha
function is a replacement for rgba
. It was renamed to
have a more clear meaning, as it can now be used with CSS variables and OKLCH colors.
rgba
function is still available as an alias for alpha
function.
@mantine/form
now supports enhanceGetInputProps. enhanceGetInputProps
is a function that can be used to add additional props to the object returned by form.getInputProps
.
You can define it in useForm
hook options. Its argument is an object with the following properties:
inputProps
– object returned by form.getInputProps
by defaultfield
– field path, first argument of form.getInputProps
, for example name
, user.email
, users.0.name
options
– second argument of form.getInputProps
, for example { type: 'checkbox' }
, can be used to pass additionalenhanceGetInputProps
functionform
– form instanceExample of using enhanceGetInputProps
to disable input based on field path:
import { NumberInput, TextInput } from '@mantine/core';
import { useForm } from '@mantine/form';
interface FormValues {
name: string;
age: number | string;
}
function Demo() {
const form = useForm<FormValues>({
initialValues: { name: '', age: '' },
enhanceGetInputProps: (payload) => ({
disabled: payload.field === 'name',
}),
});
return (
<>
<TextInput {...form.getInputProps('name')} label="Name" placeholder="Name" />
<NumberInput {...form.getInputProps('age')} label="Age" placeholder="Age" mt="md" />
</>
);
}
Example of using enhanceGetInputProps
to add additional props to the input based on option passed to form.getInputProps
:
import { NumberInput, TextInput } from '@mantine/core';
import { useForm } from '@mantine/form';
interface FormValues {
name: string;
age: number | string;
}
function Demo() {
const form = useForm<FormValues>({
initialValues: { name: '', age: '' },
enhanceGetInputProps: (payload) => {
if (payload.options.fieldType === 'name') {
return {
label: 'Your name',
placeholder: 'Your name',
withAsterisk: true,
description: 'Your personal information is stored securely. (Just kidding!)',
};
}
return {};
},
});
return (
<>
<TextInput {...form.getInputProps('name', { fieldType: 'name' })} />
<NumberInput {...form.getInputProps('age')} label="Age" placeholder="Age" mt="md" />
</>
);
}
@mantine/form
now supports form.initialize
handler.
When called form.initialize
handler sets initialValues
and values
to the same value
and marks form as initialized. It can be used only once, next form.initialize
calls
are ignored.
form.initialize
is useful when you want to sync form values with backend API response:
import { Button, NumberInput, TextInput } from '@mantine/core';
import { isInRange, isNotEmpty, useForm } from '@mantine/form';
interface FormValues {
name: string;
age: number | string;
}
function apiRequest(): Promise<FormValues> {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ name: 'John Doe', age: 25 });
}, 1000);
});
}
function Demo() {
const form = useForm<FormValues>({
initialValues: { name: '', age: 0 },
validate: {
name: isNotEmpty('Name is required'),
age: isInRange({ min: 18 }, 'You must be at least 18 to register'),
},
});
return (
<>
<TextInput {...form.getInputProps('name')} label="Name" placeholder="Name" />
<NumberInput {...form.getInputProps('age')} label="Age" placeholder="Age" mt="md" />
<Button onClick={() => apiRequest().then((values) => form.initialize(values))} mt="md">
Initialize form
</Button>
</>
);
}
Example with TanStack Query (react-query):
import { useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useForm } from '@mantine/form';
function Demo() {
const query = useQuery({
queryKey: ['current-user'],
queryFn: () => fetch('/api/users/me').then((res) => res.json()),
});
const form = useForm({
initialValues: {
name: '',
email: '',
},
});
useEffect(() => {
if (query.data) {
// Even if query.data changes, form will be initialized only once
form.initialize(query.data);
}
}, [query.data]);
}
Note that form.initialize
will erase all values that were set before it was called.
It is usually a good idea to set readOnly
or disabled
on all form fields before
form.initialize
is called to prevent data loss. You can implement this with
enhanceGetInputProps:
import { NumberInput, TextInput } from '@mantine/core';
import { useForm } from '@mantine/form';
interface FormValues {
name: string;
age: number | string;
}
function Demo() {
const form = useForm<FormValues>({
initialValues: { name: '', age: '' },
enhanceGetInputProps: (payload) => {
if (!payload.form.initialized) {
return { disabled: true };
}
return {};
},
});
return (
<>
<TextInput {...form.getInputProps('name')} label="Your name" placeholder="Your name" />
<NumberInput {...form.getInputProps('age')} label="Age" placeholder="Age" mt="md" />
<Button onClick={() => form.initialize({ name: 'John', age: 20 })} mt="md">
Initialize form
</Button>
</>
);
}
@mantine/form
now supports validbot schema resolver:
yarn add valibot mantine-form-valibot-resolver
Basic fields validation:
import { valibotResolver } from 'mantine-form-valibot-resolver';
import { email, minLength, minValue, number, object, string } from 'valibot';
import { useForm } from '@mantine/form';
const schema = object({
name: string([minLength(2, 'Name should have at least 2 letters')]),
email: string([email('Invalid email')]),
age: number([minValue(18, 'You must be at least 18 to create an account')]),
});
const form = useForm({
initialValues: {
name: '',
email: '',
age: 16,
},
validate: valibotResolver(schema),
});
form.validate();
form.errors;
// -> {
// name: 'Name should have at least 2 letters',
// email: 'Invalid email',
// age: 'You must be at least 18 to create an account'
// }
Nested fields validation
import { valibotResolver } from 'mantine-form-valibot-resolver';
import { minLength, object, string } from 'valibot';
import { useForm } from '@mantine/form';
const nestedSchema = object({
nested: object({
field: string([minLength(2, 'Field should have at least 2 letters')]),
}),
});
const form = useForm({
initialValues: {
nested: {
field: '',
},
},
validate: valibotResolver(nestedSchema),
});
form.validate();
form.errors;
// -> {
// 'nested.field': 'Field should have at least 2 letters',
// }
List fields validation:
import { valibotResolver } from 'mantine-form-valibot-resolver';
import { array, minLength, object, string } from 'valibot';
import { useForm } from '@mantine/form';
const listSchema = object({
list: array(
object({
name: string([minLength(2, 'Name should have at least 2 letters')]),
})
),
});
const form = useForm({
initialValues: {
list: [{ name: '' }],
},
validate: valibotResolver(listSchema),
});
form.validate();
form.errors;
// -> {
// 'list.0.name': 'Name should have at least 2 letters',
// }
ScrollArea now supports scrollbars
prop, which allows controlling directions at which scrollbars should be rendered.
Supported values are x
, y
and xy
. If scrollbars="y"
is set, only the vertical scrollbar will be rendered, and it will not be possible to scroll horizontally:
import { Box, ScrollArea } from '@mantine/core';
function Demo() {
return (
<ScrollArea w={300} h={200} scrollbars="y">
<Box w={600}>{/* ... content */}</Box>
</ScrollArea>
);
}
Title component now supports lineClamp
prop, which allows truncating text after a specified number of lines:
import { Box, Title } from '@mantine/core';
function Demo() {
return (
<Box maw={400}>
<Title order={2} lineClamp={2}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure doloremque quas dolorum. Quo
amet earum alias consequuntur quam accusamus a quae beatae, odio, quod provident consectetur
non repudiandae enim adipisci?
</Title>
</Box>
);
}
CSS variables for primary color are now available, you can use the following variables in your styles:
--mantine-primary-color-0
--mantine-primary-color-1
--mantine-primary-color-2
--mantine-primary-color-3
--mantine-primary-color-4
--mantine-primary-color-5
--mantine-primary-color-6
--mantine-primary-color-7
--mantine-primary-color-8
--mantine-primary-color-9
--mantine-primary-color-contrast
--mantine-primary-color-filled
--mantine-primary-color-filled-hover
--mantine-primary-color-light
--mantine-primary-color-light-hover
--mantine-primary-color-light-color
Help center is a new website with guides, tutorials and frequently
asked questions. Currently, it has 14 questions, more FAQs will be added in the next releases.
form.getInputProps
, enhanceGetInputProps
and how to integrate form.getInputProps
with custom inputs.@mantine/hooks
package. It is planned to document functions from other packages in next releases.variantColorsResolver
demos have been added to ActionIcon, ThemeIcon and Badge components.@tabler/icons
package. It is no longer required to install @tabler/icons
package to use RichTextEditor
component. Icons used in the editor are now a part of the @mantine/tiptap
package. This change improves bundling performance in several cases (mostly when using RichTextEditor
in Next.js apps).circle
prop which makes the badge round.ff
style prop with mono
, text
and heading
values: <Box ff="mono" />
.RichTextEditor.Undo
and RichTextEditor.Redo
controls.luminance
color function was added. It returns color luminance as a number between 0 and 1.flex
style prop which allows setting flex
CSS property on the root element.stepHoldDelay
and stepHoldInterval
props have been added to NumberInput.errorPriority
configuration which allows controlling the order of errors specified in the schema. This feature requires updating mantine-form-zod-resolver
to version 1.1.0 or higher.icon
prop, which allows overriding default icon. It is useful when it is not possible to replace CloseButton
, for example, in Drawer component.onChange
with an additional argument – option object. It contains label
, value
and optional disabled
properties.styles
prop of all components.Published by rtivital 10 months ago
[@mantine/core]
Portal: Fix empty className string throwing error (#5400)[@mantine/core]
Select: Fix incorrect empty string as initial value handing[@mantine/core]
Fix error thrown in jest tests when autosize Textarea is used in Next.js application (#5393)[@mantine/core]
Loader: Fix default loaders not being available if custom loader was default with defaultProps on theme[@mantine/core]
Chip: Fix color
prop not working without specifying variant[@mantine/core]
MultiSelect: Fix dropdown not being opened when Space key is pressed and the component is not searchable[@mantine/core]
NavLink: Add missing Space key handling for collapse/expand nested links[@mantine/dates]
DateInput: Fix incorrect clear button size[@mantine/core]
Fix text inside MultiSelect, TagsInput and PillsInput search field not being possible to select with mouse[@mantine/core]
Set cursor to not-allowed
on disabled Checkbox, Radio and Switch[@mantine/core]
NumberInput: Improve disabled increment/decrement controls styles[@mantine/core]
Button: Fix incorrect alignment if button is used in the same container as other buttons with component
prop[@mantine/core]
SegmentedControl: Improve readOnly styles[@mantine/core]
NumberInput: Fix incorrect controls text color in error state[@mantine/core]
Change divs to more semantic elements in Modal and Drawer[@mantine/core]
Make header height of Modal and Drawer consistent to prevent layout shift when withCloseButton
prop is changed[@mantine/core]
Fix onChange
not being called in Radio, Checkbox and Chip components if they are used inside X.Group
[@mantine/core]
NumberInput: Fix incorrect negative decimal values input handing[@mantine/core]
Button: Fix incorrect Loader vertical alignment[@mantine/vanilla-extract]
Expose all primary colors values[@mantine/core]
Menu: Fix incorrect aria roles (#5372)[@mantine/core]
Table: Fix sticky header being overlayed by elements in table rows in some cases (#5385)[@mantine/core]
Combobox: Fix rightSection
and leftSection
nor being visible on Combobox.Search
(#5368)[@mantine/core]
Tabs: Fix clipped border of outline variant (#5370)[@mantine/core]
Fix incorrect rightSectionPointerEvents
in Select and MultiSelect components (#5371)[@mantine/core]
Alert: Fix incorrect margin if title is hidden[@mantine/core]
Overlay: Fix blur styles not working in old SafariFull Changelog: https://github.com/mantinedev/mantine/compare/7.3.1...7.3.2
Published by rtivital 11 months ago
[@mantine/core]
Fix broken default colors override[@mantine/core]
Menu: Improve click-hover
trigger accessibility (#5335)[@mantine/core]
Fix incorrect lineHeight
theme variables resolving (#5375)[@mantine/core]
Select: Fix error thrown if google translate changes labels (#5377)[@mantine/tiptap]
Add missing control
Styles API selector to RichTextEditor.Link
(#5171)[@mantine/core]
Grid: Fix incorrect Grid.Col auto span handing if one Grid is used inside another Grid (#5278)[@mantine/core]
Grid: Fix incorrect Grid.Col styles when the column is auto
as base value and content
as breakpoint value (#5280)[@mantine/core]
Fix various RTL issues (#5250)[@mantine/dates]
Fix hideOutsideDates
now working if @mantine/dates
is used as a headless library (#5003)[@mantine/core]
SegmentedControl: Remove animation during initialization (#5182)[@mantine/core]
Menu: Fix broken focus logic when keepMounted
is set (#4502)[@mantine/tiptap]
Remove @tabler/icons
dependency to improve bundling performance (#5279)[@mantine/core]
Fix inputs have incorrect left and right sections colors in error state (#5304)[@mantine/core]
Title: Add lineClamp
support (#5321)[@mantine/core]
Grid: Change default overflow to visible (#5276)[@mantine/core]
ScrollArea: Fix incorrect scrollbars styles (#4904)[@mantine/core]
Expose --mantine-primary-color-x
CSS variables (#5331)[@mantine/core]
Combobox: Fix incorrect Enter key handling when dropdown is opened and option is not selected (#5348)[@mantine/core]
NumberInput: Fix startValue
nor working if min
is set (#5308)[@mantine/core]
Collapse: Add missing Collapse.extend function (#5313)[@mantine/core]
Fix incorrect clamp() function handing in style props (#5330)[@mantine/core]
PinInput: Trim value on paste before validation (#5340)[@mantine/core]
PinInput: Fix incorrectly assigned ref (#5365)[@mantine/core]
Remove use client from createPolymorphicComponent factory (#5367)Full Changelog: https://github.com/mantinedev/mantine/compare/7.3.0...7.3.1
Published by rtivital 11 months ago
View changelog with demos on mantine.dev website
smaller-than
and larger-than
mixins can be used to create styles that will be applied only when the screen is smaller or larger than specified breakpoint.
Note that to use these mixins, you need to update postcss-preset-mantine to version 1.11.0
or higher.
.demo {
@mixin smaller-than 320px {
color: red;
}
@mixin larger-than 320px {
color: blue;
}
}
Will be transformed to:
// Breakpoint values are converted to em units
// In smaller-than mixin 0.1px is subtracted from breakpoint value
// to avoid intersection with larger-than mixin
@media (max-width: 19.99375em) {
.demo {
color: red;
}
}
@media (min-width: 20em) {
.demo {
color: blue;
}
}
You can also use smaller-than
and larger-than
mixins with mantine breakpoints:
.demo {
@mixin smaller-than $mantine-breakpoint-sm {
color: red;
}
@mixin larger-than $mantine-breakpoint-sm {
color: blue;
}
}
@mantine/form
schema validation resolver packages are now available as separate packages.
Moving resolvers to separate packages allows making them type-safe and fully tested.
Old resolvers are still exported from @mantine/form
package – you will be able to use them without any changes
until 8.0.0 release.
The new packages are drop-in replacements for old resolvers, they have the same API and can be used in the same way.
Example of zod resolver:
yarn add zod mantine-form-zod-resolver
import { z } from 'zod';
import { useForm } from '@mantine/form';
import { zodResolver } from 'mantine-form-zod-resolver';
const schema = z.object({
name: z.string().min(2, { message: 'Name should have at least 2 letters' }),
email: z.string().email({ message: 'Invalid email' }),
age: z.number().min(18, { message: 'You must be at least 18 to create an account' }),
});
const form = useForm({
initialValues: {
name: '',
email: '',
age: 16,
},
validate: zodResolver(schema),
});
form.validate();
form.errors;
// -> {
// name: 'Name should have at least 2 letters',
// email: 'Invalid email',
// age: 'You must be at least 18 to create an account'
// }
rem and em function now support space-separated values. This feature is available
both in rem
function exported from @mantine/core
package and postcss-preset-mantine.
Note that you need to update postcss-preset-mantine to 1.11.0
to use this feature.
import { rem } from '@mantine/core';
rem('16px 32px');
// -> calc(1rem * var(--mantine-scale)) calc(2rem * var(--mantine-scale))
All components props that are converted to rem
units now support space-separated values as well.
For example, space-separated values can be used in radius
prop of Modal component:
import { Modal } from '@mantine/core';
function Demo() {
return <Modal radius="10px 10px 0 0" opened onClose={() => {}} />;
}
All Mantine components now support component
and renderRoot
props event if they are not polymorphic.
The difference between polymorphic and non-polymorphic components is that polymorphic components
include the full set of props of the component passed to the component
prop, while non-polymorphic
components only include props that are specific to the original component. It is done this way to
improve TypeScript performance.
import { Group } from '@mantine/core';
// Group is not polymorphic component,
// but it still supports component and renderRoot props
function Demo() {
return (
<Group component="nav">
<a>Item 1</a>
<a>Item 2</a>
<a>Item 3</a>
</Group>
);
}
Checkbox and Radio components now support outline
variant:
import { Radio, Checkbox, Stack } from '@mantine/core';
function Demo() {
return (
<Stack gap={7}>
<Checkbox variant="outline" label="Outline Checkbox" defaultChecked />
<Checkbox variant="outline" label="Outline indeterminate Checkbox" indeterminate />
<Radio variant="outline" label="Outline Radio" defaultChecked />
</Stack>
);
}
HueSlider and AlphaSlider components were added back:
import { useState } from 'react';
import { HueSlider, Text } from '@mantine/core';
function Demo() {
const [value, onChange] = useState(250);
return (
<>
<Text>Hue value: {value}</Text>
<HueSlider value={value} onChange={onChange} />
</>
);
}
import { useState } from 'react';
import { AlphaSlider, Text } from '@mantine/core';
function Demo() {
const [value, onChange] = useState(0.55);
return (
<>
<Text>Alpha value: {value}</Text>
<AlphaSlider color="#1c7ed6" value={value} onChange={onChange} />
</>
);
}
Button component now has loading state animation:
import { Button, Group } from '@mantine/core';
function Demo() {
const [loading, { toggle }] = useDisclosure();
return (
<>
<Group>
<Button loading={loading}>Filled button</Button>
<Button variant="light" loading={loading}>
Light button
</Button>
<Button variant="outline" loading={loading}>
Outline button
</Button>
</Group>
<Switch checked={loading} onChange={toggle} label="Loading state" mt="md" />
</>
);
}
Drawer now supports offset
prop. It changes drawer offset from the edge of the viewport:
import { useDisclosure } from '@mantine/hooks';
import { Drawer, Button } from '@mantine/core';
function Demo() {
const [opened, { open, close }] = useDisclosure(false);
return (
<>
<Drawer offset={8} radius="md" opened={opened} onClose={close} title="Authentication">
{/* Drawer content */}
</Drawer>
<Button onClick={open}>Open Drawer</Button>
</>
);
}
You can now use Mantine z-index CSS variables:
--mantine-z-index-app
– value 100
--mantine-z-index-modal
– value 200
--mantine-z-index-popover
– value 300
--mantine-z-index-overlay
– value 400
--mantine-z-index-max
– value 9999
Example of using --mantine-z-index-modal
variable:
/* Display content above the modal */
.my-content {
z-index: calc(var(--mantine-z-index-modal) + 1);
}
theme.colors.dark
colors were slightly changed to improve contrast and make it easier to read text.
You can preview new colors on this page. New colors values are:
--mantine-color-dark-0: #c9c9c9;
--mantine-color-dark-1: #b8b8b8;
--mantine-color-dark-2: #828282;
--mantine-color-dark-3: #696969;
--mantine-color-dark-4: #4a4a4a;
--mantine-color-dark-5: #404040;
--mantine-color-dark-6: #383838;
--mantine-color-dark-7: #2e2e2e;
--mantine-color-dark-8: #242424;
--mantine-color-dark-9: #212121;
If you prefer old colors, change theme settings on MantineProvider
:
import { createTheme } from '@mantine/core';
const theme = createTheme({
colors: {
dark: [
'#C1C2C5',
'#A6A7AB',
'#909296',
'#5c5f66',
'#373A40',
'#2C2E33',
'#25262b',
'#1A1B1E',
'#141517',
'#101113',
],
},
});
function Demo() {
return <MantineProvider theme={theme}>{/* Your app here */}</MantineProvider>;
}
@mantine/form
now has a dedicated page. It includes more examples for basic, nested and list fields validation for each resolver.minRange
prop.getInitialValueInEffect: false
option to get initial value during state initialization.useMantineColorScheme({ keepTransitions: true })
option allows keeping transitions when color scheme changes. Note that it is false
by default.<kbd />
element.hiddenValuesDivider
prop. It allows customizing divider character between values in value
prop of the hidden input.overflow
prop, which allows controlling overflow
CSS property on the root element. It is hidden
by default.removeScrollProps
prop. It allows configuring react-remove-scroll.offsetScrollbars
prop. It determines whether scrollbars should be offset, it is true
by default. The logic of scrollbars offset is controlled by react-remove-scroll.trigger="click-hover"
prop, to open menu both on click and on hover.keepMounted
prop on Tabs.Panel components individually, not only on Tabs
component.7.x
versions of @mantine/core
. To use it, update mantine-flagpack
to 4.0.0
.@mantine/ds
package has been deprecated. You can use @mantinex/mantine-logo
package to use MantineLogo
component in your project.Published by rtivital 11 months ago
[@mantine/core]
HoverCard: Remove opened
and onChange
props from types[@mantine/core]
RingProgress: Fix error thrown when thickness is larger than size / 4
[@mantine/dates]
DateInput: Fix unexpected values updates when the user tries to type in value with closed dropdown (#3818)[@mantine/core]
NumberInput: Fix onChange
called when value is changed by external state (#5235)[@mantine/core]
NumberInput: Fix onChange
function called in onBlur
when the value does not require updating[@mantine/core]
NumberInput: Improve onChange
handler to be called with number unless the input is empty (#5037)[@mantine/core]
SegmentedControl: Fix incorrect indicator position if padding is set on the root element[@mantine/core]
Select: Fix empty string not being handled correctly as option value[@mantine/core]
Blockquote: Fix incorrect border-radius
[@mantine/core]
Chip: Fix incorrect disabled styles in dark color scheme[@mantine/core]
Table: Set backgound-color
on thead
only if strickyHeader
prop is set[@mantine/core]
Radio: Fix radio icon size being the same width and height at every size[@mantine/tiptap]
Fix incorrect rtl controls styles (#5223)[@mantine/tiptap]
Fix unexpected background-color set on code
elementPublished by rtivital 12 months ago
[@mantine/core]
Numberinput: Reduce width of the right section to match controls width (#5033)[@mantine/core]
Popover: Add size
floating-ui middleware to prevent large dropdown from exceeding screen size (#5213)[@mantine/code-highlight]
Prevent error thowing if language is not recognized by highlight.js (#5099)[@mantine/notifications]
Fix limit
prop not working (#5105)[@mantine/dropzone]
Allow overriding props from react-dropzone-esm with component props (#5114)[@mantine/core]
Remove "use client";
directive from rem
, createTheme
and other utility theme functions (#5119)[@mantine/hooks]
use-hash: Add option to retrieve value initially without useEffect
(#5140)[@mantine/core]
PasswordInput: Fix incorrect styles when the component is wrapper with element with data-disabled
attribute (#5149)[@mantine/core]
Add support for values separated by space to rem
and em
functions (#5174)[@mantine/code-highlight]
Fix CodeHighlightTabs throwing error if language of the tab is nor specified (#5178)[@mantine/core]
Fieldset: Fix some elements overflowing the viewport width when rendered inside fieldset (#5179)[@mantine/core]
Modal: Fix ScrollArea not working as scroll container (#5189)[@mantine/core]
Text: Fix inline
prop not working (#5194)[@mantine/core]
Alert: Fix incorrect styles when the component is used without children (#5196)[@mantine/core]
Set aria-hidden
on Checkbox and Radio icons to prevent them being announced by screen readers (#5202)[@mantine/form]
Fix form.reset
not reseting values to updated initialValues
(#5123)Full Changelog: https://github.com/mantinedev/mantine/compare/7.2.0...7.2.1
Published by rtivital 12 months ago
You are welcome to share your GitHub templates with the community. Community templates are
featured on the getting started page. You can find a guide on how to
create and submit a template here.
Examples of templates that you can submit:
New NumberFormatter component allows to format numbers
with thousands separators, decimal separators, and custom number of decimal places.
It supports the same formatting related props as NumberInput component.
import { NumberFormatter } from '@mantine/core';
function Demo() {
return <NumberFormatter prefix="$ " value={1000000} thousandSeparator />;
}
@mantine/form
package now exports createFormActions
function that
can be used to change form state from anywhere in your application.
The mechanism of form actions is similar to notifications system,
modals manager and other similar packages.
To use form actions, set name
property in use-form settings:
import { useForm } from '@mantine/form';
export interface DemoFormValues {
name: string;
age: number;
}
function Demo() {
const form = useForm<DemoFormValues>({
name: 'demo-form',
initialValues: {
name: '',
age: 0,
},
});
}
Then call createFormActions
function with the same form name as specified in useForm
settings:
// Import type of form values from the file where you defined useForm
import type { DemoFormValues } from './DemoForm';
import { createFormActions } from '@mantine/form';
export const demoFormActions = createFormActions<DemoFormValues>('demo-form');
After that, you can use demoFormActions
to change form state from anywhere in your application.
For example, after a fetch request or after a user interaction with a component that does not have access
to the form state:
import { useEffect } from 'react';
import { Button } from '@mantine/core';
import { demoFormActions } from './demoFormActions';
function ExternalComponent() {
useEffect(() => {
fetch('/api/user')
.then((res) => res.json())
.then((res) =>
demoFormActions.setValues({
name: res.name,
age: res.age,
})
);
}, []);
return <Button onClick={() => demoFormActions.reset()}>Reset demo form</Button>;
}
Table component now supports data
prop which can be used to generate table rows
from given data:
import { Table, TableData } from '@mantine/core';
const tableData: TableData = {
caption: 'Some elements from periodic table',
head: ['Element position', 'Atomic mass', 'Symbol', 'Element name'],
body: [
[6, 12.011, 'C', 'Carbon'],
[7, 14.007, 'N', 'Nitrogen'],
[39, 88.906, 'Y', 'Yttrium'],
[56, 137.33, 'Ba', 'Barium'],
[58, 140.12, 'Ce', 'Cerium'],
],
};
function Demo() {
return <Table data={tableData} />;
}
Table component now supports stickyHeader
prop, which can be used to make the table header
stick to the top of the table:
import { Table } 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 rows = elements.map((element) => (
<Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Table stickyHeader stickyHeaderOffset={60}>
<Table.Thead>
<Table.Tr>
<Table.Th>Element position</Table.Th>
<Table.Th>Element name</Table.Th>
<Table.Th>Symbol</Table.Th>
<Table.Th>Atomic mass</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
<Table.Caption>Scroll page to see sticky thead</Table.Caption>
</Table>
);
}
It is now possible to use Mantine with Sass. You can find documentation
on this page. Note that it is still required to set up postcss-preset-mantine
in order for all functions to work properly. Sass can be used as a replacement for CSS modules
– it supports all features that CSS modules support.
You can find examples of Mantine + Sass usage in separate branches of templates:
Loader component now supports children
prop. The prop allows overriding the default
loader with any React node. It is useful in components that support loaderProps
(Button, LoadingOverlay, Dropzone, etc.)
– with loaderProps.children
you can now display any React node instead of the loader.
import { useDisclosure } from '@mantine/hooks';
import { LoadingOverlay, Button, Group, Box } from '@mantine/core';
function Demo() {
const [visible, { toggle }] = useDisclosure(false);
return (
<>
<Box pos="relative">
<LoadingOverlay visible={visible} loaderProps={{ children: 'Loading...' }} />
{/* ...other content */}
</Box>
<Group position="center">
<Button onClick={toggle}>Toggle overlay</Button>
</Group>
</>
);
}
All Mantine components now support lightHidden
and darkHidden
props that can be used to hide
components in a specific color scheme:
import { Button } from '@mantine/core';
function Demo() {
return (
<>
<Button color="cyan" lightHidden>
Visible in dark color scheme only
</Button>
<Button color="pink" darkHidden>
Visible in light color scheme only
</Button>
</>
);
}
New light-root
and dark-root
mixins were added to postcss-preset-mantine.
These mixins can be used to add color scheme specific styles to the :root
/html
element.
Note that to use these mixins, you need to update postcss-preset-mantine
to 1.9.0
or higher.
:root {
@mixin light-root {
--color: red;
}
@mixin dark-root {
--color: blue;
}
}
:global
selectorloaderProps
prop to pass props down to the Loader componenthoverColor
prop, which allows controlling color
property when the component is hovered. New property is supported in Button and ActionIcon components.renderRoot
and component
propsdata-checked
attribute when the checkbox is checkediconColor
proponValuesChange
option which can be used to sync form values with external statePublished by rtivital 12 months ago
[@mantine/core]
Change how primary color fallback is applied in default theme.variantColorResolver
to allow setting custom fallback values and undefined
handling[@mantine/core]
Select: Fix error thrown on blur when given value
is not in the data array[@mantine/core]
Fix option icon being smaller when option text has multiple lines[@mantine/core]
Spoiler: Fix unexpected empty space when hide label is null
(#5126)[@mantine/core]
Button: Fix different border width of regular and disabled buttons[@mantine/core]
Table: Fix row background changing on hover in dark color scheme even when highlightOnHover
prop is not set[@mantine/carousel]
Fix slideSize
prop not handling number values (#5050)[@mantine/core]
Add option to keep transitions when color scheme changes in useMantineColorScheme hook (#5092)[@mantine/core]
Improve pop-*
transitions animations (#5096)[@mantine/hooks]
use-local-storage: Fix error throwing if localStorage/sessionStorage is blocked by browser (#5091)[@mantine/dates]
Calendar: Fix incorrect focus logic when first item is disabled (#5078)Full Changelog: https://github.com/mantinedev/mantine/compare/7.1.5...7.1.6
Published by rtivital about 1 year ago
[@mantine/core]
HoverCard: Fix dropdown not visible when Checkbox/Switch is used as target (#5072)[@mantine/code-highlight]
Fix code not updating when content changes (#5073)[@mantine/core]
Highlight: Fix incorrect highlighted parts when one of the array items includes substrings of other item (#5045)[@mantine/core]
Rating: Fix container overflow when the width of total item exceeds parent element width (#5057)[@mantine/core]
Radio: Fix checked icon clipping and not being centered with some sizes (#5064)[@mantine/core]
Fix incorrect callback arguments values types (#5067)[@mantine/core]
TagsInput: Fix required
prop not working correctly (#5032)Full Changelog: https://github.com/mantinedev/mantine/compare/7.1.3...7.1.5
Published by rtivital about 1 year ago
[@mantine/core]
Paper: Fix incorrect withBorder
prop cascading to nested Paper components (#4930)[@mantine/core]
MultiSelect: Fix incorrect input styles without placeholder (#4954)[@mantine/core]
NumberInput: Fix focus shifting from the input when one of the controls is pressed (#5013)[@mantine/notifications]
Fix style
prop breaking animations (#5007)[@mantine/core]
Rating: Fix incorrect touch events handling (#4976)[@mantine/carousel]
Fix onClick
handler from nextControlProps
being overwritten by internal props (#4985)[@mantine/core]
MultiSelect: Fix selectFirstOptionOnChange
prop not working (#4997)[@mantine/core]
Select: Fix incorrect behavior when both searchValue
and value
are controlled (#4998)[@mantine/spotlight]
Fix DOM error thrown after HMR and several other cases (#4992)[@mantine/hooks]
use-timeout: Fix callback not running after state change (#4968)[@mantine/hooks]
use-focus-trap: Fix incorrect input[type="radio"]
handling (#4856)Full Changelog: https://github.com/mantinedev/mantine/compare/7.1.2...7.1.3
Published by rtivital about 1 year ago
[@mantine/dropzone]
Fix incorrect pointer events of inner element (#4934)[@mantine/dropzone]
Fix broken exports from react-dropzone-esm
packageFull Changelog: https://github.com/mantinedev/mantine/compare/7.1.1...7.1.2
Published by rtivital about 1 year ago
[@mantine/core]
Radio: Fix description and error being misaligned when the component is rendered inside Radio.Group[@mantine/core]
HoverCard: Add missing HoverCard.extend
[@mantine/core]
Drawer: Fix incorrect transitions in rtl direction (#4917)[@mantine/core]
TagsInput: Fix incorrect IME keyboard input handling (#4947)[@mantine/core]
Container: Fix nested Container components inheriting some properties from parent Container component (#4859)[@mantine/core]
Menu: Fix incorrect Menu.Item rtl styles (#4936)[@mantine/core]
Spoiler: remove margin-bottom when "Show more" is hidden (#4928)[@mantine/dropzone]
Migrate to react-dropzone-esm
package to support frameworks that work only with esm (#4920)[@mantine/core]
Button: Fix incorrect border-radius of loading overlay (#4939)[@mantine/core]
Portal: Fix error when value of className
prop contained whitespace (#4935)[@mantine/core]
MultiSelect: Fix incorrect input sizes values (#4925)[@mantine/core]
Affix: Fix position
prop set as attribute on the root element (#4932)[@mantine/core]
Update react-textarea-autosize
dependency to the latest version to fix issues with edge runtime (#4923)[@mantine/core]
Select: Fix search value not changing when component value is controlled (#4915)[@mantine/core]
Fix incorrect ActionIcon.Group, Button.Group and Rating components RTL styles (#4907)[@mantine/core]
TagsInput: Fix onOptionSubmit
not being called when tag is submitted with Enter
key (#4892)[@mantine/core]
NumberInput: Fix value reset to zero when leading non-zero number is deleted (#4916)Full Changelog: https://github.com/mantinedev/mantine/compare/7.1.0...7.1.1
Published by rtivital about 1 year ago
Starting from 7.1.0 it is possible to import all @mantine/*
packages styles with rules
defined in mantine
CSS layer.
CSS rules within a layer are grouped together and applied before rules without a layer. This means that
even if you do not have control over styles import order, you can still override Mantine styles with
regular styles.
// If your styles are not wrapped in @layer directive,
// they will be applied after Mantine styles.
// Import order does not affect styles in this case
import classes from './Demo.module.css';
import '@mantine/core/styles.layer.css';
You can import styles within a layer by importing @mantine/*/styles.layer.css
files.
Note that these files are a full replacement for @mantine/*/styles.css
files –
you should not import both of them.
import '@mantine/core/styles.layer.css';
import '@mantine/dates/styles.layer.css';
// ... other styles
CSS layers are also useful if you want to combine Mantine components with other libraries which also
provide styles. You can use @layer
directive to control the order of styles:
@layer base, mantine, components;
In this example, Mantine styles will take precedence over other library base
styles, but other library
components
styles will take precedence over Mantine component styles.
As of September 2023, CSS layers are supported in all modern browsers and have 90% browser support.
All polymorphic components now support renderRoot
prop, which
is an alternative to component
prop. renderRoot
prop allows changing the root element
to any other component or HTML tag with a callback function. It can be used in cases when
component
prop is not flexible enough:
className
className
to be a function.renderRoot
example with react-router-dom NavLink:
import cx from 'clsx';
import { Button } from '@mantine/core';
import { NavLink } from 'react-router-dom';
function Demo() {
return (
<Button
renderRoot={({ className, ...others }) => (
<NavLink
className={({ isActive }) => cx(className, { 'active-class': isActive })}
{...others}
/>
)}
>
React router NavLink
</Button>
);
}
renderRoot
example with typed Next.js Link:
import Link from 'next/link';
import { Button } from '@mantine/core';
function Demo() {
return (
<Button renderRoot={(props) => <Link href="/hello" {...props} />}>
Typed Next link button
</Button>
);
}
All @mantine/*
packages now have improved ESM support:
esm
folder now have .mjs
extension@mantine/*
packages with type: module
in package.json
without any additional configurationIt is now possible to define CSS variables in style
prop in all Mantine components –
style prop is no longer restricted by React.CSSProperties
type:
import { Box } from '@mantine/core';
function Demo() {
return <Box style={{ '--radius': '0.5rem', borderRadius: 'var(--radius)' }} />;
}
@mantine/form now supports form.setInitialValues
method
which allows updating initial values after the form was initialized. This method is useful when you
want to update values that are used in form.reset
and to compare values for dirty fields state:
import { useEffect } from 'react';
import { useForm } from '@mantine/form';
function Demo() {
const form = useForm({
initialValues: {
name: '',
email: '',
},
});
useEffect(() => {
fetch('/api/user')
.then((res) => res.json())
.then((data) => {
// Update initial values after form was initialized
// These values will be used in form.reset
// and to compare values to get dirty state
form.setInitialValues(data);
form.setValues(data);
});
}, []);
}