chore(calendar): upgrade FullCalendar v6 → v7 (@fullcalendar/angular 7.0.1) — new theme system, package restructure, API renames #724

Closed
opened 2026-07-19 22:56:42 +00:00 by spikerj · 2 comments
Owner

Why

FullCalendar released v7.0.1 (major). Our calendar (projects/spikersoft/src/app/_components/calendar/) is on @fullcalendar/* 6.1.21. v7 brings a formal theme system, a slimmer DOM (no nested <table>s), better performance (less layout thrashing, fewer event rerenders), accessibility (all views pass Axe), improved print view, and built-in named-timezone support via Temporal — but it restructures packages and renames a chunk of the API.

Upgrade guide: https://fullcalendar.io/docs/upgrading-from-v6

What changes for us (audit of our usage)

1. Dependencies (package.json)

v7 moves all standard plugins into connector entrypoints. The six v6 packages are replaced:

Remove (v6) Add (v7)
@fullcalendar/core 6.1.21 fullcalendar 7.0.1 (peer of the connector; never imported directly in Angular)
@fullcalendar/daygrid, /timegrid, /list, /interaction, /multimonth 6.1.21 gone — now @fullcalendar/angular/daygrid, /timegrid, /list, /interaction, /multimonth entrypoints
@fullcalendar/angular 6.1.21 @fullcalendar/angular 7.0.1
temporal-polyfill ^1.0.1 (new required peer dep, tree-shakeable)

Angular 22.0.6 is inside the supported range (16–22). ESM-only distribution is fine (Node 22, Vite/Vitest).

2. Theme system (breaking): CSS no longer bundled

v7 ships no baked-in CSS; a theme plugin + stylesheets must be added explicitly. We'll use the Classic theme (keeps the v6 look, minimal visual churn):

  • add themePlugin from @fullcalendar/angular/themes/classic to calendarOptions.plugins
  • add to projects/spikersoft/project.json build styles: @fullcalendar/angular/skeleton.css + the classic theme css
  • note: v7 classic no longer bolds day-grid column headers by default; header toolbar button labels render capitalized ("Today" vs "today")

We have zero fc-* / --fc-* custom CSS anywhere in the repo (audited), so the CSS-migration surface is just the theme wiring.

3. API renames in calendar.component.ts

  • imports: types (CalendarOptions, EventApi, DateSelectArg, …) move from @fullcalendar/core@fullcalendar/angular; plugins from @fullcalendar/<plugin>@fullcalendar/angular/<plugin>
  • Event API + EventInput field renames (breaking):
    • classNamesclassName (string) — affects transformToEventInput() and the reminder-highlight setProp("classNames", …) logic
    • backgroundColor/borderColorcolor
    • textColorcontrastColor
    • affects buildUpdateRequestFromEvent() (issue #109 color-preservation on drag/resize), handleEventClick, openEditModal, updateSpecificEvent, getCurrentEvents — the backend contract (FullCalendarEvent / CreateUpdateCalendarEventRequest) keeps its field names; only the FullCalendar-facing mapping layer changes
  • day-scheduler.component.ts: DateSelectArg import moves to @fullcalendar/angular

4. Deprecations / dead code to drop

  • DynamicLoadersService.loadFullCalendar() dynamically imports the six v6 packages — those package names won't exist anymore, and nothing calls it (the calendar imports plugins statically and is already route-lazy). Drop the FullCalendar branch of the loader.

5. Not affected (audited)

  • headerToolbar is explicitly configured (v7 disables it by default — ours keeps working); no customButtons/buttonText/buttonIcons
  • no windowResize/updateSize/stickyHeaderDates/slotLabel*/dayCellContent/moreLinkClick usage
  • no Luxon/Moment/iCalendar/premium plugins; timeZone: "local" unchanged
  • eventContent ng-template still supported by the v7 connector

Acceptance criteria

  • deps swapped per table above, lockfile updated, app builds
  • classic theme plugin + skeleton/theme CSS wired; calendar visually renders month/week/day/list/multi-month views with header toolbar
  • event create/click/edit/delete, drag & resize keep working — including color preservation on partial updates (#109 regression guard in calendar.component.spec.ts stays green with renamed fields)
  • reminder highlight (SignalR) works with className string semantics
  • dead FullCalendar dynamic-loader branch removed
  • nx test spikersoft calendar specs + pnpm typecheck + lint green
## Why FullCalendar released **v7.0.1** (major). Our calendar (`projects/spikersoft/src/app/_components/calendar/`) is on `@fullcalendar/* 6.1.21`. v7 brings a formal theme system, a slimmer DOM (no nested `<table>`s), better performance (less layout thrashing, fewer event rerenders), accessibility (all views pass Axe), improved print view, and built-in named-timezone support via Temporal — but it restructures packages and renames a chunk of the API. Upgrade guide: https://fullcalendar.io/docs/upgrading-from-v6 ## What changes for us (audit of our usage) ### 1. Dependencies (`package.json`) v7 moves all standard plugins into connector entrypoints. The six v6 packages are **replaced**: | Remove (v6) | Add (v7) | |---|---| | `@fullcalendar/core` 6.1.21 | `fullcalendar` 7.0.1 (peer of the connector; never imported directly in Angular) | | `@fullcalendar/daygrid`, `/timegrid`, `/list`, `/interaction`, `/multimonth` 6.1.21 | gone — now `@fullcalendar/angular/daygrid`, `/timegrid`, `/list`, `/interaction`, `/multimonth` entrypoints | | `@fullcalendar/angular` 6.1.21 | `@fullcalendar/angular` 7.0.1 | | — | `temporal-polyfill` ^1.0.1 (new required peer dep, tree-shakeable) | Angular 22.0.6 is inside the supported range (16–22). ESM-only distribution is fine (Node 22, Vite/Vitest). ### 2. Theme system (breaking): CSS no longer bundled v7 ships no baked-in CSS; a theme **plugin** + stylesheets must be added explicitly. We'll use the **Classic** theme (keeps the v6 look, minimal visual churn): - add `themePlugin` from `@fullcalendar/angular/themes/classic` to `calendarOptions.plugins` - add to `projects/spikersoft/project.json` build styles: `@fullcalendar/angular/skeleton.css` + the classic theme css - note: v7 classic no longer bolds day-grid column headers by default; header toolbar button labels render capitalized ("Today" vs "today") We have **zero** `fc-*` / `--fc-*` custom CSS anywhere in the repo (audited), so the CSS-migration surface is just the theme wiring. ### 3. API renames in `calendar.component.ts` - imports: types (`CalendarOptions`, `EventApi`, `DateSelectArg`, …) move from `@fullcalendar/core` → `@fullcalendar/angular`; plugins from `@fullcalendar/<plugin>` → `@fullcalendar/angular/<plugin>` - Event API + EventInput field renames (breaking): - `classNames` → `className` (string) — affects `transformToEventInput()` and the reminder-highlight `setProp("classNames", …)` logic - `backgroundColor`/`borderColor` → `color` - `textColor` → `contrastColor` - affects `buildUpdateRequestFromEvent()` (issue #109 color-preservation on drag/resize), `handleEventClick`, `openEditModal`, `updateSpecificEvent`, `getCurrentEvents` — the **backend contract** (`FullCalendarEvent` / `CreateUpdateCalendarEventRequest`) keeps its field names; only the FullCalendar-facing mapping layer changes - `day-scheduler.component.ts`: `DateSelectArg` import moves to `@fullcalendar/angular` ### 4. Deprecations / dead code to drop - `DynamicLoadersService.loadFullCalendar()` dynamically imports the six v6 packages — those package names won't exist anymore, and **nothing calls it** (the calendar imports plugins statically and is already route-lazy). Drop the FullCalendar branch of the loader. ### 5. Not affected (audited) - `headerToolbar` is explicitly configured (v7 disables it by default — ours keeps working); no `customButtons`/`buttonText`/`buttonIcons` - no `windowResize`/`updateSize`/`stickyHeaderDates`/`slotLabel*`/`dayCellContent`/`moreLinkClick` usage - no Luxon/Moment/iCalendar/premium plugins; `timeZone: "local"` unchanged - `eventContent` ng-template still supported by the v7 connector ## Acceptance criteria - [ ] deps swapped per table above, lockfile updated, app builds - [ ] classic theme plugin + skeleton/theme CSS wired; calendar visually renders month/week/day/list/multi-month views with header toolbar - [ ] event create/click/edit/delete, drag & resize keep working — including color preservation on partial updates (#109 regression guard in `calendar.component.spec.ts` stays green with renamed fields) - [ ] reminder highlight (SignalR) works with `className` string semantics - [ ] dead FullCalendar dynamic-loader branch removed - [ ] `nx test spikersoft` calendar specs + `pnpm typecheck` + lint green
Author
Owner

Worked in spikerj/spikersoft-angular#445 (branch chore/724-fullcalendar-v7).

All acceptance criteria addressed:

  • deps swapped (@fullcalendar/angular + fullcalendar 7.0.1, temporal-polyfill peer), lockfile updated, dev build green
  • Classic theme plugin + skeleton.css/theme.css/palette.css wired into project.json styles
  • v7 API renames applied at the FullCalendar-facing mapping layer only; #109 color-preservation spec updated to the v7 event shape and passing
  • reminder highlight migrated to className string semantics
  • dead loadFullCalendar() dynamic-loader branch removed
  • 17/17 calendar tests, ESLint and Prettier clean

One thing to eyeball after deploy: v7's Classic theme is intentionally close to v6 but not pixel-identical (more spacious layout, capitalized toolbar buttons, non-bold day-grid headers). If we'd rather lean into the new look, swapping to the Monarch/Forma/Breezy/Pulse themes is a two-line change.

Worked in spikerj/spikersoft-angular#445 (branch `chore/724-fullcalendar-v7`). All acceptance criteria addressed: - deps swapped (`@fullcalendar/angular` + `fullcalendar` 7.0.1, `temporal-polyfill` peer), lockfile updated, dev build green - Classic theme plugin + `skeleton.css`/`theme.css`/`palette.css` wired into `project.json` styles - v7 API renames applied at the FullCalendar-facing mapping layer only; #109 color-preservation spec updated to the v7 event shape and passing - reminder highlight migrated to `className` string semantics - dead `loadFullCalendar()` dynamic-loader branch removed - 17/17 calendar tests, ESLint and Prettier clean One thing to eyeball after deploy: v7's Classic theme is intentionally close to v6 but not pixel-identical (more spacious layout, capitalized toolbar buttons, non-bold day-grid headers). If we'd rather lean into the new look, swapping to the Monarch/Forma/Breezy/Pulse themes is a two-line change.
Author
Owner

Done and merged to master. Closing.

Verified on master: @fullcalendar/angular ^7.0.1, fullcalendar 7.0.1, temporal-polyfill ^1.0.1. All acceptance criteria addressed per the PR. Ticket stayed open only because cross-repo merges don't auto-close tracker issues.

Done and merged to `master`. Closing. - spikerj/spikersoft-angular#445 — the v6→v7 upgrade (merge commit `54f2c98412f8`, merged 2026-07-19) - spikerj/spikersoft-angular#446 — follow-up: exempt FullCalendar 7.0.1 from pnpm `minimumReleaseAge` (merge commit `f8fbe814d8e4`, merged 2026-07-20) Verified on `master`: `@fullcalendar/angular` ^7.0.1, `fullcalendar` 7.0.1, `temporal-polyfill` ^1.0.1. All acceptance criteria addressed per the PR. Ticket stayed open only because cross-repo merges don't auto-close tracker issues.
Sign in to join this conversation.