Skip to content

fix(deps): update mantine monorepo to v9 - #567

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/major-mantine-monorepo
Open

fix(deps): update mantine monorepo to v9#567
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/major-mantine-monorepo

Conversation

@renovate

@renovate renovate Bot commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
@mantine/core (source) 8.3.189.5.0 age confidence
@mantine/dates (source) 8.3.189.5.0 age confidence
@mantine/form (source) 8.3.189.5.0 age confidence
@mantine/hooks (source) 8.3.189.5.0 age confidence
@mantine/modals (source) ^8.3.18^9.0.0 age confidence
@mantine/notifications (source) 8.3.189.5.0 age confidence

Release Notes

mantinedev/mantine (@​mantine/core)

v9.5.0: 🤖

Compare Source

View changelog with demos on mantine.dev website

Support Mantine development

You can now sponsor Mantine development with OpenCollective.
All funds are used to improve Mantine and create new features and components.

Migration to oxc

Mantine has migrated its linting and formatting toolchain from ESLint and Prettier
to oxcoxlint is now used
as the linter and oxfmt as the formatter. Both
tools are written in Rust and are significantly faster than their predecessors, which
makes linting and formatting the entire codebase almost instant.

The shared configuration is available as a new
oxc-config-mantine package (a replacement for the previous
eslint-config-mantine). You can use it in your own projects to follow the same
code style and conventions as Mantine.

Native level select in date pickers

DatePicker and all other date picker components (DatePickerInput,
MonthPicker, YearPicker, DateTimePicker, etc.)
now support the withNativeLevelSelect prop. When enabled, it replaces the calendar header level button
with native <select> elements, making it easy to quickly navigate to a specific month and year.

import { DatePicker } from '@&#8203;mantine/dates';

function Demo() {
  return <DatePicker withNativeLevelSelect yearsSelectRange={[2020, 2035]} />;
}
Timeline opposite and alternate content

Timeline Timeline.Item component now supports the opposite prop that allows
rendering content on the opposite side of the timeline. When any item has the opposite prop,
the timeline switches to a centered layout with content on both sides of the line.

import { Timeline, Text } from '@&#8203;mantine/core';
import { GitBranchIcon, GitCommitIcon, GitPullRequestIcon, ChatCircleDotsIcon } from '@&#8203;phosphor-icons/react';

