v7.0.2
For more details visit https://dockview.dev/docs/overview/whats-new-v7. For migration from v6 visit https://dockview.dev/docs/overview/migrating-to-v7.
- fix: charset in merged styles by @puschie286 in https://github.com/mathuo/dockview/pull/1309
- feat: modularize components for long term architecture by @mathuo in https://github.com/mathuo/dockview/pull/1303
- feat(dockview-core): dedicated floating-group drag handle by @mathuo in https://github.com/mathuo/dockview/pull/1312
- feat(dockview-core): floating & popout windows as nested (multi-group) layouts by @mathuo in https://github.com/mathuo/dockview/pull/1310
- fix(dockview-core): polish spaced theme floating groups by @mathuo in https://github.com/mathuo/dockview/pull/1313
- feat(dockview-core): WAI-ARIA roles and states for tabs, groups and floating groups by @mathuo in https://github.com/mathuo/dockview/pull/1314
- refactor(dockview-core): consolidate advanced drag-and-drop behind a module + add dropOverlayModel by @mathuo in https://github.com/mathuo/dockview/pull/1315
- feat(dockview-core): a11y polish — tab keyboard navigation + floating dialog name by @mathuo in https://github.com/mathuo/dockview/pull/1316
- feat(dockview-core): layout-mutation transaction events (onWillMutateLayout / onDidMutateLayout) by @mathuo in https://github.com/mathuo/dockview/pull/1317
- feat(dockview-core): AdvancedDnD showPreviewOverlay (keyboard-docking seam) by @mathuo in https://github.com/mathuo/dockview/pull/1318
- feat(dockview-core): LiveRegion announcer + keyboard docking (AccessibilityModule) by @mathuo in https://github.com/mathuo/dockview/pull/1319
- feat(dockview-core): spatial keyboard group focus + focus-logic refactor by @mathuo in https://github.com/mathuo/dockview/pull/1320
- feat(dockview-core): L4 focus management by @mathuo in https://github.com/mathuo/dockview/pull/1321
- feat(dockview-core): L5 announcements — assertive region, more events, pluggable announcer by @mathuo in https://github.com/mathuo/dockview/pull/1322
- feat(dockview-core): i18n message catalog for accessibility strings by @mathuo in https://github.com/mathuo/dockview/pull/1323
- chore(dockview-core): module boundary hardening (removability test + contract extraction) by @mathuo in https://github.com/mathuo/dockview/pull/1324
- feat(dockview-core): tag layout-mutation origin and complete mutation-boundary coverage by @mathuo in https://github.com/mathuo/dockview/pull/1328
- feat(dockview-core): add popout group open event and enumeration by @mathuo in https://github.com/mathuo/dockview/pull/1330
- feat(dockview-core): add a floating-group drag position transform hook by @mathuo in https://github.com/mathuo/dockview/pull/1331
- feat(dockview-core): expose spatial group navigation and geometry by @mathuo in https://github.com/mathuo/dockview/pull/1332
- feat(dockview-core)!: remove the deprecated rootOverlayModel option by @mathuo in https://github.com/mathuo/dockview/pull/1336
- feat(dockview-core): report user-vs-api origin on active panel change by @mathuo in https://github.com/mathuo/dockview/pull/1335
- feat(dockview-core): keyboard tab-close + focus-the-tab-strip by @mathuo in https://github.com/mathuo/dockview/pull/1337
- feat!: v7 package rename — dockview as vanilla JS entry, React bindings to dockview-react by @mathuo in https://github.com/mathuo/dockview/pull/1338
- feat: extract separable feature modules into a dockview-modules package by @mathuo in https://github.com/mathuo/dockview/pull/1342
- fix(v7): externalize dockview-react bundle + complete the v7 migration guide by @mathuo in https://github.com/mathuo/dockview/pull/1345
- fix(build): __esModule + exports maps + sideEffects for v7 packages by @mathuo in https://github.com/mathuo/dockview/pull/1347
- test(docs): build example templates against a specific (experimental) version by @mathuo in https://github.com/mathuo/dockview/pull/1346
- fix(dockview-angular): ship bundled CSS under dist/styles by @mathuo in https://github.com/mathuo/dockview/pull/1348
- chore(v7): audit cleanup — group origin, popout remove event, exports, comments by @mathuo in https://github.com/mathuo/dockview/pull/1349
- docs: v7 feature docs + migration guide by @mathuo in https://github.com/mathuo/dockview/pull/1350
- docs/v7: audit follow-ups, regenerated API reference, floatingGroupDragHandle by @mathuo in https://github.com/mathuo/dockview/pull/1351
- feat: split keyboard support into default navigation + optional docking module by @mathuo in https://github.com/mathuo/dockview/pull/1353
- fix(dockview-core): tab group indicator placement for bottom/right header positions by @mathuo in https://github.com/mathuo/dockview/pull/1333
- docs: treat dockview-core as internal; point users at dockview by @mathuo in https://github.com/mathuo/dockview/pull/1354
- refactor: v7 public API naming + deprecation cleanups by @mathuo in https://github.com/mathuo/dockview/pull/1355
- docs: prefer "JavaScript" over "vanilla"; treat module system as internal by @mathuo in https://github.com/mathuo/dockview/pull/1356
- chore: include dockview-modules in SonarCloud analysis by @mathuo in https://github.com/mathuo/dockview/pull/1357
- fix: keep dockview-modules & docs in version lockstep (v7 CI fix) by @mathuo in https://github.com/mathuo/dockview/pull/1359
- fix: watermark overlay persists over layout after fromJSON (blocks clicks) by @mathuo in https://github.com/mathuo/dockview/pull/1360
Full Changelog: https://github.com/mathuo/dockview/compare/v6.6.1...v7.0.2
9.4.0 🥵
View changelog with demos on mantine.dev website
You can now sponsor Mantine development with OpenCollective. All funds are used to improve Mantine and create new features and components.
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>
);
}
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 '@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>
);
}
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 '@mantine/core';
import { MagnifyingGlassIcon } from '@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>
);
}
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 '@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>
);
}
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 '@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 '@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 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 '@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 '@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',
},
];
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 '@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 '@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',
},
];
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 '@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 '@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' },
];
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 '@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}
/>
);
}
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 '@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 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 '@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 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 '@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}
/>
);
}
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 '@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.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 '@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 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 '@mantine/core';
import { createNotificationsStore, notifications, Notifications } from '@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>
</>
);
}
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 '@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' },
];
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 '@mantine/core';
import { Demo } from './Demo';
const theme = createTheme({
colors: {
white: colorsTuple('#FFFFFF'),
black: colorsTuple('#000000'),
adaptive: virtualColor({
name: 'adaptive',
dark: 'white',
light: 'black',
}),
},
});
function App() {
return (
<MantineProvider theme={theme}>
<Demo />
</MantineProvider>
);
}
// Demo.tsx
import { Button } from '@mantine/core';
export function Demo() {
return (
<Button color="adaptive" autoContrast>
Button
</Button>
);
}
- Splitter now supports
resetOnDoubleClickprop. When enabled, double-clicking a resize handle restores the adjacent panes to their default ratio. - TimePicker now supports
closeDropdownOnPresetSelectprop. When set, the dropdown is closed once a value is selected from the presets list. - useLongPress hook now handles
onTouchCancelevents: the returned handlers include anonTouchCancelcallback so that a long press is correctly canceled when the touch is interrupted by the system (incoming call, browser gesture, etc.).
v4.5.0
- Adapters
- New
registerAdapter()API to extendanimate()andutils.set()to non-DOM targets (learn more: https://animejs.com/documentation/adapters)
- New
- Three.js adapter
- New built-in three.js adapter, imported as a side-effect from
animejs/adapters/three, to animateObject3D, materials, lights, cameras, audio nodes,UniformNode(TSL) and instanced meshes (learn more: https://animejs.com/documentation/adapters/three)
- New built-in three.js adapter, imported as a side-effect from
- Stagger
- Auto-grid mode now supports 3D layouts, using
{x, y, z}coordinates or an explicitgrid: [columns, rows, depth]triplet - The
fromparameter now accepts[x, y, z]normalized coordinates andaxisnow accepts'z'for 3D grid origins - New
jitterparameter to add a random offset to staggered values, either a single number or a[start, end]range - New
seedparameter to makejitterandfrom: 'random'reproducible
- Auto-grid mode now supports 3D layouts, using
- Color
- Color animations now blend RGB channels in pseudo-linear space for smoother, more even transitions (intermediate colors differ slightly from previous versions)
- Render
- Fix a flicker that could appear randomly between iterations of reversed loops
- Fix a flicker that could appear randomly on alternate loops when using non-integer duration values
- Timeline
- Fix a backward seek leaving a timeline child stuck at its end value when all its properties share the same delay
- Fix a timeline child whose delay is longer than its duration overwriting a later sibling's value on a forward seek
- Fix stale values when seeking a timeline whose children animate the same property through delayed tweens, most visible with staggered
jitterdelays - Fix an implicit
fromvalue resolving to a stale value when an overridden tween sits earlier in the chain - Improve performance when building large timelines with many overlapping
.add()calls on the same property, and fix a case where such a timeline could cancel itself
- Keyframes
- Fix a floating point precision issue producing incorrect intermediate values in keyframe arrays
- Fix scrubbing backward past the start of a keyframe sequence not restoring the first keyframe's
fromvalue - Fix scrubbing forward past the end of a keyframe sequence leaving the target stuck on a previous keyframe's value
- Fix sequential keyframes occasionally detected as overlapping because of floating point drift, leaving the target stuck on the wrong value when scrubbing
- Animation
- Fix function-based and CSS variable
fromvalues in object form ({ from, to }) not re-resolving onrefresh() - Fix
stretch()not correctly scaling animations that use keyframes
- Fix function-based and CSS variable
- Scroll
- Fix a
getBoundingClientRectcrash that could happen when a scroll container resized before its target was ready
- Fix a
- Engine
- More accurate frame scheduling that no longer drops frames arriving slightly early because of
requestAnimationFramejitter - Faster
engine.speedandengine.timeUnitupdates that skip unnecessary work when the value does not actually change
- More accurate frame scheduling that no longer drops frames arriving slightly early because of
@xyflow/react@12.11.1
-
#5815
87da45c- FixFinalConnectionStatetype so it preserves the discriminated union. -
#5824
6b1dac5- Do not fire on pane click when connection ends on pane -
#5818
4ddc2d8- Provide the shared handle config (connectOnClick,noPanClassName,rfId) through context instead of subscribing to the store in everyHandle, so a store update no longer runs a selector once per handle -
#5817
8df250b- Reduce per-handle work on store updates by returning a shared connection state while no connection is in progress. -
#5822
a6249de- Return stable reference for edge position when connected node gets deleted -
Updated dependencies [
ceb8604,87da45c]:- @xyflow/system@0.0.78
@xyflow/react@12.11.1
-
#5815
87da45c- FixFinalConnectionStatetype so it preserves the discriminated union. -
#5824
6b1dac5- Do not fire on pane click when connection ends on pane -
#5818
4ddc2d8- Provide the shared handle config (connectOnClick,noPanClassName,rfId) through context instead of subscribing to the store in everyHandle, so a store update no longer runs a selector once per handle -
#5817
8df250b- Reduce per-handle work on store updates by returning a shared connection state while no connection is in progress. -
#5822
a6249de- Return stable reference for edge position when connected node gets deleted -
Updated dependencies [
ceb8604,87da45c]:- @xyflow/system@0.0.78