# Kalendar: standalone Compose calendar views with a matching event model

> Kalendar is an Apache-2.0 Kotlin library of calendar composables for Jetpack Compose and Compose Multiplatform, published as com.himanshoe:kalendar with a separate foundation module for the event model. Version 2 removed the single Kalendar entry point in favour of separate month, week, year, timeline, schedule and agenda views.

**hi-manshu/kalendar** — Kalendar is no ordinary library — it’s the Elder Wand of calendar components, crafted for Compose (now with KMP support) sorcerers who demand both power and elegance. With the flick of your wrist (or a few lines of Kotlin), you conjure a magical, interactive calendar that bends to your will. With Kalendar, your app becomes as organized as Hermione

- Repository: https://github.com/hi-manshu/kalendar
- Website: https://hi-manshu.github.io/kalendar/
- Stars: 924 · Forks: 73
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/hi-manshu-kalendar

## Seven separate composables instead of one configurable widget

The structural decision in Kalendar 2.0 is that there is no single entry point. The README is explicit: there is no Kalendar(type = ...) entry point and no KalendarType, because both were removed in 2.0. Instead every view is a top-level composable you call directly, such as KalendarMonth(...) or KalendarAgenda(...). The catalogue of views is specific. KalendarMonth is a full month grid, KalendarWeek a single week row, and KalendarYear a 12-month overview. KalendarTimeline is described as a continuous, boundless vertical scroll through every month with no paging. KalendarSchedule is an hourly time grid for one day with duration-sized event blocks, overlap packing and a now-indicator, and KalendarScheduleWeek is the 7-day variant where day columns share one hour gutter. KalendarAgenda is a scrollable list of events grouped by date, with no grid and no paging. For a product that needs an agenda on one screen and a month grid on another, this set covers the common shapes rather than forcing one compromise widget.

## Every view takes arrow clicks and swipes, which decides how you wire gestures

Across the view list the same navigation contract repeats: month, week and year each get arrow-click and swipe navigation together, and the timeline deliberately drops paging in favour of unbounded scrolling. That pairing matters more than it sounds. A view that only supports arrows forces you to build a swipe gesture yourself on top, and a view that only supports swipe leaves the accessibility story thin, because a swipe-only calendar is unusable with VoiceOver or Switch Control. Shipping both means the gesture layer is already handled. The timeline's no-paging choice is the interesting outlier, since it trades page boundaries for a long list, which suits an agenda feed and does not suit a view where you need to jump to an arbitrary month. The README also notes that adjacent pages are prefetched during a swipe so the gesture does not land on an empty grid, which is the kind of detail that separates a considered navigation implementation from a naive one.

## The event model lives in a separate foundation artifact

Kalendar does not define its own event type in the view module. The views use the event model from kalendar-foundation, with KalendarEvent and BasicKalendarEvent, and kalendar re-exports that foundation as an api dependency, which means adding com.himanshoe:kalendar alone is enough for the common case. This split has a practical consequence for a project with an existing domain model: if your events already come from a backend as your own type, the foundation module is the seam where you map into BasicKalendarEvent rather than wrapping the whole view in adapters. The foundation artifact is published separately as com.himanshoe:kalendar-foundation, and the version catalog snippet in the README lists kalendar, kalendarFoundation and kalendarSync as three distinct coordinates, which tells you the maintainer intends them to be consumed independently.

## Adding the dependency, and calling one composable

Adding the library is the whole setup. With a Version Catalog you declare three coordinates in libs.versions.toml:

```toml
[versions]
kalendar = "<version>"
kalendarFoundation = "<version>"
kalendarSync = "<version>"

[libraries]
kalendar = { module = "com.himanshoe:kalendar", version.ref = "kalendar" }
kalendar-foundation = { module = "com.himanshoe:kalendar-foundation", version.ref = "kalendarFoundation" }
kalendar-sync = { module = "com.himanshoe:kalendar-sync", version.ref = "kalendarSync" }
```

In a plain Gradle module you write the coordinates directly instead:

```gradle
dependencies {
    implementation("com.himanshoe:kalendar:$version")
    implementation("com.himanshoe:kalendar-foundation:$version")
    implementation("com.himanshoe:kalendar-sync:$version") // optional: device calendar sync

    // if you're using Version Catalog
    implementation(libs.kalendar)
    implementation(libs.kalendar.foundation)
    implementation(libs.kalendar.sync)

}
```

For a Kotlin Multiplatform project the same three libraries go into the commonMain source set:

```gradle
sourceSets {
    commonMain.dependencies {
          implementation(libs.kalendar)
          implementation(libs.kalendar.foundation)
          implementation(libs.kalendar.sync) // optional: device calendar sync
     }
}
```

Only the first artifact is required for the views, since kalendar re-exports the foundation event model as an api dependency. After the dependency resolves, your first real use is one composable call: pass your events and a range to KalendarMonth or KalendarAgenda, and if the events come from a network call, supply the range and fill the loadingContent slot.

## Events arrive up front or by visible range, and loadingContent covers the gap