function Demo() {
  return (
    <Timeline active={1} bulletSize={24} lineWidth={2}>
      <Timeline.Item
        bullet={<GitBranchIcon size={12} />}
        title="New branch"
        opposite={
          <Text size="sm" c="dimmed">
            2 hours ago
          </Text>
        }
      >
        <Text c="dimmed" size="sm">You&apos;ve created new branch <Text variant="link" component="span" inherit>fix-notifications</Text> from master</Text>
      </Timeline.Item>

      <Timeline.Item
        bullet={<GitCommitIcon size={12} />}
        title="Commits"
        opposite={
          <Text size="sm" c="dimmed">
            52 minutes ago
          </Text>
        }
      >
        <Text c="dimmed" size="sm">You&apos;ve pushed 23 commits to <Text variant="link" component="span" inherit>fix-notifications branch</Text></Text>
      </Timeline.Item>

      <Timeline.Item
        title="Pull request"
        bullet={<GitPullRequestIcon size={12} />}
        lineVariant="dashed"
        opposite={
          <Text size="sm" c="dimmed">
            34 minutes ago
          </Text>
        }
      >
        <Text c="dimmed" size="sm">You&apos;ve submitted a pull request <Text variant="link" component="span" inherit>Fix incorrect notification message (#&#8203;187)</Text></Text>
      </Timeline.Item>

      <Timeline.Item title="Code review" bullet={<ChatCircleDotsIcon size={12} />}>
        <Text c="dimmed" size="sm"><Text variant="link" component="span" inherit>Robert Gluesticker</Text> left a code review on your pull request</Text>
      </Timeline.Item>
    </Timeline>
  );
}

Set the alternate prop on individual Timeline.Item components to switch
the position of content and opposite:

import { Timeline, Text } from '@&#8203;mantine/core';
import { GitBranchIcon, GitCommitIcon, GitPullRequestIcon, ChatCircleDotsIcon } from '@&#8203;phosphor-icons/react';

function Demo() {
  return (
    <Timeline active={2} bulletSize={24} lineWidth={2}>
      <Timeline.Item
        bullet={<GitBranchIcon size={12} />}
        title="New branch"
        opposite={
          <Text size="sm" c="dimmed">
            2 hours ago
          </Text>
        }
      >
        <Text c="dimmed" size="sm">You&apos;ve created new branch <Text variant="link" component="span" inherit>fix-notifications</Text> from master</Text>
      </Timeline.Item>

      <Timeline.Item
        bullet={<GitCommitIcon size={12} />}
        title="Commits"
        opposite={
          <Text size="sm" c="dimmed">
            52 minutes ago
          </Text>
        }
        alternate
      >
        <Text c="dimmed" size="sm">You&apos;ve pushed 23 commits to <Text variant="link" component="span" inherit>fix-notifications branch</Text></Text>
      </Timeline.Item>

      <Timeline.Item
        title="Pull request"
        bullet={<GitPullRequestIcon size={12} />}
        lineVariant="dashed"
        opposite={
          <Text size="sm" c="dimmed">
            34 minutes ago
          </Text>
        }
      >
        <Text c="dimmed" size="sm">You&apos;ve submitted a pull request <Text variant="link" component="span" inherit>Fix incorrect notification message (#&#8203;187)</Text></Text>
      </Timeline.Item>

      <Timeline.Item
        title="Code review"
        bullet={<ChatCircleDotsIcon size={12} />}
        opposite={
          <Text size="sm" c="dimmed">
            12 minutes ago
          </Text>
        }
        alternate
      >
        <Text c="dimmed" size="sm"><Text variant="link" component="span" inherit>Robert Gluesticker</Text> left a code review on your pull request</Text>
      </Timeline.Item>
    </Timeline>
  );
}
FloatingWindow resize handle

FloatingWindow now supports a ResizeHandle compound component
that allows users to resize the floating window by dragging a handle element.
Set the dimensions prop on FloatingWindow to control resize constraints for both
width (initialWidth, minWidth, maxWidth) and height (initialHeight, minHeight, maxHeight).

The resize handle is fully accessible – it supports keyboard interaction with
Arrow Left/Arrow Right keys for width, Arrow Up/Arrow Down for height (10px steps),
and Home/End keys (jump to min/max size).

import { NotchesIcon } from '@&#8203;phosphor-icons/react';
import { Button, CloseButton, FloatingWindow, Group, Text } from '@&#8203;mantine/core';
import { useDisclosure } from '@&#8203;mantine/hooks';

function Demo() {
  const [visible, handlers] = useDisclosure();

  return (
    <>
      <Button onClick={handlers.toggle} variant="default">
        {visible ? 'Hide' : 'Show'} floating window
      </Button>

      {visible && (
        <FloatingWindow
          withBorder
          constrainOffset={40}
          dimensions={{
            initialWidth: 260,
            maxWidth: 500,
            minWidth: 180,
            initialHeight: 260,
            maxHeight: 400,
            minHeight: 220,
          }}
          dragHandleSelector=".drag-handle"
          excludeDragHandleSelector="button"
          initialPosition={{ top: 300, left: 60 }}
          style={{ overflow: 'hidden' }}
        >
          <Group
            justify="space-between"
            px="md"
            py="sm"
            className="drag-handle"
            style={{ cursor: 'move' }}
          >
            <Text fw={500} fz="sm">
              Resize demo
            </Text>
            <CloseButton onClick={handlers.close} />
          </Group>
          <Text fz="sm" px="md" pb="sm">
            Drag the grip icon in the bottom-right corner to resize.
            Use Arrow keys when the handle is focused:
            Left/Right for width, Up/Down for height.
          </Text>
          <FloatingWindow.ResizeHandle
            aria-label="Resize floating window"
            style={{
              position: 'absolute',
              right: 0,
              bottom: 0,
              width: 20,
              height: 20,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              cursor: 'nwse-resize',
            }}
          >
            <NotchesIcon size={14} style={{ opacity: 0.5 }} />
          </FloatingWindow.ResizeHandle>
        </FloatingWindow>
      )}
    </>
  );
}
Cascader component

New Cascader component allows selecting a value from hierarchical data
by drilling down through cascading columns. Picking an option in one column reveals its
children in a new column to the right, and the value is an ordered path from the root option
to the selected node. It supports changeOnSelect, hover expand trigger, search, a flat list
layout for mobile, and full keyboard navigation.

import { Cascader, useMatches } from '@&#8203;mantine/core';
import { data } from './data';

function Demo() {
  // Switch to a flat list on small screens
  const withColumns = useMatches({ base: false, sm: true });
  return (
    <Cascader
      withColumns={withColumns}
      label="Location"
      placeholder="Pick location"
      data={data}
    />
  );
}
SunburstChart component

New SunburstChart component displays hierarchical data
as concentric rings, similar to a treemap plotted in polar coordinates.

// Demo.tsx
import { SunburstChart } from '@&#8203;mantine/charts';
import { data } from './data';

function Demo() {
  return <SunburstChart data={data} />;
}

// data.ts
export const data = [
  { name: 'Analytics', value: 100, color: 'pink.6' },
  {
    name: 'DevOps',
    color: 'grape.6',
    children: [
      { name: 'Docker', value: 80 },
      { name: 'Kubernetes', value: 50 },
    ],
  },
  {
    name: 'Backend',
    color: 'teal.6',
    children: [
      { name: 'Node', value: 150 },
      {
        name: 'Python',
        children: [
          { name: 'Django', value: 110 },
          { name: 'FastAPI', value: 60 },
        ],
      },
      { name: 'Go', value: 50 },
    ],
  },
  {
    name: 'Frontend',
    color: 'blue.6',
    children: [
      {
        name: 'React',
        children: [
          {
            name: 'Frameworks',
            children: [
              { name: 'Next.js', value: 150 },
              { name: 'Remix', value: 40 },
            ],
          },
          { name: 'CRA', value: 20 },
        ],
      },
      { name: 'Vue', value: 90 },
      { name: 'Svelte', value: 30 },
    ],
  },
];
BulletChart component

New BulletChart component displays a single measure against
a qualitative range, useful for comparing a primary value (such as revenue) against
a target and qualitative thresholds like poor, average, and good.

// Demo.tsx
import { BulletChart } from '@&#8203;mantine/charts';
import { ranges } from './data';

function Demo() {
  return (
    <BulletChart
      value={230000}
      target={150000}
      ranges={ranges}
      valueFormatter={(value) => `${(value / 1000).toFixed(0)}k`}
    />
  );
}

// data.ts
export const ranges = ${JSON.stringify(ranges, null, 2)};
Charts keyboard navigation

All @​mantine/charts components now expose the
accessibilityLayer prop (true by default) that makes charts navigable with the keyboard.
The chart surface is focusable and displays the Mantine focus ring; once focused, the arrow keys
move the active tooltip point-by-point and Enter toggles the tooltip, so users who do not
use a mouse can read the underlying values. The prop is supported by AreaChart, BarChart,
LineChart, CompositeChart, ScatterChart, BubbleChart, PieChart, DonutChart, RadarChart,
RadialBarChart and FunnelChart components.

Charts brush

AreaChart, BarChart, LineChart
and CompositeChart now support the withBrush prop that displays a
brush (range selector) under the chart. Drag the brush handles to zoom into a subset of the data.
Use the brushProps prop to customize the underlying recharts Brush, or render the new
themed ChartBrush component as a child of the chart for full control.

// Demo.tsx
import { AreaChart } from '@&#8203;mantine/charts';
import { data } from './data';

function Demo() {
  return (
    <AreaChart
      h={300}
      data={data}
      dataKey="date"
      withBrush
      series={[
        { name: 'Apples', color: 'indigo.6' },
        { name: 'Oranges', color: 'blue.6' },
      ]}
    />
  );
}

// data.ts
export const data = [
  { date: 'Mar 1', Apples: 2200, Oranges: 1400 },
  { date: 'Mar 2', Apples: 2500, Oranges: 1500 },
  { date: 'Mar 3', Apples: 2800, Oranges: 1700 },
  { date: 'Mar 4', Apples: 3100, Oranges: 1600 },
  { date: 'Mar 5', Apples: 3000, Oranges: 1800 },
  { date: 'Mar 6', Apples: 2700, Oranges: 2000 },
  { date: 'Mar 7', Apples: 2400, Oranges: 2100 },
  { date: 'Mar 8', Apples: 2100, Oranges: 1900 },
  { date: 'Mar 9', Apples: 1900, Oranges: 1700 },
  { date: 'Mar 10', Apples: 2200, Oranges: 1500 },
  { date: 'Mar 11', Apples: 2600, Oranges: 1600 },
  { date: 'Mar 12', Apples: 3000, Oranges: 1800 },
  { date: 'Mar 13', Apples: 3300, Oranges: 2000 },
  { date: 'Mar 14', Apples: 3100, Oranges: 2200 },
  { date: 'Mar 15', Apples: 2800, Oranges: 2100 },
  { date: 'Mar 16', Apples: 2500, Oranges: 1900 },
];
Heatmap month labels position

Heatmap now supports monthLabelsPosition prop that allows
displaying month labels at the bottom of the heatmap instead of the top (default).

// Demo.tsx
import { Heatmap } from '@&#8203;mantine/charts';
import { data } from './data';

function Demo() {
  return (
    <Heatmap
      data={data}
      startDate="2024-02-16"
      endDate="2025-02-16"
      withMonthLabels
      withWeekdayLabels
      monthLabelsPosition="bottom"
    />
  );
}

// data.ts
export const data = ${JSON.stringify(data, null, 2)};
Accordion disable collapse

Accordion now supports the disableCollapse prop. When enabled in single
mode (multiple={false}), the open item cannot be collapsed by clicking it again, so one item
always stays open. Pair it with defaultValue or value to guarantee that a section is open
from the start – useful for settings panels, stepper-style flows and FAQ pages.

// Demo.tsx
import { Accordion } from '@&#8203;mantine/core';
import { data } from './data';

function Demo() {
  const items = data.map((item) => (
    <Accordion.Item key={item.value} value={item.value}>
      <Accordion.Control icon={item.emoji}>{item.value}</Accordion.Control>
      <Accordion.Panel>{item.description}</Accordion.Panel>
    </Accordion.Item>
  ));

  return (
    <Accordion defaultValue="Apples" disableCollapse order={3}>
      {items}
    </Accordion>
  );
}

// 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.',
  },
];
ScrollArea vertical scrollbar position

