7.14.0
mantinedev/mantine7.14.0Nov 12, 2024by rtivital
AI Summary
A major feature release introducing new chart types, modal stacks, and angle slider components.
Key Highlights
- Introduce AngleSlider component for circular sliders
- Introduce RadialBarChart component
- Introduce FunnelChart component
- Introduce Modal.Stack and Drawer.Stack components with useModalsStack hook
- Add Slider restrictToMarks prop
New Features
- AngleSlider component
- RadialBarChart component
- FunnelChart component
- Modal.Stack and Drawer.Stack components
- useModalsStack hook
- Slider restrictToMarks prop
Full Release Notes
[View changelog with demos on mantine.dev website](https://mantine.dev/changelog/7-14-0)
## AngleSlider component
New [AngleSlider](https://mantine.dev/core/angle-slider/) component:
```tsx
import { AngleSlider, Group } from '@mantine/core';
function Demo() {
return (
<Group p="lg" gap={50}>
<AngleSlider
aria-label="Angle slider"
formatLabel={(value) => `${value}°`}
size={100}
restrictToMarks
marks={[
{ value: 0 },
{ value: 45 },
{ value: 90 },
{ value: 135 },
{ value: 180 },
{ value: 225 },
{ value: 270 },
{ value: 315 },
]}
/>
<AngleSlider
aria-label="Angle slider"
formatLabel={(value) => `${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°' },
]}
/>
</Group>
);
}
```
## RadialBarChart component
New [RadialBarChart](https://mantine.dev/charts/radial-bar-chart/) component:
```tsx
import { RadialBarChart } from '@mantine/charts';
const data = [
{ name: '18-24', value: 31.47, color: 'blue.7' },
{ name: '25-29', value: 26.69, color: 'orange.6' },
{ name: '30-34', value: 15.69, color: 'yellow.7' },
{ name: '35-39', value: 8.22, color: 'cyan.6' },
{ name: '40-49', value: 8.63, color: 'green' },
{ name: '50+', value: 2.63, color: 'pink' },
{ name: 'unknown', value: 6.67, color: 'gray' },
];
function Demo() {
return <RadialBarChart data={data} dataKey="value" h={280} withLabels />;
}
```
## FunnelChart component
New [FunnelChart](https://mantine.dev/charts/funnel-chart/) component:
```tsx
import { FunnelChart } from '@mantine/charts';
const data = [
{ name: 'USA', value: 400, color: 'indigo.6' },
{ name: 'India', value: 300, color: 'yellow.6' },
{ name: 'Japan', value: 100, color: 'teal.6' },
{ name: 'Other', value: 200, color: 'gray.6' },
];
function Demo() {
return <FunnelChart data={data} />;
}
```
## Modal.Stack and Drawer.Stack components
New [Modal.Stack](https://mantine.dev/core/modal/) and [Drawer.Stack](https://mantine.dev/core/drawer) components simplify usage of multiple modals/drawers at the same time.
Use `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 `useModalsStack` hook.
Differences from using multiple `Modal` components:
- `Modal.Stack` manages z-index values – modals that are opened later will always have higher z-index value disregarding 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 (
<>
<Modal.Stack>
<Modal {...stack.register('delete-page')} title="Delete this page?">
Are you sure you want to delete this page? This action cannot be undone.
<Group mt="lg" justify="flex-end">
<Button onClick={stack.closeAll} variant="default">
Cancel
</Button>
<Button onClick={() => stack.open('confirm-action')} color="red">
Delete
</Button>
</Group>
</Modal>
<Modal {...stack.register('confirm-action')} title="Confirm action">
Are you sure you want to perform this action? This action cannot be undone. If you are
sure, press confirm button below.
<Group mt="lg" justify="flex-end">
<Button onClick={stack.closeAll} variant="default">
Cancel
</Button>
<Button onClick={() => stack.open('really-confirm-action')} color="red">
Confirm
</Button>
</Group>
</Modal>
<Modal {...stack.register('really-confirm-action')} title="Really confirm action">
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?
<Group mt="lg" justify="flex-end">
<Button onClick={stack.closeAll} variant="default">
Cancel
</Button>
<Button onClick={stack.closeAll} color="red">
Confirm
</Button>
</Group>
</Modal>
</Modal.Stack>
<Button onClick={() => stack.open('delete-page')}>Open modal</Button>
</>
);
}
```
## useModalsStack/useDrawersStack hooks
`useModalsStack` hook provides an easy way to control multiple modals at the same time.
It accepts an array of unique modals ids and returns an object with the following properties:
```tsx
interface ModalStackReturnType<T extends string> {
// Current opened state of each modal
state: Record<T, boolean>;
// 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 `Modal` component:
```tsx
import { Modal, useModalsStack } from '@mantine/core';
function Demo() {
const stack = useModalsStack(['first', 'second']);
return (
<>
<Modal {...stack.register('first')}>First</Modal>
<Modal {...stack.register('second')}>Second</Modal>
<Button onClick={() => stack.open('first')}>Open first</Button>
</>
);
}
```
## Restrict Slider selection to marks
[Slider](https://mantine.dev/core/slider) component now supports `restrictToMarks` prop that restricts slider value to marks only.
Note that in this case `step` prop is ignored:
```tsx
import { Slider } from '@mantine/core';
function Demo() {
return (
<Slider
restrictToMarks
defaultValue={25}
marks={Array.from({ length: 5 }).map((_, index) => ({ value: index * 25 }))}
/>
);
}
```
## BarChart SVG pattern fill
[BarChart](https://mantine.dev/charts/bar-chart) now can be used with SVG pattern fill:
```tsx
import { BarChart } from '@mantine/charts';
import { data } from './data';
function Demo() {
return (
<BarChart
h={300}
data={mixedStackData}
dataKey="month"
series={[
{ name: 'Smartphones', color: 'url(#crosshatch)', stackId: 'a' },
{ name: 'Laptops', color: 'blue.6', stackId: 'b' },
{ name: 'Tablets', color: 'url(#diagonalStripes)', stackId: 'b' },
]}
>
<defs>
<pattern
id="diagonalStripes"
patternUnits="userSpaceOnUse"
width={6}
height={8}
patternTransform="rotate(45)"
>
<rect
width="2"
height="8"
transform="translate(0,0)"
fill="color-mix(in lch, var(--mantine-color-teal-6) 70%, rgba(0,0,0,0))"
/>
</pattern>
<pattern id="crosshatch" patternUnits="userSpaceOnUse" width={8} height={8}>
<path
d="M 0 0 L 8 0 L 8 8 L 0 8 Z"
fill="none"
stroke="color-mix(in lch, var(--mantine-color-indigo-6) 70%, rgba(0,0,0,0))"
strokeWidth="1"
/>
<path
d="M 0 0 L 8 8"
stroke="color-mix(in lch, var(--mantine-color-indigo-6) 70%, rgba(0,0,0,0))"
strokeWidth="1"
/>
<path
d="M 8 0 L 0 8"
stroke="color-mix(in lch, var(--mantine-color-indigo-6) 70%, rgba(0,0,0,0))"
strokeWidth="1"
/>
</pattern>
</defs>
</BarChart>
);
}
```
## Help center updates
- New [Can I use nested inline styles with Mantine components?](https://help.mantine.dev/q/nested-inline-styles) question
- New [Can I use PostCSS function in inline styles?](https://help.mantine.dev/q/postcss-fns-inline) question
- New [Why my Carousel slides are in vertical orientation?](https://help.mantine.dev/q/carousel-missing-styles) question
- New [My buttons are transparent and the background is visible only on hover, what is wrong?](https://help.mantine.dev/q/transparent-buttons) question
- New [Can I have different primary color for light and dark color schemes?](https://help.mantine.dev/q/primary-virtual-color) question
- New [How can I change body background color?](https://help.mantine.dev/q/body-background) question
- New [My Popover dropdown closes when I click on the dropdown of nested Popover](https://help.mantine.dev/q/nested-popover-closes) question
## Other changes
- [useTree](https://mantine.dev/core/tree/) hook now accepts `onNodeExpand` and `onNodeCollapse` callbacks
- [useTree](https://mantine.dev/core/tree/) hook now returns additional `checkAllNodes`, `uncheckAllNodes` and `setCheckedState` handlers
- [Tree](https://mantine.dev/core/tree) component now includes `getTreeExpandedState` to generate expanded state based on the tree data
- [use-form](https://mantine.dev/form/use-form) now supports `form.replaceListItem` handler to replace list item at given index