v-calendar
An elegant calendar and date-picker plugin for Vue.js, with attribute-based highlights, dots, bars, and popovers.
Repository Health
Technical Analysis
v-calendar is a Vue.js plugin for building attributed calendars and date pickers. Instead of hard-coding calendar markup, it lets you decorate dates with a normalized attribute model — highlighted regions, dots, bars, custom content classes, and popovers — that can target single dates, date ranges, or recurring patterns like “every other Friday” or “the last Friday of every other month”.
A date picker ships out of the box on top of the same calendar engine, supporting single-date, multiple-date, and date-range selection modes, with the same props, slots, and theming as the base calendar component. Locale-aware date math (first day of week, timezones, formatting) is handled through date-fns and date-fns-tz, and layout is responsive down to mobile widths.
What You Get
- A
v-calendarcomponent with responsive multi-row/multi-column layouts, slot-based custom header and day content, and slide/fade navigation transitions - A
v-date-pickercomponent built as a thin wrapper over the calendar, supporting single, multiple, and date-range picker modes with the same props and slots - An attribute system (
Attribute/AttributeStore) for decorating dates with highlights, dots, bars, content classes, and popovers, including recurring date patterns viaDateInfo - A
Localemodule wrapping date-fns/date-fns-tz for first-day-of-week, timezone normalization, and locale-aware formatting - A
Popovercomponent for tooltip-style or custom slot content anchored to calendar days, positioned with @popperjs/core - Global plugin configuration via
setupCalendar(opts), plus responsive breakpoint support throughsetupScreens
Common Use Cases
- Booking and scheduling UIs that need to highlight available, booked, or blocked date ranges
- Date-range filters and reporting dashboards where users pick a start and end date
- Event calendars that mark specific days with dots, bars, or custom content based on data
- Form date pickers requiring single, multiple, or range selection with locale/timezone-correct output
Under The Hood
Architecture
v-calendar is registered as a standard Vue 2 plugin: src/lib.js exports an install(Vue, opts) function that calls setupCalendar(opts) and registers each component under a configurable prefix. The core rendering component, Calendar.vue, composes smaller pieces (CalendarPane, CalendarNav, CalendarDay, CalendarWeeks), while DatePicker.vue wraps Calendar.vue and adds selection-mode logic (single/multiple/range) rather than duplicating the calendar’s rendering. Date-related state is modeled outside the components entirely: DateInfo normalizes single dates, ranges, and recurring patterns, and Attribute/AttributeStore translate that into the highlight/dot/bar/popover visuals the calendar renders, so calendar visuals stay data-driven rather than templated per day. Shared cross-cutting behavior (popover positioning, responsive breakpoints via setupScreens) is implemented with Vue 2 Options API mixins (utils/mixins/) rather than composables, consistent with the Vue 2 peer dependency. The tradeoff of this design is that the core components (Calendar.vue, DatePicker.vue) and Locale are each large single files (800-1000+ lines), concentrating a lot of behavior rather than splitting it into smaller composable units.
Tech Stack
The library targets Vue 2 (peerDependencies: vue ^2.5.18) and ships via @vue/cli-service’s library build mode, producing separate UMD bundles per component (calendar, date-picker, popover, popover-row) plus a combined v-calendar bundle. Date handling runs on date-fns and date-fns-tz for locale/timezone-correct math, @popperjs/core positions popovers, and lodash plus core-js round out general utilities and polyfills. Styling is plain CSS (src/styles/base.css) processed through PostCSS preset-env. The documentation site is a separate VuePress app under docs/, styled with Tailwind.
Code Quality
The repo includes Jest-based unit tests (tests/unit/specs/) covering Calendar, DatePicker, Locale, and DateInfo, using @vue/test-utils and vue-jest, with ESLint configured against an Airbnb-derived Vue config. There is no TypeScript — the codebase is plain JavaScript with hand-written runtime type checks (isObject/isArray/isFunction helpers in _.js) standing in for static types, and error handling leans on defensive defaults rather than explicit thrown/typed errors. No CI workflow configuration (e.g. GitHub Actions) is present in the repository, so test/lint enforcement on contributions isn’t visible from the repo itself.
What Makes It Unique
Rather than exposing a calendar as fixed markup with per-cell slots, v-calendar’s distinguishing choice is treating calendar decoration as a normalized attribute model (Attribute, AttributeStore, DateInfo) that is shared identically between the plain calendar and the date picker — including support for recurring date patterns (e.g. “every other Friday”, “last Friday of every other month”) as first-class attribute targets, not just single dates or simple ranges. This lets highlights, dots, bars, and popovers all be driven by the same declarative date-matching logic instead of separate ad hoc implementations per visual type.