ScrollArea now supports the verticalScrollbarPosition prop that pins the
vertical scrollbar to a physical side (left or right) regardless of direction. This is useful
for RTL applications where users expect the vertical scrollbar to stay on the right, matching the
behavior of most desktop software. The prop also realigns the offset padding, the corner and the
horizontal scrollbar gap, so it works correctly with offsetScrollbars and scrollbars="xy".

import { ScrollArea } from '@&#8203;mantine/core';

function Demo() {
  return (
    <ScrollArea
      w={300}
      h={200}
      type="always"
      scrollbars="y"
       verticalScrollbarPosition="right" offsetScrollbars={true}
    >
      {/* ... content */}
    </ScrollArea>
  );
}
Schedule intervals larger than one hour

ResourcesDayView and
ResourcesWeekView now support intervalMinutes values
larger than 60. Previously the interval was capped at one hour – you can now set it to any
whole number of hours (for example 120 or 240) to display multi-hour time slots. Values
of 60 or less must still divide evenly into an hour; any value that does not keep the grid on
hour boundaries falls back to 60.

// Demo.tsx
import dayjs from 'dayjs';
import { useState } from 'react';
import { SegmentedControl, Stack } from '@&#8203;mantine/core';
import { ResourcesDayView } from '@&#8203;mantine/schedule';
import { events, resources } from './data';

function Demo() {
  const [date, setDate] = useState(dayjs().format('YYYY-MM-DD'));
  const [intervalMinutes, setIntervalMinutes] = useState('120');

  return (
    <Stack>
      <SegmentedControl
        value={intervalMinutes}
        onChange={setIntervalMinutes}
        data={[
          { label: '1 hour', value: '60' },
          { label: '2 hours', value: '120' },
          { label: '4 hours', value: '240' },
        ]}
      />
      <ResourcesDayView
        date={date}
        onDateChange={setDate}
        resources={resources}
        events={events}
        intervalMinutes={Number(intervalMinutes)}
        startScrollTime="08:00:00"
      />
    </Stack>
  );
}

// data.ts
import dayjs from 'dayjs';
import { ScheduleResourceData } from '@&#8203;mantine/schedule';

const today = dayjs().format('YYYY-MM-DD');

const resources: ScheduleResourceData[] = [
  { id: 'tokyo', label: 'Meeting room: Tokyo' },
  { id: 'paris', label: 'Meeting room: Paris' },
  { id: 'new-york', label: 'Meeting room: New York' },
  { id: 'london', label: 'Meeting room: London' },
];

