
Cally is a JavaScript Web Component library for single-date calendars, date ranges, multiple-date selection, and multi-month calendar views. It uses standard custom elements and works in plain HTML, React, Vue, and Svelte projects.
Cally focuses on the calendar layer of a date picker. Your app or component library handles the input, toggle button, and popup. The package is less than 9KB min/gzip and has one runtime dependency, Atomico.
For React and shadcn/ui projects, compare this Flexible Date & Date Range Picker For Shadcn/ui.
Key Features:
- Single-date, multiple-date, and date-range selection.
- One or more months per calendar page.
- Minimum and maximum dates plus custom disabled-date rules.
- Week numbers and configurable weekday labels.
- Month and year select components for quick calendar navigation.
- Locale-aware labels through
Intl.DateTimeFormat and RTL layouts. - Keyboard and screen reader support within the calendar components.
- CSS parts, day-specific parts, and accent-color custom properties.
- Framework-independent Web Components with TypeScript types.
How to use it:
1. Importing Cally registers its custom elements. Install the package from npm and import it into your JavaScript or TypeScript file, or load the ESM build from unpkg.
# NPM
npm install cally
# JavaScript / TypeScript
import "cally";
# CDN
<script type="module" src="https://unpkg.com/cally"></script>
2. Use <calendar-date> with <calendar-month> for single-date selection. Date values use the YYYY-MM-DD ISO 8601 format.
<calendar-date value="2026-09-08">
<calendar-month></calendar-month>
</calendar-date>
3. Use <calendar-range> for a date range. The value uses YYYY-MM-DD/YYYY-MM-DD.
<calendar-range value="2026-09-08/2026-09-14">
<calendar-month></calendar-month>
</calendar-range>
4. Use <calendar-multi> for multiple individual dates. Its value is a space-separated list of ISO dates.
<calendar-multi value="2026-09-08 2026-09-12 2026-09-18">
<calendar-month></calendar-month>
</calendar-multi>
5. Set months on the parent calendar and offset on each month for a multi-month calendar.
<calendar-range months="2">
<calendar-month></calendar-month>
<calendar-month offset="1"></calendar-month>
</calendar-range>
6. Place <calendar-select-month> and <calendar-select-year> inside a date, range, or multi calendar when direct month and year navigation is useful.
<calendar-date min="2020-01-01" max="2030-12-31">
<calendar-select-month></calendar-select-month>
<calendar-select-year slot="heading" max-years="20"></calendar-select-year>
<calendar-month></calendar-month>
</calendar-date>
Cally Component API Reference:
<calendar-date>, <calendar-range>, and <calendar-multi> Values
| Component | value Format | Description |
|---|
<calendar-date> | YYYY-MM-DD | The selected date. |
<calendar-range> | YYYY-MM-DD/YYYY-MM-DD | The selected start and end dates. |
<calendar-multi> | Space-separated YYYY-MM-DD values | The selected individual dates. |
Shared Properties and Attributes
The following public properties belong to <calendar-date>, <calendar-range>, and <calendar-multi>. The value format differs by component as shown above.
| Property | Attribute | Type | Default | Description |
|---|
value | value | string | "" | The selected date, range, or dates for the current component. |
min | min | string | "" | The earliest selectable date. |
max | max | string | "" | The latest selectable date. |
today | today | string | "" | The date that the calendar considers today. |
focusedDate | focused-date | string | undefined | The date considered focused by the calendar. |
firstDayOfWeek | first-day-of-week | number | 1 | The first weekday, where Sunday is 0 and Monday is 1. |
showOutsideDays | show-outside-days | boolean | false | Shows dates outside the displayed month. |
showWeekNumbers | show-week-numbers | boolean | false | Shows week numbers. |
locale | locale | string | undefined | undefined | Sets the locale used for date formatting. The browser locale is used when unset. |
months | months | number | 1 | The number of months displayed per page. |
pageBy | page-by | "months" | "single" | "months" | Moves previous and next navigation by the displayed month count or by one month. |
formatWeekday | format-weekday | "narrow" | "short" | "narrow" | Sets the weekday header format. |
isDateDisallowed | None | (date: Date) => boolean | () => false | Returns true for dates that cannot be selected. |
getDayParts | None | (date: Date) => string | () => "" | Returns one or more CSS part names for an individual date. |
<calendar-range> Specific Property
| Property | Attribute | Type | Default | Description |
|---|
tentative | tentative | string | "" | The tentative date during range selection, such as the selected range start. |
Events
Cally emits non-bubbling custom events in response to user interaction. Programmatic changes to value do not emit change.
| Event | Components | Type | Fires When |
|---|
change | calendar-date, calendar-range, calendar-multi | Event | The selected value changes through user interaction. |
focusday | calendar-date, calendar-range, calendar-multi | CustomEvent<Date> | The focused day changes through keyboard navigation or previous/next controls. |
rangestart | calendar-range | CustomEvent<Date> | The user starts a range selection. |
rangeend | calendar-range | CustomEvent<Date> | The user finishes a range selection. |
Method
| Method | Components | Parameters | Description |
|---|
focus(options?: FocusOptions & { target: "previous" | "next" | "day" }) => void | calendar-date, calendar-range, calendar-multi | options | Focuses the month containing the focused date. target selects the previous button, next button, or day. |
Shared CSS Parts
| Part | Description |
|---|
container | The container for the entire component. |
header | The container for the heading and navigation buttons. |
button | Any button within the component. |
previous | The previous-page button. |
next | The next-page button. |
disabled | A navigation button disabled by min or max. |
heading | The heading that labels the calendar. |
months | The default slot where month components are rendered. |
Shared Slots
| Slot | Description |
|---|
| Default | Holds <calendar-month> components and other markup. |
previous | Replaces the content of the previous-page button. |
next | Replaces the content of the next-page button. |
heading | Replaces the visible calendar heading. Cally keeps a separate visually hidden heading for accessibility. |
<calendar-month>
<calendar-month> renders the grid of days and is designed for use inside <calendar-date>, <calendar-range>, or <calendar-multi>.
| Property | Attribute | Type | Default | Description |
|---|
offset | offset | number | 0 | Sets the displayed month relative to the first month in a multi-month view. |
CSS Custom Properties
| Property | Default | Description |
|---|
--color-accent | black | The accent color used throughout the month component. |
--color-text-on-accent | white | The text color used on the accent color. |
CSS Parts
| Part | Description |
|---|
heading | The month heading. |
table | The calendar <table>. |
tr | Any row in the table. |
head | The table header row. |
week | The table body rows. |
th | The table header cells. |
td | The table body cells. |
col-weeknumber | The <col> for the week-number column. |
col-1 | The <col> for the first weekday column. |
col-2 | The <col> for the second weekday column. |
col-3 | The <col> for the third weekday column. |
col-4 | The <col> for the fourth weekday column. |
col-5 | The <col> for the fifth weekday column. |
col-6 | The <col> for the sixth weekday column. |
col-7 | The <col> for the seventh weekday column. |
weekday | The weekday header cell. |
weeknumber | The week-number cell. |
button | Any button in the month component. |
day | The buttons and headings for calendar days. |
day-0 | Sunday day buttons and headings. |
day-1 | Monday day buttons and headings. |
day-2 | Tuesday day buttons and headings. |
day-3 | Wednesday day buttons and headings. |
day-4 | Thursday day buttons and headings. |
day-5 | Friday day buttons and headings. |
day-6 | Saturday day buttons and headings. |
selected | Selected days. |
today | The current day. |
disallowed | Days rejected by isDateDisallowed. |
outside | Days outside the displayed month. |
range-start | The first day in a selected range. |
range-end | The last day in a selected range. |
range-inner | Days between the range start and end. |
Slot
| Slot | Description |
|---|
weeknumber | Holds the heading for the week-number column when week numbers are shown. The default content is #. |
<calendar-select-month>
| Property | Attribute | Type | Default | Description |
|---|
formatMonth | format-month | "short" | "long" | "long" | Uses short or long localized month names. |
CSS Parts
| Part | Description |
|---|
label | The <label> for the select. |
select | The <select> element. |
option | Each month <option>. |
<calendar-select-year>
| Property | Attribute | Type | Default | Description |
|---|
maxYears | max-years | number | 20 | Sets the maximum year count around the focused year. Parent min and max values can reduce the displayed range. |
CSS Parts
| Part | Description |
|---|
label | The <label> for the select. |
select | The <select> element. |
option | Each year <option>. |
Styling Cally:
Use CSS parts for individual controls and calendar states. <calendar-month> also exposes two custom properties for its accent colors.
calendar-range::part(months) {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
calendar-range::part(button) {
border: 1px solid #bbb;
border-radius: 4px;
background: #fff;
}
calendar-month {
--color-accent: #6d4aff;
--color-text-on-accent: #fff;
}
calendar-month::part(range-inner) {
border-radius: 0;
}
Official Guides:
Alternatives & Related Resources:
Changelog:
v0.9.2 (02/05/2026)
- Fixed week-number calculations in non-GMT timezones.
- Fixed numbered day CSS parts such as
day-1 in non-GMT timezones.