AdminKitDocs
Plugins

React FullCalendar

React FullCalendar in AdminKit PRO: FullCalendar 7 with month, week and day views, drag and drop events and Bootstrap buttons, in light and dark mode.

Pro

This component is only available in AdminKit PRO. Learn more.

Use FullCalendar to show meetings, deadlines and time off in a month, week or day view. With editable on, people can drag an event to another day or resize it. The calendar follows light and dark mode, and its toolbar uses Bootstrap's btn btn-primary buttons.

FullCalendar is a React component around FullCalendar 7 (@fullcalendar/react 7.1.3), set up for AdminKit for React. It comes with the day grid, time grid and interaction plugins of FullCalendar. It uses FullCalendar's classic theme.

FullCalendar is a large library, so the component loads it and its plugins with React.lazy. Vite keeps them out of the main bundle, and the browser only fetches them on the first page that shows a calendar. Until then, a skeleton about the size of the month view (aspect ratio 1.25) keeps the card at its height. FullCalendar's stylesheets are part of app.scss.

Example

The props are FullCalendar's options. The demo events below fill the current month view, so the example always has something to show.

import { useState } from "react";
import { type EventInput, FullCalendar } from "@/components/plugins/fullcalendar";

const today = new Date();
const first = new Date(today.getFullYear(), today.getMonth(), 1);

// day(2, 1, "10:00:00"): the Monday of the third row of the month view at 10 am
const day = (week: number, weekday: number, time?: string) => {
  const value = new Date(
    first.getFullYear(),
    first.getMonth(),
    1 - first.getDay() + week * 7 + weekday
  );
  const text = [
    value.getFullYear(),
    String(value.getMonth() + 1).padStart(2, "0"),
    String(value.getDate()).padStart(2, "0"),
  ].join("-");
  return time ? `${text}T${time}` : text;
};

export function TeamCalendar() {
  const [events] = useState<EventInput[]>(() => [
    { title: "Sprint planning", start: day(0, 1, "10:00:00"), end: day(0, 1, "11:30:00"), className: "calendar-event-primary" },
    { title: "Q4 roadmap due", start: day(1, 4), className: "calendar-event-danger" },
    { title: "Web Summit, Lisbon", start: day(2, 2), end: day(2, 5), className: "calendar-event-success" },
    { title: "Fiona Green out", start: day(3, 4), className: "calendar-event-warning" },
  ]);

  return (
    <FullCalendar
      initialView="dayGridMonth"
      todayHint="Today"
      headerToolbar={{
        left: "prev,next today",
        center: "title",
        right: "dayGridMonth,timeGridWeek,timeGridDay",
      }}
      editable
      eventDisplay="block"
      eventClass="calendar-event"
      events={events}
    />
  );
}

Keep events in state, as the demo does, or outside the component. That way FullCalendar gets the same array on every render.

Props

FullCalendarProps is FullCalendar's CalendarOptions plus a ref. See FullCalendar's options for the full list. The component is in src/components/plugins/fullcalendar.tsx.

PropTypeDefaultDescription
initialViewstring"dayGridMonth", "timeGridWeek", "timeGridDay", ...
eventsEventInput[]The events: title, start, end, className, ...
editablebooleanEvents can be dragged and resized
headerToolbarobjectThe buttons and title of the toolbar
pluginsPluginInput[]Plugins to add to the built-in ones; keep it a stable array
refRef<CalendarRef>ref.current.getApi() returns FullCalendar's Calendar API

You don't pass the built-in plugins yourself. They are the day grid, the time grid, the interaction plugin and a Bootstrap theme on top of the classic theme. The interaction plugin handles dragging, resizing and clicking dates. The module also exports the CalendarOptions, CalendarRef and EventInput types.

Event colors

Colors help people tell meetings from deadlines at a glance. Give an event the class calendar-event, through eventClass as above, and a category class: calendar-event-primary, -success, -warning, -danger or -info. The event becomes a tinted chip with a colored left edge, in light and dark mode. For a legend, calendar-swatch with the same category class draws a small square of that color:

<ul className="list-inline small text-body-secondary mb-0" aria-label="Event categories">
  <li className="list-inline-item me-3">
    <span className="calendar-swatch calendar-event-primary me-1" />
    Meetings
  </li>
  <li className="list-inline-item me-0">
    <span className="calendar-swatch calendar-event-danger me-1" />
    Deadlines
  </li>
</ul>

The calendar demo also shades the weekends: it returns calendar-weekend from dayCellClass and dayLaneClass. It marks today's date by returning calendar-today-number from dayCellTopInnerClass. To change the colors of the theme, edit the --fc-classic-* custom properties in src/scss/5-vendor/_fullcalendar.scss.

Calendar API

To control the calendar from your own code, such as switching views from your own buttons, use FullCalendar's Calendar API. A ref gives it to you through getApi():

import { useRef } from "react";
import {
  type CalendarRef,
  type EventInput,
  FullCalendar,
} from "@/components/plugins/fullcalendar";

export function WeekCalendar({ events }: { events: EventInput[] }) {
  const calendar = useRef<CalendarRef>(null);

  return (
    <>
      <button
        type="button"
        className="btn btn-light mb-3"
        onClick={() => calendar.current?.getApi().changeView("timeGridWeek")}
      >
        Week
      </button>
      <FullCalendar ref={calendar} initialView="dayGridMonth" events={events} />
    </>
  );
}

Accessibility

  • todayHint="Today" gives the today button an accessible name that matches its text.
  • Don't let color be an event's only label. Keep the category in the title or a legend, and give the legend an aria-label, as above.
  • The toolbar buttons are Bootstrap buttons, focusable and usable with the keyboard.

Last updated on

On this page