const events = [
  {
    id: 1,
    title: 'Team Standup',
    start: \`\${today} 09:00:00\`,
    end: \`\${today} 09:30:00\`,
    color: 'blue',
    resourceId: 'tokyo',
  },
  {
    id: 2,
    title: 'Sprint Planning',
    start: \`\${today} 10:00:00\`,
    end: \`\${today} 11:30:00\`,
    color: 'green',
    resourceId: 'tokyo',
  },
  {
    id: 3,
    title: 'Client Call',
    start: \`\${today} 09:30:00\`,
    end: \`\${today} 10:30:00\`,
    color: 'violet',
    resourceId: 'paris',
  },
  {
    id: 4,
    title: 'Design Review',
    start: \`\${today} 13:00:00\`,
    end: \`\${today} 14:00:00\`,
    color: 'orange',
    resourceId: 'paris',
  },
  {
    id: 5,
    title: '1:1 Meeting',
    start: \`\${today} 11:00:00\`,
    end: \`\${today} 11:30:00\`,
    color: 'cyan',
    resourceId: 'new-york',
  },
  {
    id: 6,
    title: 'Workshop',
    start: \`\${today} 14:00:00\`,
    end: \`\${today} 16:00:00\`,
    color: 'pink',
    resourceId: 'new-york',
  },
  {
    id: 7,
    title: 'Architecture Review',
    start: \`\${today} 10:00:00\`,
    end: \`\${today} 11:00:00\`,
    color: 'red',
    resourceId: 'london',
  },
  {
    id: 8,
    title: 'Retrospective',
    start: \`\${today} 15:00:00\`,
    end: \`\${today} 16:00:00\`,
    color: 'grape',
    resourceId: 'london',
  },
];
New example: Table virtualization

New Table example demonstrates how to use Table.ScrollContainer with
@tanstack/react-virtual to efficiently render large datasets with 5,000 rows.

import { useState } from 'react';
import { useVirtualizer } from '@&#8203;tanstack/react-virtual';
import { Table } from '@&#8203;mantine/core';
import { generateData } from './data';

const data = generateData(5000);
const ROW_HEIGHT = 36;

function Demo() {
  const [scrollParent, setScrollParent] = useState<HTMLDivElement | null>(null);

  const virtualizer = useVirtualizer({
    count: data.length,
    getScrollElement: () => scrollParent,
    estimateSize: () => ROW_HEIGHT,
    overscan: 20,
  });

  const virtualItems = virtualizer.getVirtualItems();

  return (
    <Table.ScrollContainer
      minWidth={500}
      maxHeight={400}
      scrollAreaProps={{ viewportRef: setScrollParent }}
    >
      <Table stickyHeader layout="fixed">
        <Table.Thead>
          <Table.Tr>
            <Table.Th w={50}>#</Table.Th>
            <Table.Th>Name</Table.Th>
            <Table.Th>Email</Table.Th>
            <Table.Th>Company</Table.Th>
            <Table.Th>City</Table.Th>
          </Table.Tr>
        </Table.Thead>

        <Table.Tbody>
          {virtualItems.length > 0 && (
            <tr aria-hidden>
              <td
                aria-hidden
                colSpan={5}
                style={{ height: virtualItems[0].start, padding: 0, border: 'none' }}
              />
            </tr>
          )}

          {virtualItems.map((virtualItem) => {
            const row = data[virtualItem.index];
            return (
              <Table.Tr key={virtualItem.index}>
                <Table.Td>{row.id}</Table.Td>
                <Table.Td>{row.name}</Table.Td>
                <Table.Td>{row.email}</Table.Td>
                <Table.Td>{row.company}</Table.Td>
                <Table.Td>{row.city}</Table.Td>
              </Table.Tr>
            );
          })}

          {virtualItems.length > 0 && (
            <tr aria-hidden>
              <td
                aria-hidden
                colSpan={5}
                style={{
                  height:
                    virtualizer.getTotalSize() -
                    virtualItems[virtualItems.length - 1].end,
                  padding: 0,
                  border: 'none',
                }}
              />
            </tr>
          )}
        </Table.Tbody>
      </Table>
    </Table.ScrollContainer>
  );
}

v9.4.2

Compare Source

What's Changed
  • [@mantine/schedule] Fix 1-3 minutes events not aligning correctly in ResourcesWeekView and ResourcesDayView (#​9057)
  • [@mantine/form] Fix async validation with debounce on initial keystroke of empty input (#​9068)
  • [@mantine/core] Add keepMountedMode prop to Modal and Drawer components (#​9056)
  • [@mantine/core] Menubar: Fix menu requiring two clicks to dismiss after switching menus with hover (#​9050)
  • [@mantine/core] AppShell: Fix breakpoint={0} not working correctly (#​9042)
  • [@mantine/core] Tree: Fix keyboard navigation not working on Safari (#​9049)
  • [@mantine/notifications] NotificationContainer: Fix autoClose leak (#​9048)
  • [@mantine/core] Collapse: Add keepMountedMode prop (#​9021)
  • [@mantine/dates] TimePicker: Fix incorrect withSeconds handling when pasting partial values (#​9041)
  • [@mantine/schedule] Add option to customize current time in ResourcesDayView and ResourcesWeekView components
  • [@mantine/core] TreeSelect: Add expand callback to renderNode payload
  • [@mantine/core] Fix incorrect empty children arrays handling in Tree and TreeSelect
  • [@mantine/hooks] Fix unstable scrollIntoView for some bundlers (#​9035)
  • [@mantine/schedule] Add intervalMinutes more than 60 support to ResourcesDayView and ResourcesWeekView
  • [@mantine/schedule] ResourcesWeekView: Fix incorrect handling of events with small duration
  • [@mantine/schedule] ResourcesDayView: Fix events with small durations not being visible
New Contributors

Full Changelog: mantinedev/mantine@9.4.1...9.4.2

v9.4.1

Compare Source

What's Changed
  • [@mantine/form] Fix some functions not working correctly with react compiler (#​9007)
  • [@mantine/charts] Heatmap: Fix values outside the provided domain rendering with no fill (#​8982)
  • [@mantine/core] RollingNumber: Fix rendering -0 for values that round to zero (#​8983)
  • [@mantine/core] Slider: Fix incorrect marks labels position in RTL layouts (#​8996)
  • [@mantine/hooks] Fix use-set and use-map hooks using stale values when used with React compiler (#​9008)
  • [@mantine/form] Add FormProviderProps type export (#​9009)
  • [@mantine/schedule] ResourcesDayView: Fix incorrect multiday events rendering (#​9014)
  • [@mantine/dates] TimePicker: Fix duration values greater than 9999 hours not working (#​9002)
  • [@mantine/core] Menu: Mark non-menuitem dropdown children as presentational (#​9004)
  • [@mantine/core] Collapse: Fix ref and style props not working when transitionDuration: 0 (#​9013)
  • [@mantine/core] Textarea: Fix autosize not working correctly with minRows on initial render
  • [@mantine/schedule] ResourcesWeekView: Add events resizing support
New Contributors

Full Changelog: mantinedev/mantine@9.4.0...9.4.1

v9.4.0: 🥵

Compare Source

View changelog with demos on mantine.dev website

Support Mantine development

You can now sponsor Mantine development with OpenCollective.
All funds are used to improve Mantine and create new features and components.

ComboboxPopover component

New ComboboxPopover component allows adding a combobox dropdown
with selectable options to any button element. Unlike Select and MultiSelect, it does not
render an input – you provide your own target element via ComboboxPopover.Target. Supports
single and multiple selection modes with the same data format as Select.

import { useState } from 'react';
import { Button, ComboboxPopover } from '@&#8203;mantine/core';

function Demo() {
  const [value, setValue] = useState<string | null>(null);

  return (
    <ComboboxPopover
      data={['React', 'Angular', 'Vue', 'Svelte']}
      value={value}
      onChange={setValue}
    >
      <ComboboxPopover.Target>
        <Button variant="default" miw={200}>{value || 'Select framework'}</Button>
      </ComboboxPopover.Target>
    </ComboboxPopover>
  );
}

DataList component

New DataList component displays label-value pairs as a semantic description
list using dl, dt, and dd HTML elements. Supports vertical and horizontal orientations,
dividers between items, and all standard Mantine features like Styles API and size prop.

import { DataList } from '@&#8203;mantine/core';

const data = [
  { label: 'Name', value: 'John Doe' },
  { label: 'Email', value: 'john@example.com' },
  { label: 'Role', value: 'Software Engineer' },
  { label: 'Location', value: 'San Francisco, CA' },
];

function Demo() {
  return (
    <DataList size="md" orientation="vertical" withDivider={false}>
      {data.map((item) => (
        <DataList.Item key={item.label}>
          <DataList.ItemLabel>{item.label}</DataList.ItemLabel>
          <DataList.ItemValue>{item.value}</DataList.ItemValue>
        </DataList.Item>
      ))}
    </DataList>
  );
}

EmptyState component

New EmptyState component displays a placeholder for "no data" situations:
empty search results, empty tables and lists, first-run states or error illustrations with an
optional call to action. It can be used with icon, title and description shorthand props
or with EmptyState.Indicator, EmptyState.Title, EmptyState.Description and
EmptyState.Actions compound components for full control.

import { Button, EmptyState } from '@&#8203;mantine/core';
import { MagnifyingGlassIcon } from '@&#8203;phosphor-icons/react';

function Demo() {
  return (
    <EmptyState>
      <EmptyState.Indicator>
        <MagnifyingGlassIcon />
      </EmptyState.Indicator>
      <EmptyState.Title>No results found</EmptyState.Title>
      <EmptyState.Description>
        We couldn't find anything matching your search. Try adjusting your filters or searching with
        different keywords to see more results.
      </EmptyState.Description>
      <EmptyState.Actions>
        <Button variant="default">Reset filters</Button>
        <Button variant="default">Create new</Button>
      </EmptyState.Actions>
    </EmptyState>
  );
}

Menubar component

New Menubar component adds a desktop-application style menu bar: a horizontal row
of top-level menu triggers (File, Edit, View, …) where each trigger opens a dropdown. Arrow keys
move between the top-level menus, and once one menu is opened, moving to a sibling opens it
immediately. Menubar is built on top of Menu and follows the WAI-ARIA menubar pattern.

import { Menu, Menubar, Text } from '@&#8203;mantine/core';

function Demo() {
  return (
    <Menubar>
      <Menubar.Menu width={220}>
        <Menubar.Target>File</Menubar.Target>
        <Menubar.Dropdown>
          <Menu.Item rightSection={<Text size="xs" c="dimmed">⌘N</Text>}>New file</Menu.Item>
          <Menu.Item rightSection={<Text size="xs" c="dimmed">⌘⇧N</Text>}>New window</Menu.Item>
          <Menu.Sub>
            <Menu.Sub.Target>
              <Menu.Sub.Item>Open recent</Menu.Sub.Item>
            </Menu.Sub.Target>
            <Menu.Sub.Dropdown>
              <Menu.Item>project-alpha</Menu.Item>
              <Menu.Item>project-beta</Menu.Item>
              <Menu.Item>project-gamma</Menu.Item>
            </Menu.Sub.Dropdown>
          </Menu.Sub>
          <Menu.Divider />
          <Menu.Item rightSection={<Text size="xs" c="dimmed">⌘S</Text>}>Save</Menu.Item>
          <Menu.Item>Save as…</Menu.Item>
        </Menubar.Dropdown>
      </Menubar.Menu>

      <Menubar.Menu width={220}>
        <Menubar.Target>Edit</Menubar.Target>
        <Menubar.Dropdown>
          <Menu.Item rightSection={<Text size="xs" c="dimmed">⌘Z</Text>}>Undo</Menu.Item>
          <Menu.Item rightSection={<Text size="xs" c="dimmed">⌘⇧Z</Text>}>Redo</Menu.Item>
          <Menu.Divider />
          <Menu.Item>Cut</Menu.Item>
          <Menu.Item>Copy</Menu.Item>
          <Menu.Item>Paste</Menu.Item>
        </Menubar.Dropdown>
      </Menubar.Menu>

      <Menubar.Menu width={220}>
        <Menubar.Target>Help</Menubar.Target>
        <Menubar.Dropdown>
          <Menu.Item>Documentation</Menu.Item>
          <Menu.Item>Keyboard shortcuts</Menu.Item>
          <Menu.Item>About</Menu.Item>
        </Menubar.Dropdown>
      </Menubar.Menu>
    </Menubar>
  );
}

ResourcesDayView component

New ResourcesDayView component displays resources as rows and
time slots as columns. Each row represents a resource (conference room, person, equipment) and
shows events assigned to that resource. Supports drag and drop across resources, business hours
highlighting, and slot drag select.

// Demo.tsx
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesDayView } from '@&#8203;mantine/schedule';
import { events, resources } from './data';

function Demo() {
  const [date, setDate] = useState(dayjs().format('YYYY-MM-DD'));

  return (
    <ResourcesDayView
      date={date}
      onDateChange={setDate}
      resources={resources}
      events={events}
      startTime="08:00:00"
      endTime="18:00:00"
    />
  );
}

// data.ts
import dayjs from 'dayjs';
import { ScheduleResourceData } from '@&#8203;mantine/schedule';

const today = dayjs().format('YYYY-MM-DD');

const resources: ScheduleResourceData[] = [
  { id: 'tokyo', label: 'Meeting room: Tokyo' },
  { id: 'paris', label: 'Meeting room: Paris' },
  { id: 'new-york', label: 'Meeting room: New York' },
  { id: 'london', label: 'Meeting room: London' },
];

const events = [
  {
    id: 1,
    title: 'Team Standup',
    start: \`\${today} 09:00:00\`,
    end: \`\${today} 09:30:00\`,
    color: 'blue',
    resourceId: 'tokyo',
  },
  {
    id: 2,
    title: 'Sprint Planning',
    start: \`\${today} 10:00:00\`,
    end: \`\${today} 11:30:00\`,
    color: 'green',
    resourceId: 'tokyo',
  },
  {
    id: 3,
    title: 'Client Call',
    start: \`\${today} 09:30:00\`,
    end: \`\${today} 10:30:00\`,
    color: 'violet',
    resourceId: 'paris',
  },
  {
    id: 4,
    title: 'Design Review',
    start: \`\${today} 13:00:00\`,
    end: \`\${today} 14:00:00\`,
    color: 'orange',
    resourceId: 'paris',
  },
  {
    id: 5,
    title: '1:1 Meeting',
    start: \`\${today} 11:00:00\`,
    end: \`\${today} 11:30:00\`,
    color: 'cyan',
    resourceId: 'new-york',
  },
  {
    id: 6,
    title: 'Workshop',
    start: \`\${today} 14:00:00\`,
    end: \`\${today} 16:00:00\`,
    color: 'pink',
    resourceId: 'new-york',
  },
  {
    id: 7,
    title: 'Architecture Review',
    start: \`\${today} 10:00:00\`,
    end: \`\${today} 11:00:00\`,
    color: 'red',
    resourceId: 'london',
  },
  {
    id: 8,
    title: 'Retrospective',
    start: \`\${today} 15:00:00\`,
    end: \`\${today} 16:00:00\`,
    color: 'grape',
    resourceId: 'london',
  },
];

ResourcesWeekView component

New ResourcesWeekView component displays resources as rows
and a full week of time slots as columns with a two-level header showing day names and time
labels. Supports drag and drop, slot selection, business hours, and current time indicator.

// Demo.tsx
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesWeekView } from '@&#8203;mantine/schedule';
import { events, resources } from './data';

function Demo() {
  const today = dayjs().format('YYYY-MM-DD');
  const [date, setDate] = useState(today);

  return (
    <ResourcesWeekView
      date={date}
      onDateChange={setDate}
      resources={resources}
      events={events}
      startTime="08:00:00"
      endTime="18:00:00"
      startScrollDateTime={`${today} 08:00:00`}
    />
  );
}

// data.ts
import dayjs from 'dayjs';
import { ScheduleResourceData } from '@&#8203;mantine/schedule';

const today = dayjs().format('YYYY-MM-DD');
const tomorrow = dayjs().add(1, 'day').format('YYYY-MM-DD');
const dayAfter = dayjs().add(2, 'day').format('YYYY-MM-DD');
const dayAfter2 = dayjs().add(3, 'day').format('YYYY-MM-DD');

const resources: ScheduleResourceData[] = [
  { id: 'tokyo', label: 'Meeting room: Tokyo' },
  { id: 'paris', label: 'Meeting room: Paris' },
  { id: 'new-york', label: 'Meeting room: New York' },
  { id: 'london', label: 'Meeting room: London' },
];

const events = [
  {
    id: 1,
    title: 'Team Standup',
    start: \`\${today} 09:00:00\`,
    end: \`\${today} 09:30:00\`,
    color: 'blue',
    resourceId: 'tokyo',
  },
  {
    id: 2,
    title: 'Sprint Planning',
    start: \`\${today} 10:00:00\`,
    end: \`\${today} 11:30:00\`,
    color: 'green',
    resourceId: 'tokyo',
  },
  {
    id: 3,
    title: 'Client Call',
    start: \`\${tomorrow} 09:30:00\`,
    end: \`\${tomorrow} 10:30:00\`,
    color: 'violet',
    resourceId: 'paris',
  },
  {
    id: 4,
    title: 'Design Review',
    start: \`\${today} 13:00:00\`,
    end: \`\${today} 14:00:00\`,
    color: 'orange',
    resourceId: 'paris',
  },
  {
    id: 5,
    title: '1:1 Meeting',
    start: \`\${tomorrow} 11:00:00\`,
    end: \`\${tomorrow} 11:30:00\`,
    color: 'cyan',
    resourceId: 'new-york',
  },
  {
    id: 6,
    title: 'Workshop',
    start: \`\${dayAfter} 14:00:00\`,
    end: \`\${dayAfter} 16:00:00\`,
    color: 'pink',
    resourceId: 'new-york',
  },
  {
    id: 7,
    title: 'Architecture Review',
    start: \`\${tomorrow} 10:00:00\`,
    end: \`\${tomorrow} 11:00:00\`,
    color: 'red',
    resourceId: 'london',
  },
  {
    id: 8,
    title: 'Retrospective',
    start: \`\${today} 15:00:00\`,
    end: \`\${today} 16:00:00\`,
    color: 'grape',
    resourceId: 'london',
  },
  {
    id: 9,
    title: 'Product Demo',
    start: \`\${dayAfter} 09:00:00\`,
    end: \`\${dayAfter} 10:00:00\`,
    color: 'teal',
    resourceId: 'tokyo',
  },
  {
    id: 10,
    title: 'Budget Review',
    start: \`\${dayAfter2} 11:00:00\`,
    end: \`\${dayAfter2} 12:30:00\`,
    color: 'indigo',
    resourceId: 'paris',
  },
];

ResourcesMonthView component

New ResourcesMonthView component displays resources as rows
and days of the month as columns. Events are shown as colored indicators within each
resource-day cell for easy visualization of resource utilization across the month.

// Demo.tsx
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesMonthView } from '@&#8203;mantine/schedule';
import { events, resources } from './data';

function Demo() {
  const [date, setDate] = useState(dayjs().format('YYYY-MM-DD'));

  return (
    <ResourcesMonthView
      date={date}
      onDateChange={setDate}
      resources={resources}
      events={events}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

// data.ts
import dayjs from 'dayjs';
import { ScheduleResourceData } from '@&#8203;mantine/schedule';

const today = dayjs().format('YYYY-MM-DD');
const tomorrow = dayjs().add(1, 'day').format('YYYY-MM-DD');
const nextWeek = dayjs().add(5, 'day').format('YYYY-MM-DD');

const resources: ScheduleResourceData[] = [
  { id: 'tokyo', label: 'Meeting room: Tokyo' },
  { id: 'paris', label: 'Meeting room: Paris' },
  { id: 'new-york', label: 'Meeting room: New York' },
];

const events = [
  {
    id: 1,
    title: 'Team Standup',
    start: \`\${today} 09:00:00\`,
    end: \`\${today} 09:30:00\`,
    color: 'blue',
    resourceId: 'tokyo',
  },
  {
    id: 2,
    title: 'Sprint Planning',
    start: \`\${today} 10:00:00\`,
    end: \`\${today} 11:30:00\`,
    color: 'green',
    resourceId: 'paris',
  },
  {
    id: 3,
    title: 'Design Review',
    start: \`\${tomorrow} 13:00:00\`,
    end: \`\${tomorrow} 14:00:00\`,
    color: 'orange',
    resourceId: 'tokyo',
  },
  {
    id: 4,
    title: 'Client Call',
    start: \`\${tomorrow} 09:30:00\`,
    end: \`\${tomorrow} 10:30:00\`,
    color: 'violet',
    resourceId: 'new-york',
  },
  {
    id: 5,
    title: 'Workshop',
    start: \`\${nextWeek} 14:00:00\`,
    end: \`\${nextWeek} 16:00:00\`,
    color: 'pink',
    resourceId: 'paris',
  },
];

ResourcesSchedule component

New ResourcesSchedule wrapper component combines ResourcesDayView,
ResourcesWeekView and ResourcesMonthView into a single component with view switching, similar
to how Schedule combines day, week, month and year views.

// Demo.tsx
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesSchedule } from '@&#8203;mantine/schedule';
import { events, resources } from './data';

function Demo() {
  const today = dayjs().format('YYYY-MM-DD');
  const [date, setDate] = useState(today);

  return (
    <ResourcesSchedule
      date={date}
      onDateChange={setDate}
      resources={resources}
      events={events}
      dayViewProps={{ startTime: '08:00:00', endTime: '18:00:00', startScrollTime: '08:00:00' }}
      weekViewProps={{ startTime: '08:00:00', endTime: '18:00:00', startScrollDateTime: `${today} 08:00:00` }}
      monthViewProps={{ startScrollDate: today }}
    />
  );
}

// data.ts
import dayjs from 'dayjs';
import { ScheduleResourceData } from '@&#8203;mantine/schedule';

const today = dayjs().format('YYYY-MM-DD');
const tomorrow = dayjs().add(1, 'day').format('YYYY-MM-DD');
const nextWeek = dayjs().add(5, 'day').format('YYYY-MM-DD');

const resources: ScheduleResourceData[] = [
  { id: 'tokyo', label: 'Meeting room: Tokyo' },
  { id: 'paris', label: 'Meeting room: Paris' },
  { id: 'new-york', label: 'Meeting room: New York' },
  { id: 'london', label: 'Meeting room: London' },
];

const events = [
  { id: 1, title: 'Team Standup', start: \`\${today} 09:00:00\`, end: \`\${today} 09:30:00\`, color: 'blue', resourceId: 'tokyo' },
  { id: 2, title: 'Sprint Planning', start: \`\${today} 10:00:00\`, end: \`\${today} 11:30:00\`, color: 'green', resourceId: 'tokyo' },
  { id: 3, title: 'Client Call', start: \`\${today} 09:30:00\`, end: \`\${today} 10:30:00\`, color: 'violet', resourceId: 'paris' },
  { id: 4, title: 'Design Review', start: \`\${tomorrow} 13:00:00\`, end: \`\${tomorrow} 14:00:00\`, color: 'orange', resourceId: 'paris' },
  { id: 5, title: '1:1 Meeting', start: \`\${today} 11:00:00\`, end: \`\${today} 11:30:00\`, color: 'cyan', resourceId: 'new-york' },
  { id: 6, title: 'Workshop', start: \`\${nextWeek} 14:00:00\`, end: \`\${nextWeek} 16:00:00\`, color: 'pink', resourceId: 'new-york' },
  { id: 7, title: 'Architecture Review', start: \`\${today} 10:00:00\`, end: \`\${today} 11:00:00\`, color: 'red', resourceId: 'london' },
  { id: 8, title: 'Retrospective', start: \`\${tomorrow} 15:00:00\`, end: \`\${tomorrow} 16:00:00\`, color: 'grape', resourceId: 'london' },
];

AgendaView component

New AgendaView component renders a vertical list of events for a specified
time period. Events are grouped by date in chronological order.

import dayjs from 'dayjs';
import { AgendaView } from '@&#8203;mantine/schedule';

const today = dayjs().format('YYYY-MM-DD');
const startOfMonth = dayjs().startOf('month').format('YYYY-MM-DD');

const events = [
  {
    id: 'team-meeting',
    title: 'Team Meeting',
    start: `${startOfMonth} 09:00:00`,
    end: `${startOfMonth} 10:30:00`,
    color: 'blue',
  },
  {
    id: 'client-call',
    title: 'Client Call',
    start: `${today} 14:00:00`,
    end: `${today} 15:00:00`,
    color: 'green',
  },
  {
    id: 'daily-sync-series',
    title: 'Daily sync',
    start: `${startOfMonth} 09:30:00`,
    end: `${startOfMonth} 10:00:00`,
    color: 'grape',
    recurrence: {
      rrule: 'FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR;COUNT=30',
    },
  },
  {
    id: 'weekly-review-series',
    title: 'Weekly review',
    start: `${startOfMonth} 16:00:00`,
    end: `${startOfMonth} 17:00:00`,
    color: 'cyan',
    recurrence: {
      rrule: 'FREQ=WEEKLY;COUNT=8',
    },
  },
];

function Demo() {
  return (
    <AgendaView
      rangeStart={dayjs().startOf('month').format('YYYY-MM-DD')}
      rangeEnd={dayjs().endOf('month').format('YYYY-MM-DD')}
      events={events}
    />
  );
}

withAgenda prop for DayView, WeekView, MonthView and Schedule

DayView, WeekView, MonthView and Schedule components now support withAgenda prop.
When enabled, an "Agenda" button is displayed in the header. Clicking it opens an AgendaView
for the currently visible date range.

import dayjs from 'dayjs';
import { useState } from 'react';
import { MonthView } from '@&#8203;mantine/schedule';

const today = dayjs().format('YYYY-MM-DD');
const startOfMonth = dayjs().startOf('month').format('YYYY-MM-DD');

const events = [
  {
    id: 'team-meeting',
    title: 'Team Meeting',
    start: `${startOfMonth} 09:00:00`,
    end: `${startOfMonth} 10:30:00`,
    color: 'blue',
  },
  {
    id: 'client-call',
    title: 'Client Call',
    start: `${today} 14:00:00`,
    end: `${today} 15:00:00`,
    color: 'green',
  },
  {
    id: 'daily-sync-series',
    title: 'Daily sync',
    start: `${startOfMonth} 09:30:00`,
    end: `${startOfMonth} 10:00:00`,
    color: 'grape',
    recurrence: {
      rrule: 'FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR;COUNT=30',
    },
  },
  {
    id: 'weekly-review-series',
    title: 'Weekly review',
    start: `${startOfMonth} 16:00:00`,
    end: `${startOfMonth} 17:00:00`,
    color: 'orange',
    recurrence: {
      rrule: 'FREQ=WEEKLY;COUNT=8',
    },
  },
];

function Demo() {
  const [date, setDate] = useState(today);

  return (
    <MonthView
      date={date}
      onDateChange={setDate}
      events={events}
      withAgenda
    />
  );
}

MonthView hide weekend days

MonthView now supports withWeekendDays prop. Set it to false
to hide weekend days: the grid shrinks to the remaining columns and events that span hidden
days are clipped to the visible days. The days that are considered weekend are controlled by
the weekendDays prop (or DatesProvider, [0, 6] by default).

// Demo.tsx
import { MonthView } from '@&#8203;mantine/schedule';
import { events } from './data';

function Demo() {
  return <MonthView date={new Date()} events={events} withWeekendDays={false} />;
}

// data.ts
import dayjs from 'dayjs';

const today = dayjs().format('YYYY-MM-DD');
const startOfMonth = dayjs().startOf('month').format('YYYY-MM-DD');
const midMonth = dayjs().date(15).format('YYYY-MM-DD');
const endOfMonth = dayjs().endOf('month').format('YYYY-MM-DD');

export const events = [
  {
    id: 1,
    title: 'Team Meeting',
    start: \`\${startOfMonth} 09:00:00\`,
    end: \`\${startOfMonth} 10:30:00\`,
    color: 'blue',
  },
  {
    id: 2,
    title: 'Project Deadline',
    start: \`\${midMonth} 00:00:00\`,
    end: dayjs(midMonth).add(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss'),
    color: 'red',
  },
  {
    id: 3,
    title: 'Client Call',
    start: \`\${today} 14:00:00\`,
    end: \`\${today} 15:00:00\`,
    color: 'green',
  },
  {
    id: 4,
    title: 'Monthly Review',
    start: \`\${endOfMonth} 00:00:00\`,
    end: dayjs(endOfMonth).add(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss'),
    color: 'violet',
  },
  {
    id: 5,
    title: 'Workshop',
    start: dayjs().add(3, 'day').format('YYYY-MM-DD 10:00:00'),
    end: dayjs().add(3, 'day').format('YYYY-MM-DD 12:00:00'),
    color: 'orange',
  },
  {
    id: 6,
    title: 'Conference',
    start: dayjs().add(5, 'day').format('YYYY-MM-DD 00:00:00'),
    end: dayjs().add(6, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss'),
    color: 'cyan',
  },
];

DayView and WeekView sub-hour grid lines

DayView and WeekView now support withSubHourGridLines
prop. When intervalMinutes is smaller than 60, set withSubHourGridLines={false} to display only
one grid line per hour while keeping the smaller interval for creating and resizing events. This is
useful to achieve a Google Calendar like layout: events snap to 15 or 30 minutes increments, but the
grid stays clean with hourly lines.

import { useState } from 'react';
import dayjs from 'dayjs';
import { WeekView, ScheduleEventData } from '@&#8203;mantine/schedule';

const today = dayjs().format('YYYY-MM-DD');
const tomorrow = dayjs().add(1, 'day').format('YYYY-MM-DD');

const initialEvents: ScheduleEventData[] = [
  {
    id: 1,
    title: 'Morning Standup',
    start: `${today} 09:00:00`,
    end: `${today} 09:30:00`,
    color: 'blue',
  },
  {
    id: 2,
    title: 'Team Meeting',
    start: `${tomorrow} 11:15:00`,
    end: `${tomorrow} 12:00:00`,
    color: 'green',
  },
  {
    id: 3,
    title: 'Code Review',
    start: `${today} 14:00:00`,
    end: `${today} 14:45:00`,
    color: 'violet',
  },
];

function Demo() {
  const [events, setEvents] = useState(initialEvents);

  const handleEventResize = ({ eventId, newStart, newEnd }: { eventId: string | number; newStart: string; newEnd: string }) => {
    setEvents((prev) =>
      prev.map((event) =>
        event.id === eventId ? { ...event, start: newStart, end: newEnd } : event
      )
    );
  };

  // Events snap to 15 minutes increments, but only one grid line per hour is displayed
  return (
    <WeekView
      date={new Date()}
      events={events}
      startTime="08:00:00"
      endTime="18:00:00"
      intervalMinutes={15}
      withSubHourGridLines
      withEventResize
      onEventResize={handleEventResize}
    />
  );
}

Input success state

All inputs based on Input and Input.Wrapper now support a success prop. When set, it changes the
input border color to green (--mantine-color-success). You can also pass a React node to display
a success message below the input. If both error and success props are set, error takes precedence.

New --mantine-color-success CSS variable has been added (resolves to teal-6 in light mode and teal-8 in dark mode).

import { TextInput } from '@&#8203;mantine/core';

function Demo() {
  return (
    <>
      <TextInput placeholder="Success as boolean" label="Success as boolean" success />
      <TextInput
        mt="md"
        placeholder="Success as react node"
        label="Success as react node"
        success="Username is available"
      />
    </>
  );
}

Splitter CSS units

Splitter.Pane defaultSize, min and max props now accept CSS units in
addition to plain numbers. A plain number or % string is a flexible size that shares the
leftover space, while a px or rem string is a fixed size that keeps its pixel size when the
container is resized. This makes it possible to mix a fixed-width sidebar with a fluid content pane:

import { Splitter } from '@&#8203;mantine/core';

function Demo() {
  return (
    <Splitter h={200}>
      <Splitter.Pane defaultSize="240px" min="160px" max="50%" bg="blue">
        Fixed 240px sidebar
      </Splitter.Pane>
      <Splitter.Pane defaultSize={100} bg="teal">
        Flexible content
      </Splitter.Pane>
    </Splitter>
  );
}

Notifications priority

Notifications now support a priority property. When the number of active notifications exceeds
the limit, notifications with a higher priority take the visible slots and lower priority ones
are pushed into the queue. Notifications with equal priority keep insertion order (FIFO), so the
default behavior is unchanged (priority defaults to 0).

import { Button, Group } from '@&#8203;mantine/core';
import { createNotificationsStore, notifications, Notifications } from '@&#8203;mantine/notifications';

// Dedicated store with limit={1} so the priority behavior is easy to see
const store = createNotificationsStore();

function Demo() {
  return (
    <>
      <Notifications store={store} limit={1} position="top-center" />

      <Group justify="center">
        <Button
          color="gray"
          onClick={() =>
            notifications.show(
              {
                title: 'Low priority',
                message: 'I am pushed to the queue when an urgent notification arrives',
                autoClose: false,
                priority: 0,
              },
              store
            )
          }
        >
          Show low priority
        </Button>

        <Button
          color=

> ✂ **Note**
> 
> PR body was truncated to here.


</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/openscript-ch/quassel).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from 1dc93ac to 66c7692 Compare April 6, 2026 09:58
@changeset-bot

changeset-bot Bot commented Apr 6, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8e54d42

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from 66c7692 to 27f4979 Compare April 13, 2026 09:48
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from c8f58a2 to 6f412fc Compare April 27, 2026 18:12
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from 6f412fc to 2376858 Compare May 11, 2026 17:00
@renovate renovate Bot changed the title fix(deps): update mantine monorepo to v9 (major) fix(deps): update mantine monorepo to v9 May 12, 2026
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from 2376858 to 973154e Compare May 14, 2026 14:03
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch 3 times, most recently from 0f2f705 to c42fb4e Compare June 2, 2026 12:02
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from c42fb4e to d23c354 Compare June 8, 2026 21:40
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from 38cd529 to 0ff68a2 Compare June 22, 2026 17:15
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from 0ff68a2 to 9956944 Compare June 28, 2026 13:03
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from 9956944 to b7dfad3 Compare July 12, 2026 16:48
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from b7dfad3 to 4ac8328 Compare July 21, 2026 09:53
@renovate
renovate Bot force-pushed the renovate/major-mantine-monorepo branch from 4ac8328 to 8e54d42 Compare July 27, 2026 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants