Skip to content

fix(deps): update mantine monorepo to v9#233

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

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

Conversation

@renovate

@renovate renovate Bot commented Sep 18, 2023

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) 6.0.229.4.1 age confidence
@mantine/hooks (source) 6.0.229.4.1 age confidence

Release Notes

mantinedev/mantine (@​mantine/core)

v9.4.1

Compare Source

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 '@​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="red"
          onClick={() =>
            notifications.show(
              {
                title: 'High priority',
                message: 'I take the visible slot even when the limit is reached',
                color: 'red',
                autoClose: false,
                priority: 10,
              },
              store
            )
          }
        >
          Show high priority
        </Button>
      </Group>
    </>
  );
}

Legend support for PieChart, DonutChart and FunnelChart

PieChart, DonutChart and FunnelChart
now support the withLegend prop. When enabled, a legend with the name and color of each segment
is displayed. Hovering over a legend item highlights the corresponding segment. Use the legendProps
prop to pass props down to the underlying recharts Legend component.

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

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

// data.ts
export const data = [
  { name: 'USA', value: 400, color: 'indigo.6' },
  { name: 'India', value: 300, color: 'yellow.6' },
  { name: 'Japan', value: 300, color: 'teal.6' },
  { name: 'Other', value: 200, color: 'gray.6' },
];

autoContrast support for virtual colors

Virtual colors now support autoContrast.
Previously, filled components with a virtual color always used white text because the underlying color
could not be resolved on the JavaScript side. The contrast color is now calculated separately for each
color scheme based on the resolved background color, so text stays readable when the virtual color resolves
to a light color in one scheme and a dark color in another. Switch between light and dark color schemes
(Ctrl + J) to see the text color adjust:

// App.tsx
import { Button, colorsTuple, createTheme, MantineProvider, virtualColor } from '@&#8203;mantine/core';
import { Demo } from './Demo';

const theme = createTheme({
  colors: {
    white: colorsTuple('#FFFFFF'),
    black: colorsTuple('#&#8203;000000'),
    adaptive: virtualColor({
      name: 'adaptive',
      dark: 'white',
      light: 'black',
    }),
  },
});

function App() {
  return (
    <MantineProvider theme={theme}>
      <Demo />
    </MantineProvider>
  );
}

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

export function Demo() {
  return (
    <Button color="adaptive" autoContrast>
      Button
    </Button>
  );
}

Other changes

  • Splitter now supports resetOnDoubleClick prop. When enabled, double-clicking a resize handle restores the adjacent panes to their default ratio.
  • TimePicker now supports closeDropdownOnPresetSelect prop. When set, the dropdown is closed once a value is selected from the presets list.
  • useLongPress hook now handles onTouchCancel events: the returned handlers include an onTouchCancel callback so that a long press is correctly canceled when the touch is interrupted by the system (incoming call, browser gesture, etc.).

v9.3.2

Compare Source

