ResourcesMonthView

Month view with resource lanes for scheduling across resources

Usage

ResourcesMonthView displays a month grid where each day cell contains resource lanes. Events are shown within their resource's lane, making it easy to see resource utilization across the month.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
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')}
    />
  );
}

Static mode

Set mode="static" to disable all interactions.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
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}
      mode="static"
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

Drag and drop

Enable drag and drop with withEventsDragAndDrop prop. The onEventDrop callback receives the resourceId of the target resource, allowing you to update the event's resource assignment.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesMonthView, ScheduleEventData } from '@mantine/schedule';
import { events as initialEvents, resources } from './data';

function Demo() {
  const [date, setDate] = useState(dayjs().format('YYYY-MM-DD'));
  const [events, setEvents] = useState<ScheduleEventData[]>(initialEvents);

  return (
    <ResourcesMonthView
      date={date}
      onDateChange={setDate}
      resources={resources}
      events={events}
      withEventsDragAndDrop
      onEventDrop={({ eventId, newStart, newEnd, resourceId }) => {
        setEvents((current) =>
          current.map((event) =>
            event.id === eventId
              ? { ...event, start: newStart, end: newEnd, resourceId }
              : event
          )
        );
      }}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

Event form

Click a day cell to create a new event, or click an existing event to edit it. Use withDragSlotSelect and onSlotDragEnd to allow drag-to-create across day cells. The onSlotDragEnd callback includes the resourceId of the resource where the drag started.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
import dayjs from 'dayjs';
import { useState } from 'react';
import { Select } from '@mantine/core';
import { ResourcesMonthView, ScheduleEventData } from '@mantine/schedule';
import { EventData, EventForm } from './EventForm';
import { events as initialEvents, resources } from './data';

function Demo() {
  const [date, setDate] = useState(dayjs().format('YYYY-MM-DD'));
  const [events, setEvents] = useState<ScheduleEventData[]>(initialEvents);
  const [formOpened, setFormOpened] = useState(false);
  const [selectedEventData, setSelectedEventData] = useState<EventData | null>(null);
  const [selectedResourceId, setSelectedResourceId] = useState<string | null>(null);

  const handleDayClick = ({
    date: clickedDate,
    resourceId,
  }: {
    date: string;
    nativeEvent: React.MouseEvent<HTMLButtonElement>;
    resourceId?: string | number;
  }) => {
    setSelectedResourceId(resourceId ? String(resourceId) : null);
    setSelectedEventData({
      title: '',
      start: dayjs(clickedDate).startOf('day').toDate(),
      end: dayjs(clickedDate).endOf('day').toDate(),
      color: 'blue',
    });
    setFormOpened(true);
  };

  const handleEventClick = (event: ScheduleEventData) => {
    setSelectedResourceId(event.resourceId ? String(event.resourceId) : null);
    setSelectedEventData({
      id: event.id,
      title: event.title,
      start: new Date(event.start),
      end: new Date(event.end),
      color: event.color || 'blue',
    });
    setFormOpened(true);
  };

  const handleSlotDragEnd = ({
    rangeStart,
    rangeEnd,
    resourceId,
  }: {
    rangeStart: string;
    rangeEnd: string;
    resourceId?: string | number;
  }) => {
    setSelectedResourceId(resourceId ? String(resourceId) : null);
    setSelectedEventData({
      title: '',
      start: new Date(rangeStart),
      end: new Date(rangeEnd),
      color: 'blue',
    });
    setFormOpened(true);
  };

  const handleSubmit = (values: EventData) => {
    if (values.id) {
      setEvents((prev) =>
        prev.map((event) =>
          event.id === values.id
            ? {
                ...event,
                title: values.title,
                start: dayjs(values.start).toISOString(),
                end: dayjs(values.end).toISOString(),
                color: values.color || 'blue',
                resourceId: selectedResourceId || event.resourceId,
              }
            : event
        )
      );
    } else {
      setEvents((prev) => [
        ...prev,
        {
          id: Math.random().toString(36).substring(2, 11),
          title: values.title,
          start: dayjs(values.start).toISOString(),
          end: dayjs(values.end).toISOString(),
          color: values.color || 'blue',
          resourceId: selectedResourceId || undefined,
        },
      ]);
    }
  };

  const handleDeleteEvent = () => {
    if (selectedEventData?.id) {
      setEvents((prev) => prev.filter((e) => e.id !== selectedEventData.id));
    }
  };

  return (
    <>
      <ResourcesMonthView
        date={date}
        onDateChange={setDate}
        resources={resources}
        events={events}
        withDragSlotSelect
        onDayClick={handleDayClick}
        onSlotDragEnd={handleSlotDragEnd}
        onEventClick={handleEventClick}
        startScrollDate={dayjs().format('YYYY-MM-DD')}
      />

      <EventForm
        opened={formOpened}
        onClose={() => setFormOpened(false)}
        onExitTransitionEnd={() => setSelectedEventData(null)}
        values={selectedEventData}
        onSubmit={handleSubmit}
        onDelete={selectedEventData?.id ? handleDeleteEvent : undefined}
      >
        <Select
          label="Resource"
          placeholder="Select resource"
          radius="md"
          data={resources.map((r) => ({ value: String(r.id), label: r.label }))}
          value={selectedResourceId}
          onChange={setSelectedResourceId}
        />
      </EventForm>
    </>
  );
}

Custom event rendering

Use renderEvent prop to customize how events are rendered. The example below uses HoverCard to display event details on hover.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
import dayjs from 'dayjs';
import { useState } from 'react';
import { HoverCard, UnstyledButton } from '@mantine/core';
import { ResourcesMonthView, ScheduleEventData } from '@mantine/schedule';
import { EventDetails } from './EventDetails';
import { events as initialEvents, resources } from './data';

function Demo() {
  const [date, setDate] = useState(dayjs().format('YYYY-MM-DD'));
  const [events, setEvents] = useState<ScheduleEventData[]>(initialEvents);

  return (
    <ResourcesMonthView
      date={date}
      onDateChange={setDate}
      resources={resources}
      events={events}
      withEventsDragAndDrop
      onEventDrop={({ eventId, newStart, newEnd, resourceId }) => {
        setEvents((current) =>
          current.map((event) =>
            event.id === eventId
              ? { ...event, start: newStart, end: newEnd, resourceId }
              : event
          )
        );
      }}
      renderEvent={(event, props) => (
        <HoverCard width={280} position="right" closeDelay={0} transitionProps={{ duration: 0 }}>
          <HoverCard.Target>
            <UnstyledButton {...props} />
          </HoverCard.Target>
          <HoverCard.Dropdown>
            <EventDetails event={event} resources={resources} />
          </HoverCard.Dropdown>
        </HoverCard>
      )}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

Custom resource label

Use renderResourceLabel prop to customize how resource labels are rendered in the row headers.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30

Meeting room: Tokyo

Office

Meeting room: Paris

Office

Meeting room: New York

Office

import dayjs from 'dayjs';
import { useState } from 'react';
import { Stack, Text } from '@mantine/core';
import { ResourcesMonthView, ScheduleResourceData } 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}
      renderResourceLabel={(resource: ScheduleResourceData) => (
        <Stack gap={0} align="flex-start">
          <Text fw={600} size="sm">
            {resource.label}
          </Text>
          <Text size="xs" c="dimmed">
            Office
          </Text>
        </Stack>
      )}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

Resource groups

Use groups prop to group resources under labeled headers. The group labels are displayed as a column to the left of resource labels, spanning vertically across their resources. Use renderGroupLabel to customize group label rendering and groupLabelWidth to control the group column width.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Floor 1
Meeting room: Tokyo
Meeting room: Paris
Floor 2
Meeting room: New York
Overflow room
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesMonthView, ScheduleResourceGroup } from '@mantine/schedule';
import { events } from './data';

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

const groups: ScheduleResourceGroup[] = [
  { label: 'Floor 1', resourceIds: ['tokyo', 'paris'] },
  { label: 'Floor 2', resourceIds: ['new-york'] },
];

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

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

Localization

Set locale prop to change the language. Use labels prop to override built-in labels.

Recursos
lun.1
mar.2
mié.3
jue.4
vie.5
sáb.6
dom.7
lun.8
mar.9
mié.10
jue.11
vie.12
sáb.13
dom.14
lun.15
mar.16
mié.17
jue.18
vie.19
sáb.20
dom.21
lun.22
mar.23
mié.24
jue.25
vie.26
sáb.27
dom.28
lun.29
mar.30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
import 'dayjs/locale/es';

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}
      locale="es"
      labels={{
        day: 'Día',
        week: 'Semana',
        month: 'Mes',
        year: 'Año',
        today: 'Hoy',
        previous: 'Anterior',
        next: 'Siguiente',
        more: 'Más',
        resources: 'Recursos',
        moreLabel: (hiddenEventsCount) => `+${hiddenEventsCount} más`,
      }}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

Recurring events

ResourcesMonthView automatically expands recurring events for the visible month. See Recurring events guide for full documentation.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesMonthView } from '@mantine/schedule';

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