There are two ways to feed a view. Events can be handed over up front as a list, which suits a small in-memory set. Or they can be loaded a visible range at a time, for the case where they live in a database or behind a network call. In the range mode the view reports the range it is about to draw, adjacent pages are prefetched so a swipe does not land on an empty grid, and a loadingContent slot keeps no events yet from looking like no events. That last detail is the one worth copying into your own component design. The failure mode it avoids is specific and common: a calendar that shows an empty grid while the query is still in flight reads as a calendar with no events, and users report that as missing data. The view tells you what it wants and lets you supply the placeholder, which is the only workable arrangement for an asynchronous source.

## Theming runs through colour tokens rather than Google's design system dependency

All views are restylable through KalendarTheme colour tokens, and the README stresses that no dependency on Google's design system for Android is required in your app. That is a deliberate constraint, and it matters for two kinds of project. A Compose Multiplatform app targeting platforms other than Android may not want to carry an Android-specific design system into their codebase, and a product with its own established palette may want the calendar to match rather than approximate. The cost of the choice is that you are on your own for anything the token set does not cover, and the README does not enumerate every token, so the theming documentation page is the reference you need. Note also that the repository ships detekt.yml, a static analysis configuration, which suggests the library is held to lint rules rather than left to drift.

## Device calendar sync is a separate module with its own scope semantics

kalendar-sync is independent of both kalendar and kalendar-foundation, and that independence is deliberate. It reads, writes and exports events from the device's real calendar, using Android CalendarContract, iOS EventKit, and a file-backed .ics provider on Desktop, with no third-party account required. It includes RFC 5545 recurrence handling and iCal import and export. The part worth attention is edit scope on recurring events: you can edit or delete at one occurrence, this and following, or the whole series, and each scope resolves to an explicit set of writes, so you can see exactly what your backend will be asked to do. Making the write set explicit matters because the alternative, silently widening a one-occurrence edit into the whole series, is a data loss bug that is very hard to notice after the fact.

## Apache-2.0 terms, a live demo, and a release candidate holding the 2.0 API

The licence field is Apache-2.0, with a LICENSE.txt at the repository root, which is a permissive grant that includes an express patent licence and does not impose copyleft on code that merely depends on it. The release history is the part to note before adopting. The newest tagged release is 2.0.0-RC1 published on 2025-03-14, which is a release candidate rather than a stable 2.0.0, and before it v1.3.2 from 2023-06-05 and 1.3.1 from 2023-05-17. Meanwhile the last push to the repository was on 2026-10-20 and the default branch is main, so there is a large amount of work on main that has not been cut as a tagged release. If you pin to 2.0.0-RC1 you get the new API with the removed Kalendar entry point, but you also pin to a March 2025 snapshot. Reading the CHANGELOG in the repository before choosing a version is the concrete first step. The project publishes its own documentation site, and the deployment is described in enough detail to be useful: the live demo runs every view in your browser through a Compose for Web and wasm build of the sample app, deployed from main by the Deploy Demo workflow, and the same deployment publishes the Dokka API reference under /api/kalendar/ and /api/kalendar-foundation/. That means you can evaluate all seven views without writing a line of Kotlin, which is a reasonable way to decide whether the visual design fits before you commit to the dependency. The library itself is on Maven Central under com.himanshoe:kalendar, with kalendar-foundation as a second artifact. The repository layout shows the modules as directories, kalendar, kalendar-foundation and kalendar-sync, plus a sample app, an iosApp directory, a docsite, a kotlin-js-store and a CHANGELOG.

## Conclusion

Kalendar suits a Compose team that needs a calendar surface now and wants control over colour tokens rather than a design system default, and its separate views make it a reasonable fit for agenda, schedule and year overview screens that most libraries give you only one of. It does not suit a project that wants a single drop-in widget with the old 1.x API, because the Kalendar type and KalendarType were removed in 2.0, and the 2.0.0-RC1 build is the newest tagged release, so pin carefully. Before you adopt it, read the theme documentation to see how much of the default look you have to replace, and check the sync module separately, since device calendar access sits in kalendar-sync and is independent of the view library.

## FAQ

### How do I add the Kalendar dependency to an Android project?

Add the artifacts to your module's build.gradle.kts. The README lists com.himanshoe:kalendar, com.himanshoe:kalendar-foundation and the optional com.himanshoe:kalendar-sync, or the equivalent Version Catalog entries from libs.versions.toml.

### What happened to Kalendar(type = ...) in version 2.0?

Both the Kalendar entry point and KalendarType were removed in 2.0. Every view is now a top-level composable you call directly, such as KalendarMonth(...) or KalendarAgenda(...).

### Does Kalendar support Compose Multiplatform?

Yes. The README describes the library as Compose with KMP support and gives a commonMain source set dependency block for Kotlin Multiplatform, alongside an Android build.gradle.kts block. The sample app is also built for the web with wasm.

### Can Kalendar read and write the device calendar?

Yes, through the separate kalendar-sync module, which uses Android CalendarContract, iOS EventKit and a file-backed .ics provider on Desktop. It handles RFC 5545 recurrence and iCal import and export, and it is independent of the kalendar and kalendar-foundation modules.

## Sources

- [hi-manshu/kalendar on GitHub](https://github.com/hi-manshu/kalendar)
- [License: Apache-2.0](https://github.com/hi-manshu/kalendar/blob/main/LICENSE)
- [Project website](https://hi-manshu.github.io/kalendar/)
- [README](https://github.com/hi-manshu/kalendar/blob/main/README.md)
- [Releases](https://github.com/hi-manshu/kalendar/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hi-manshu-kalendar