What's Changed
  • [@mantine/core] Allow undefined className with TypeScript exactOptionalPropertyTypes (#​8978)
  • [@mantine/dates] TimePicker: Allow entering 01-09 hours over a selected 00 value (#​8970)
  • [@mantine/mcp-server] Fix cli flags not being handled correctly (#​8966)
  • [@mantine/core] Combobox: Fix default options rendering not fully working with some components combination (#​8979)
  • [@mantine/charts] SankeyChart: Fix incorrect color resolving (#​8973)
  • [@mantine/dates] DatePickerPicker: Fix range presets ignoring specified time (#​8980)
  • [@mantine/schedule] DayView: Fix double top border when events are present
  • [@mantine/dates] TimePicker: Add closeDropdownOnPresetSelect prop support
  • [@mantine/dates] TimePicker: Fix input getting stuck at maximum value when typing at the last spin input
  • [@mantine/core] PasswordInput: Fix sections misplaced when dir overrides parent direction (#​8936)
  • [@mantine/core] Splitter: Add option to reset on double click (#​8957)
  • [@mantine/core] Popover: Fix dropdown position not updating when page is zommed
  • [@mantine/core] Text: Fix incorrect default textWrap value (#​8961)
  • [@mantine/core] Checkbox: Fix readOnly prop not working correctly for controlled checkbox (#​8960)
  • [@mantine/core] Textarea: Fix autosize textarea not growing when resized within Splitter (#​8956)
New Contributors

Full Changelog: mantinedev/mantine@9.3.1...9.3.2

v9.3.1

Compare Source

What's Changed

  • [@mantine/notifications] Fix stale DOM nodes references not being cleaned up when notifications is closed (#​8955)
  • [@mantine/dates] DateInput: Add presets support (#​8954)
  • [@mantine/core] Collapse: Fix keepMounted prop not being set correctly (#​8949)
  • [@mantine/core] Menu: Add controlled state support for Menu.Sub opened state
  • [@mantine/schedule] Fix incorrect current time indicator position when time does not divide evenly with interval minutes in DayView and WeekView (#​8945)
  • [@mantine/core] Popover: Fix context menu not working on iOS touch devices (#​8942)
  • [@mantine/core] SegemntedControl: Fix incorrect indicator border-radius calculation (#​8904)
  • [@mantine/core] PinInput: Fix incorrect placeholder text centering (#​8943)
  • [@mantine/core] Tree: Fix arrow key navigation focusing hidden nodes when keepMounted is set (#​8939)
  • [@mantine/core] MaskInput: Fix compatibility issues with uncontrolled use-form (#​8947)
  • [@mantine/hooks] use-id: Fix id changing to new value with Activity (#​8925)

New Contributors

Full Changelog: mantinedev/mantine@9.3.0...9.3.1

v9.3.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.

Pagination responsive layout

Pagination component now supports layout="responsive" prop that uses CSS container
queries to switch between page number buttons and a compact "Page X of Y" label based on the available width.

import { Box, Pagination } from '@&#8203;mantine/core';

function Demo() {
  return (
    <Box style={{ resize: 'horizontal', overflow: 'auto', minWidth: 200, maxWidth: '100%' }}>
      <Pagination total={20} layout="responsive" />
    </Box>
  );
}

Text textWrap prop

Text and Blockquote components now support
textWrap prop that controls the text-wrap CSS property. You can use it to balance line lengths
or prevent orphaned words in paragraphs.

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

function Demo() {
  return (
    <Text textWrap="wrap">
      Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quasi voluptatibus inventore iusto
      cum dolore molestiae perspiciatis! Totam repudiandae impedit maxime!
    </Text>
  );
}

use-splitter hook

New use-splitter hook provides resizable split-pane functionality
with pointer drag, keyboard navigation (WAI-ARIA Window Splitter pattern), collapsible panels
and min/max constraints:

import React from 'react';
import { DotsSixVerticalIcon } from '@&#8203;phosphor-icons/react';
import { useSplitter } from '@&#8203;mantine/hooks';

const colors = ['var(--mantine-color-blue-filled)', 'var(--mantine-color-teal-filled)'];
const labels = ['Panel A', 'Panel B'];

function Demo() {
  const splitter = useSplitter({
    panels: [
      { defaultSize: 50, min: 20 },
      { defaultSize: 50, min: 20 },
    ],
  });

  return (
    <div
      ref={splitter.ref}
      style={{
        display: 'flex',
        height: 200,
        borderRadius: 'var(--mantine-radius-md)',
        overflow: 'hidden',
      }}
    >
      {splitter.sizes.map((size, i) => (
        <React.Fragment key={i}>
          {i > 0 && (
            <div
              {...splitter.getHandleProps({ index: i - 1 })}
              style={{
                width: 4,
                flexShrink: 0,
                cursor: 'col-resize',
                touchAction: 'none',
                backgroundColor: 'var(--mantine-color-default-border)',
                position: 'relative',
              }}
            >
              <div
                style={{
                  position: 'absolute',
                  top: '50%',
                  left: '50%',
                  transform: 'translate(-50%, -50%)',
                  width: 8,
                  height: 40,
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  borderRadius: 'var(--mantine-radius-xs)',
                  backgroundColor: 'var(--mantine-color-default)',
                  border: '1px solid var(--mantine-color-default-border)',
                  color: 'var(--mantine-color-dimmed)',
                }}
              >
                <DotsSixVerticalIcon />
              </div>
            </div>
          )}
          <div
            style={{
              width: `${size}%`,
              display: 'flex',
              flexDirection: 'column',
              alignItems: 'center',
              justifyContent: 'center',
              backgroundColor: colors[i],
              color: 'var(--mantine-color-white)',
              fontWeight: 500,
              whiteSpace: 'nowrap',
              gap: 2,
            }}
          >
            {labels[i]} ({Math.round(size)}%)
          </div>
        </React.Fragment>
      ))}
    </div>
  );
}

Splitter component

New Splitter component provides declarative resizable split pane layout
built on top of the use-splitter hook:

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

function Demo() {
  return (
    <Splitter orientation="horizontal" h={200}>
      <Splitter.Pane defaultSize={50} min={20} bg="blue">
        First pane
      </Splitter.Pane>
      <Splitter.Pane defaultSize={50} min={20} bg="teal">
        Second pane
      </Splitter.Pane>
    </Splitter>
  );
}

CodeHighlight line numbers

CodeHighlight component now supports withLineNumbers prop
to display line numbers alongside the code:

import { CodeHighlight } from '@&#8203;mantine/code-highlight';

const exampleCode = `...`;

function Demo() {
  return <CodeHighlight code={exampleCode} language="tsx" withLineNumbers />;
}

OverflowList collapseFrom

OverflowList component now supports collapseFrom prop that controls
from which direction items are collapsed when they overflow. Set collapseFrom="start" to
collapse items from the beginning – this is useful for breadcrumb-like patterns where
the last items should remain visible.

// OverflowListDemo.tsx
import { Badge, OverflowList } from '@&#8203;mantine/core';
import { data } from './data';

function Demo() {
  return (
    <div style={{ resize: 'horizontal', overflow: 'auto', maxWidth: '100%' }}>
      <OverflowList
        data={data}
        gap={4}
        collapseFrom="start"
        renderOverflow={(items) => <Badge>+{items.length} more</Badge>}
        renderItem={(item, index) => <Badge key={index}>{item}</Badge>}
      />
    </div>
  );
}

// data.ts
export const data = [
  'Apple',
  'Banana',
  'Cherry',
  'Date',
  'Elderberry',
  'Fig',
  'Grape',
  'Honeydew',
  'Indian Fig',
  'Jackfruit',
  'Kiwi',
  'Lemon',
  'Mango',
  'Nectarine',
  'Orange',
  'Papaya',
];

Textarea bottomSection

Textarea component now supports bottomSection prop that renders content
inside the input border at the bottom. This is useful for displaying character counters
or other supplementary information:

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

function Demo() {
  const maxLength = 500;
  const [value, setValue] = useState('');

  return (
    <Textarea
      label="Your message"
      placeholder="Type your message..."
      autosize
      minRows={4}
      value={value}
      onChange={(event) => setValue(event.currentTarget.value.slice(0, maxLength))}
      bottomSection={
        <Text size="xs" c="dimmed">
          {value.length}/{maxLength} characters
        </Text>
      }
    />
  );
}

Combobox floatingHeight

Combobox, Select, MultiSelect,
Autocomplete and TagsInput now support
floatingHeight="viewport". When set, the dropdown grows to fill the available vertical
space in the viewport and the flip middleware is disabled – useful when working with
large option lists:

import { useState } from 'react';
import { Combobox, Input, InputBase, ScrollArea, useCombobox } from '@&#8203;mantine/core';

const countries = [
  'Afghanistan', 'Albania', 'Algeria', 'Andorra', 'Angola', 'Argentina', 'Armenia', 'Australia',
  'Austria', 'Azerbaijan', 'Bahamas', 'Bahrain', 'Bangladesh', 'Barbados', 'Belarus', 'Belgium',
  'Belize', 'Benin', 'Bhutan', 'Bolivia', 'Botswana', 'Brazil', 'Brunei', 'Bulgaria', 'Burkina Faso',
  'Burundi', 'Cambodia', 'Cameroon', 'Canada', 'Cape Verde', 'Chad', 'Chile', 'China', 'Colombia',
  'Comoros', 'Costa Rica', 'Croatia', 'Cuba', 'Cyprus', 'Czech Republic', 'Denmark', 'Djibouti',
  'Dominica', 'Ecuador', 'Egypt', 'El Salvador', 'Estonia', 'Eswatini', 'Ethiopia', 'Fiji',
  'Finland', 'France', 'Gabon', 'Gambia', 'Georgia', 'Germany', 'Ghana', 'Greece', 'Grenada',
  'Guatemala', 'Guinea', 'Guyana', 'Haiti', 'Honduras', 'Hungary', 'Iceland', 'India', 'Indonesia',
  'Iran', 'Iraq', 'Ireland', 'Israel', 'Italy', 'Jamaica', 'Japan', 'Jordan', 'Kazakhstan', 'Kenya',
  'Kiribati', 'Kuwait', 'Kyrgyzstan', 'Laos', 'Latvia', 'Lebanon', 'Lesotho', 'Liberia', 'Libya',
  'Liechtenstein', 'Lithuania', 'Luxembourg', 'Madagascar', 'Malawi', 'Malaysia', 'Maldives',
  'Mali', 'Malta', 'Mauritania', 'Mauritius', 'Mexico', 'Moldova', 'Monaco', 'Mongolia',
];

function Demo() {
  const combobox = useCombobox({
    onDropdownClose: () => combobox.resetSelectedOption(),
  });

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

  const options = countries.map((item) => (
    <Combobox.Option value={item} key={item}>
      {item}
    </Combobox.Option>
  ));

  return (
    <Combobox
      store={combobox}
      floatingHeight="viewport"
      onOptionSubmit={(val) => {
        setValue(val);
        combobox.closeDropdown();
      }}
    >
      <Combobox.Target>
        <InputBase
          component="button"
          type="button"
          pointer
          rightSection={<Combobox.Chevron />}
          rightSectionPointerEvents="none"
          onClick={() => combobox.toggleDropdown()}
        >
          {value || <Input.Placeholder>Pick a country</Input.Placeholder>}
        </InputBase>
      </Combobox.Target>

      <Combobox.Dropdown>
        <Combobox.Options>
          <ScrollArea.Autosize mah="var(--combobox-floating-options-max-height)" type="scroll">
            {options}
          </ScrollArea.Autosize>
        </Combobox.Options>
      </Combobox.Dropdown>
    </Combobox>
  );
}

Menu submenu safe polygon

Menu submenus now use a safe polygon when moving the cursor from
the parent item to the dropdown. This allows you to move the cursor diagonally
across other menu items without accidentally closing the submenu.

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

function Demo() {
  return (
    <Menu width={200} position="bottom-start">
      <Menu.Target>
        <Button>Toggle Menu</Button>
      </Menu.Target>

      <Menu.Dropdown>
        <Menu.Item>Dashboard</Menu.Item>

        <Menu.Sub openDelay={120} closeDelay={150}>
          <Menu.Sub.Target>
            <Menu.Sub.Item>Products</Menu.Sub.Item>
          </Menu.Sub.Target>

          <Menu.Sub.Dropdown>
            <Menu.Item>All products</Menu.Item>
            <Menu.Item>Categories</Menu.Item>
            <Menu.Item>Tags</Menu.Item>
            <Menu.Item>Attributes</Menu.Item>
            <Menu.Item>Shipping classes</Menu.Item>
          </Menu.Sub.Dropdown>
        </Menu.Sub>

        <Menu.Item>Customers</Menu.Item>
        <Menu.Item>Reports</Menu.Item>

        <Menu.Sub>
          <Menu.Sub.Target>
            <Menu.Sub.Item>Orders</Menu.Sub.Item>
          </Menu.Sub.Target>

          <Menu.Sub.Dropdown>
            <Menu.Item>Open</Menu.Item>
            <Menu.Item>Completed</Menu.Item>
            <Menu.Item>Cancelled</Menu.Item>
          </Menu.Sub.Dropdown>
        </Menu.Sub>

        <Menu.Sub>
          <Menu.Sub.Target>
            <Menu.Sub.Item>Settings</Menu.Sub.Item>
          </Menu.Sub.Target>

          <Menu.Sub.Dropdown>
            <Menu.Item>Profile</Menu.Item>
            <Menu.Item>Security</Menu.Item>
            <Menu.Item>Notifications</Menu.Item>
          </Menu.Sub.Dropdown>
        </Menu.Sub>
      </Menu.Dropdown>
    </Menu>
  );
}

Menu search

Menu now supports Menu.Search – a search input that filters items
without taking focus away from the input. Use ArrowUp/ArrowDown to move the
highlight, Enter to trigger the highlighted item. Filtering logic is controlled
by the user: pass value/onChange and filter Menu.Item children based on the query.
The search value is cleared automatically after the menu close transition completes; set
clearSearchOnClose={false} to keep the query between openings.

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

const data = [
  'Dashboard',
  'Customers',
  'Products',
  'Orders',
  'Reports',
  'Settings',
  'Integrations',
  'Billing',
  'Team members',
  'Help center',
];

function Demo() {
  const [query, setQuery] = useState('');
  const items = data.filter((item) => item.toLowerCase().includes(query.toLowerCase().trim()));

  return (
    <Menu shadow="md" width={240}>
      <Menu.Target>
        <Button>Toggle menu</Button>
      </Menu.Target>

      <Menu.Dropdown>
        <Menu.Search
          value={query}
          onChange={(event) => setQuery(event.currentTarget.value)}
          placeholder="Search items"
        />

        {items.length > 0 ? (
          items.map((item) => <Menu.Item key={item}>{item}</Menu.Item>)
        ) : (
          <Text c="dimmed" size="sm" ta="center" py="xs">
            Nothing found
          </Text>
        )}
      </Menu.Dropdown>
    </Menu>
  );
}

Menu checkbox and radio items

Menu now supports Menu.CheckboxItem, Menu.RadioItem, and Menu.RadioGroup
for building option menus. Checkbox and radio items render an indicator slot at the start
and do not close the menu on click by default. The new alignItemsLabels prop on Menu
controls how indicator slot space is reserved so labels stay aligned when mixing plain
and indicator items.

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

function Demo() {
  const [columns, setColumns] = useState({
    name: true,
    email: true,
    role: false,
    lastSeen: false,
  });

  const setColumn = (key: keyof typeof columns) => (checked: boolean) =>
    setColumns((current) => ({ ...current, [key]: checked }));

  return (
    <Menu shadow="md" width={220} closeOnItemClick={false}>
      <Menu.Target>
        <Button>Columns</Button>
      </Menu.Target>

      <Menu.Dropdown>
        <Menu.Label>Visible columns</Menu.Label>
        <Menu.CheckboxItem checked={columns.name} onChange={setColumn('name')}>
          Name
        </Menu.CheckboxItem>
        <Menu.CheckboxItem checked={columns.email} onChange={setColumn('email')}>
          Email
        </Menu.CheckboxItem>
        <Menu.CheckboxItem checked={columns.role} onChange={setColumn('role')}>
          Role
        </Menu.CheckboxItem>
        <Menu.CheckboxItem checked={columns.lastSeen} onChange={setColumn('lastSeen')}>
          Last seen
        </Menu.CheckboxItem>
      </Menu.Dropdown>
    </Menu>
  );
}

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

function Demo() {
  const [sort, setSort] = useState('newest');

  return (
    <Menu shadow="md" width={220} closeOnItemClick={false}>
      <Menu.Target>
        <Button>Sort by</Button>
      </Menu.Target>

      <Menu.Dropdown>
        <Menu.Label>Order</Menu.Label>
        <Menu.RadioGroup value={sort} onChange={setSort}>
          <Menu.RadioItem value="newest">Newest first</Menu.RadioItem>
          <Menu.RadioItem value="oldest">Oldest first</Menu.RadioItem>
          <Menu.RadioItem value="popular">Most popular</Menu.RadioItem>
          <Menu.RadioItem value="commented">Most commented</Menu.RadioItem>
        </Menu.RadioGroup>
      </Menu.Dropdown>
    </Menu>
  );
}

Menu context menu

Menu now supports Menu.ContextMenu – a target replacement that opens the
dropdown at the cursor position when the wrapped element is right-clicked. The browser's
default context menu is suppressed, and right-clicking again repositions the dropdown to
the new coordinates.

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

function Demo() {
  return (
    <Menu shadow="md" width={200}>
      <Menu.ContextMenu>
        <Paper withBorder p="xl" radius="md" style={{ userSelect: 'none', textAlign: 'center' }}>
          <Text fw={500}>Right-click anywhere inside this area</Text>
          <Text c="dimmed" size="sm" mt={4}>
            The menu will open at the cursor position
          </Text>
        </Paper>
      </Menu.ContextMenu>

      <Menu.Dropdown>
        <Menu.Label>Actions</Menu.Label>
        <Menu.Item>Open</Menu.Item>
        <Menu.Item>Rename</Menu.Item>
        <Menu.Item>Duplicate</Menu.Item>
        <Menu.Divider />
        <Menu.Item color="red">Delete</Menu.Item>
      </Menu.Dropdown>
    </Menu>
  );
}

Popover context menu

Popover now supports Popover.ContextMenu – a target replacement that
opens the dropdown at the cursor position on right-click. Unlike Menu.ContextMenu,
Popover.Dropdown can contain any content.

import { Avatar, Button, Group, Paper, Popover, Stack, Text } from '@&#8203;mantine/core';

function Demo() {
  return (
    <Popover width={260} shadow="md" position="bottom-start" offset={0}>
      <Popover.ContextMenu>
        <Paper withBorder p="xl" radius="md" style={{ userSelect: 'none', textAlign: 'center' }}>
          <Text fw={500}>Right-click anywhere inside this area</Text>
          <Text c="dimmed" size="sm" mt={4}>
            A popover will open at the cursor position
          </Text>
        </Paper>
      </Popover.ContextMenu>

      <Popover.Dropdown>
        <Stack gap="xs">
          <Group gap="sm" wrap="nowrap">
            <Avatar radius="xl" color="blue">JD</Avatar>
            <div>
              <Text size="sm" fw={500}>Jane Doe</Text>
              <Text size="xs" c="dimmed">jane@example.com</Text>
            </div>
          </Group>
          <Group grow gap="xs">
            <Button size="xs" variant="default">Message</Button>
            <Button size="xs">Follow</Button>
          </Group>
        </Stack>
      </Popover.Dropdown>
    </Popover>
  );
}

Menu type-ahead navigation

When focus is inside Menu dropdown (and Menu.Search is not used), pressing a
printable character key now moves focus to the next item whose label starts with the typed
character. Pressing the same character cycles through matches, and multiple characters typed
within 500ms match items by full prefix.

import { Menu, Button, Text } from '@&#8203;mantine/core';
import { GearSixIcon, MagnifyingGlassIcon, ImageIcon, ChatCircleIcon, TrashIcon, IconArrowsLeftRight } from '@&#8203;phosphor-icons/react';

function Demo() {
  return (
    <Menu shadow="md" width={200}>
      <Menu.Target>
        <Button>Toggle menu</Button>
      </Menu.Target>

      <Menu.Dropdown>
        <Menu.Label>Application</Menu.Label>
        <Menu.Item leftSection={<GearSixIcon size={14} />}>
          Settings
        </Menu.Item>
        <Menu.Item leftSection={<ChatCircleIcon size={14} />}>
          Messages
        </Menu.Item>
        <Menu.Item leftSection={<ImageIcon size={14} />}>
          Gallery
        </Menu.Item>
        <Menu.Item
          leftSection={<MagnifyingGlassIcon size={14} />}
          rightSection={
            <Text size="xs" c="dimmed">
              ⌘K
            </Text>
          }
        >
          Search
        </Menu.Item>

        <Menu.Divider />

        <Menu.Label>Danger zone</Menu.Label>
        <Menu.Item
          leftSection={<IconArrowsLeftRight size={14} />}
        >
          Transfer my data
        </Menu.Item>
        <Menu.Item
          color="red"
          leftSection={<TrashIcon size={14} />}
        >
          Delete my account
        </Menu.Item>
      </Menu.Dropdown>
    </Menu>
  );
}

Highlight accent and case insensitive matching

Highlight component now supports caseInsensitive and accentInsensitive
props. Both are enabled by default – matching is case-insensitive and accent-insensitive,
so cafe matches café, CAFÉ, etc. Set either prop to false to opt out:

import { Highlight, Stack, Text } from '@&#8203;mantine/core';

function Demo() {
  return (
    <Stack gap="md">
      <div>
        <Text size="sm" fw={500} mb={5}>
          With accent-insensitive matching (default)
        </Text>
        <Highlight highlight="cafe">We visited café and cafe.</Highlight>
      </div>

      <div>
        <Text size="sm" fw={500} mb={5}>
          {'With accent-sensitive matching (accentInsensitive={false})'}
        </Text>
        <Highlight highlight="cafe" accentInsensitive={false}>
          We visited café and cafe.
        </Highlight>
      </div>
    </Stack>
  );
}

PieChart and DonutChart labelsType="name"

[PieChart](https://mantine.

Note

PR body was truncated to here.


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.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@changeset-bot

changeset-bot Bot commented Sep 18, 2023

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 49a8272

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.

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

@socket-security

socket-security Bot commented Sep 18, 2023

Copy link
Copy Markdown

Updated dependencies detected. Learn more about Socket for GitHub ↗︎

Packages Version New capabilities Transitives Size Publisher
@mantine/hooks 6.0.21...7.1.3 None +0/-0 536 kB rtivital
@mantine/core 6.0.21...7.1.3 None +8/-23 9.43 MB rtivital

@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 3 times, most recently from 5175bd7 to c202c09 Compare September 28, 2023 09:44
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from 8379140 to 92c729c Compare October 2, 2023 20:22
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 3 times, most recently from f7bbe2c to e114e58 Compare October 19, 2023 10:19
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 3 times, most recently from b410886 to 3163dda Compare October 26, 2023 14:43
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 4 times, most recently from de0ff16 to ed16dfe Compare November 13, 2023 12:13
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch from ed16dfe to c28961c Compare November 18, 2023 12:23
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from b1681cd to 5fd3ae3 Compare November 29, 2023 15:16
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 4 times, most recently from 9b4964d to 24643f9 Compare December 11, 2023 03:26
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from 15fe8ed to 6d8cbd6 Compare December 18, 2023 03:36
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from 75e7bd3 to cc183fa Compare January 3, 2024 10:56
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from 89c6a25 to 54729f6 Compare January 9, 2024 09:14
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from b026a66 to 51c4da4 Compare March 18, 2024 03:22
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 4 times, most recently from 7cb58ba to a3fa2a2 Compare April 1, 2024 04:14
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 3 times, most recently from e8a125a to 5307a5b Compare April 12, 2024 12:57
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from 994f4aa to 66541ff Compare April 22, 2024 03:09
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from aa78110 to 1c878e4 Compare April 29, 2024 04:21
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 3 times, most recently from 206d0e2 to e211da0 Compare May 8, 2024 10:32
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from a1391f5 to aafe63b Compare May 17, 2024 17:57
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 3 times, most recently from da11e0b to b3249ec Compare May 27, 2024 03:14
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch from b3249ec to 4c672ef Compare May 30, 2024 10:12
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from 0e0e508 to c13e47c Compare June 13, 2024 10:22
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 2 times, most recently from d867a67 to 9b54f7a Compare July 2, 2024 14:11
@renovate renovate Bot force-pushed the renovate/major-mantine-monorepo branch 3 times, most recently from 8b053e0 to 31de66d Compare July 13, 2024 20:33
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