const resources = [
  { id: 'tokyo', label: 'Meeting room: Tokyo' },
  { id: 'paris', label: 'Meeting room: Paris' },
];

const events = [
  {
    id: 'daily-sync-series',
    title: 'Daily sync (series)',
    start: `${dayjs(today).subtract(2, 'day').format('YYYY-MM-DD')} 09:00:00`,
    end: `${dayjs(today).subtract(2, 'day').format('YYYY-MM-DD')} 09:30:00`,
    color: 'blue',
    resourceId: 'tokyo',
    recurrence: {
      rrule: 'FREQ=DAILY;COUNT=10',
      exdate: [`${today} 09:00:00`],
    },
  },
  {
    id: 'daily-sync-override',
    title: 'Daily sync (moved today)',
    start: `${today} 14:00:00`,
    end: `${today} 14:30:00`,
    color: 'grape',
    resourceId: 'tokyo',
    recurringEventId: 'daily-sync-series',
    recurrenceId: `${today} 09:00:00`,
  },
  {
    id: 'one-off',
    title: 'One-off planning',
    start: `${today} 11:00:00`,
    end: `${today} 12:00:00`,
    color: 'green',
    resourceId: 'paris',
  },
];

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

  return (
    <ResourcesMonthView
      date={date}
      onDateChange={setDate}
      resources={resources}
      events={events}
      startScrollDate={today}
    />
  );
}

Max events per cell

Use maxEventsPerTimeSlot prop to limit the number of events visible in each cell. When there are more events than the limit, a "+more" indicator is shown.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesMonthView, ScheduleEventData, 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' },
];

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

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

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

Day width and row height

Use dayWidth and rowHeight props to customize the dimensions of day columns and resource rows.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
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}
      dayWidth={60}
      rowHeight={64}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

Start scroll date

Use startScrollDate prop to scroll to a specific date on initial render. This is useful when the month has many days and you want the view to start at a specific date, for example today.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
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')}
    />
  );
}

Without weekend days

Set withWeekendDays={false} to hide weekend day columns from the month grid.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Mon8
Tue9
Wed10
Thu11
Fri12
Mon15
Tue16
Wed17
Thu18
Fri19
Mon22
Tue23
Wed24
Thu25
Fri26
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
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}
      withWeekendDays={false}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

More events indicator

When a day cell has more events than maxEventsPerTimeSlot, a "+X more" indicator is shown. Click the indicator to see all events for that day.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesMonthView, ScheduleEventData, 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' },
];

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

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

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

More events props

Use moreEventsProps to customize the more events dropdown, for example to use a modal instead of a popover.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
import dayjs from 'dayjs';
import { useState } from 'react';
import { ResourcesMonthView, ScheduleEventData, 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' },
];

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

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

  return (
    <ResourcesMonthView
      date={date}
      onDateChange={setDate}
      resources={resources}
      events={events}
      maxEventsPerTimeSlot={2}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
      moreEventsProps={{ dropdownType: 'modal', modalTitle: 'All Events' }}
    />
  );
}

Custom header

Set withHeader={false} to hide the default header and use ScheduleHeader to build a custom header with navigation controls.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
import dayjs from 'dayjs';
import { useState } from 'react';
import { DateStringValue, ResourcesMonthView, ScheduleHeader } from '@mantine/schedule';
import { events, resources } from './data';

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

  return (
    <div>
      <ScheduleHeader>
        <ScheduleHeader.Previous
          onClick={() =>
            setDate(
              dayjs(date)
                .subtract(1, 'month')
                .startOf('month')
                .format('YYYY-MM-DD') as DateStringValue
            )
          }
        />
        <ScheduleHeader.MonthYearSelect
          yearValue={dayjs(date).year()}
          monthValue={dayjs(date).month()}
          onYearChange={(year) =>
            setDate(
              dayjs(date)
                .year(year)
                .startOf('month')
                .format('YYYY-MM-DD') as DateStringValue
            )
          }
          onMonthChange={(month) =>
            setDate(
              dayjs(date)
                .month(month)
                .startOf('month')
                .format('YYYY-MM-DD') as DateStringValue
            )
          }
        />
        <ScheduleHeader.Next
          onClick={() =>
            setDate(
              dayjs(date)
                .add(1, 'month')
                .startOf('month')
                .format('YYYY-MM-DD') as DateStringValue
            )
          }
        />
        <ScheduleHeader.Today
          onClick={() =>
            setDate(
              dayjs().format('YYYY-MM-DD') as DateStringValue
            )
          }
        />
      </ScheduleHeader>

      <ResourcesMonthView
        date={date}
        onDateChange={setDate}
        resources={resources}
        events={events}
        withHeader={false}
      />
    </div>
  );
}

Radius

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
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}
      radius="md"
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}

Scroll area props

Use scrollAreaProps to customize the scroll area behavior.

Resources
Mon1
Tue2
Wed3
Thu4
Fri5
Sat6
Sun7
Mon8
Tue9
Wed10
Thu11
Fri12
Sat13
Sun14
Mon15
Tue16
Wed17
Thu18
Fri19
Sat20
Sun21
Mon22
Tue23
Wed24
Thu25
Fri26
Sat27
Sun28
Mon29
Tue30
Meeting room: Tokyo
Meeting room: Paris
Meeting room: New York
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}
      scrollAreaProps={{
        scrollbarSize: 10,
        offsetScrollbars: true,
        type: 'always',
        scrollbars: 'x',
      }}
      startScrollDate={dayjs().format('YYYY-MM-DD')}
    />
  );
}