Calendar
A calendar component with month/year modes, supporting selection, disabled dates, week numbers, and keyboard grid navigation; date descriptions use Intl.DateTimeFormat (locale-aware).
Basic Usage
Month view (mode=month)
Click a date to select it and dispatch oas-change; the title opens a month-selection panel for quick month jumps.
On touch screens (pointer: coarse) day cells get a 44px minimum height, month/year cells a 44px minimum height, and header navigation buttons a 44px hit target (day cells only grow in height — their width still shares the container evenly).
Year View
Year view (mode=year)
In year mode, selecting a month dispatches yyyy-MM.
Disabled Range
min / max limits
Disabled Callback
disabled-date (disable weekends)
disabledDate is passed in via a property callback (functions cannot be expressed in JSON).
Week Numbers
Show week numbers (show-week-number)
Events
oas-change event
Custom Cells
Event-marked calendar (oas-cell-render marks holidays)
oas-cell-render is dispatched for each rendered day cell (detail: { date, element }), letting the host append markers/badges/rich content (e.g. holidays, event dots); alternatively drop a <template slot="cell"> inside the component for a static skeleton whose [data-cell-date] node is auto-bound to the day number. Appending <span class="cell-dot"> inside element shows the built-in marker dot (uses the --oas-color-danger token; adapts to light/dark themes).
Scheduled Items (events)
events scheduled items (declarative markers + day detail popover)
The events attribute/property channel declares per-day items: [{ date: 'YYYY-MM-DD', title?, color? }]. A day with items renders marker dots (uses color when given, else the primary color); more than 2 items collapse into a +N badge; hovering or focusing the day opens an inline items popover (one row per title with its dot). Fully declarative — no hand-written oas-cell-render listener needed (that event stays as a fallback). Excludes cross-day items / drag-to-reschedule / week view (Scheduler-level capabilities).
Mode Switching
Mode switching (month ↔ year quick year jump)
mode="year" shows a 12-month grid; the previous/next year buttons in the header quickly switch years. Picking a month selects it (dispatches oas-change with value yyyy-MM) and auto-switches back to the month view (dispatches oas-mode-change). In a controlled scenario, listen to oas-mode-change and re-set the mode attribute to keep a specific mode.
Week Start Override
Week start override (first-day-of-week)
first-day-of-week accepts 0 (Sunday) through 6 (Saturday); defaults to the locale (Monday for European/Chinese locales, Sunday for Japanese/Korean/English/Arabic; otherwise derived from Intl.Locale week info).
Panel Month Anchor
page-show-date anchor + oas-panel-change
page-show-date anchors the displayed panel to the given month initially and reactively — even when value lives in another year (e.g. echoing a birth date while opening from the current month); it takes precedence over value. oas-panel-change (detail: { date }) fires when the user pages / picks a month / jumps; removing the attribute falls back to the value month.
Paging Boundaries
min / max paging boundaries
When the next page would fall entirely outside [min, max] (whole month in the day view, whole year in the month panel, whole decade page in the decade grid), the previous/next buttons grey out.
Range Selection
range: two-click range picking with highlight
Selected range: Click the start date, then the end date (hover shows a preview)
Set range to enter range selection mode: the first click sets the start date (highlighted), moving the pointer previews the range on hovered day cells in real time, and the second click sets the end date and emits oas-change (detail: { start, end }, both YYYY-MM-DD strings; swapped automatically when the end precedes the start). Range endpoints get a solid primary background with rounded corners, and the in-between days a light primary tint — all colors via tokens (same visual language as the date-picker daterange). Clicking again after a commit starts a new round (the old range clears immediately). The value attribute reflects/presets the range as a JSON array: value='["2026-08-05","2026-08-15"]'.
Multiple / Week Selection: Use date-picker
This component (a persistent selection panel) covers single-date selection out of the box; range selection is now covered by the range attribute above. Multiple dates and week picking remain covered by date-picker — the two share the same date grid with consistent semantics:
- Multiple dates:
<oas-date-picker multiple> - Week picking:
<oas-date-picker type="week">(valueyyyy-Wnn)
If multiple selection is needed on a persistent page, the host can combine the inner-panel capabilities of oas-date-picker with oas-calendar, or use oas-calendar for single selection while maintaining the set itself.
Custom Header
header slot (custom header, built-in nav by default)
slot="header" distributes a custom header (replaces the built-in navigation region entirely — the host takes over paging interaction, e.g. via controlled page-show-date anchoring); without it the built-in prev / title / next / today navigation remains ([part="header"] is targetable and styleable via ::part).
Panel Language & Header Format
locale: panel language override
locale overrides the panel language: title/weekday/cell-description Intl formatting, navigation and "Today" labels, and week-start derivation all follow; it defaults to the config-provider injection or the global locale.
format: header date format string
format customizes the header title format (same tokens as date-picker: yyyy/MM/dd/HH/mm/ss; applies to both the day and month panel titles); the decade panel title is a range form (2020-2031) and does not take the format string.
Custom Header Action Bar: Card Composition (extra content, keeps built-in nav)
To place a brand/action bar above the calendar while keeping the built-in navigation, wrap oas-calendar in the host's own card with the action bar on top (to replace the header entirely, use the header slot above):
Header composition: custom header action bar
Read-only Calendar
readonly: read-only detail view with event dots
With readonly, paging and panel drill-down stay available but picking dates / pressing Enter does not commit — combined with oas-cell-render event dots this yields a "viewable, not editable" detail calendar.
Globally Disabled
disabled: fully non-interactive
disabled greys out the whole calendar and stops all interaction (picking / paging / keyboard); use it with form-disabled scenarios. readonly still allows browsing.
Keyboard & Fast Year Jump
Extended keyboard + decade fast year jump
- Keyboard:
Home/Endjump to the start/end of the week;PageUp/PageDownmove to the previous/next month (Shiftmoves by year); arrow keys move cell by cell,Enter/Spaceselects. - Fast year jump: click the title to open the month panel, click the year to open the decade grid (pages step by ±12 years), pick a year to return to that year's month panel, then pick a month to return to the day view — from 2026 to 1980 takes about 7-8 clicks.
Non-Gregorian Calendars (calendar-system)
Chinese calendar (calendar-system=chinese)
Islamic calendar (calendar-system=islamic)
calendar-system passes through Intl.DateTimeFormat's calendar option (chinese / islamic / hebrew, etc.): the title, weekday headers, cell numbers and aria descriptions follow that calendar, while date math and the value / data-date stay on the Gregorian internal model — the calendar only affects display and screen-reader output.
Multi-month Panels (months)
months=2: two months side by side + linked paging
months sets the number of side-by-side month panels (default 1, positive integer; invalid or below 1 falls back to 1, values above the cap clamp to 12): panels lay out horizontally at equal width, and prev/next page the whole strip (stepping months months at a time) with the title showing the month range. It combines with first-day-of-week, show-week-number, range, and the rest.
API
oas-calendar
Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
calendar-system | Non-Gregorian calendar (Intl calendar option, e.g. chinese/islamic/hebrew): title, weekday headers, cell numbers and aria descriptions follow it; date math and value/data-date stay Gregorian | string | — |
disabled | Globally disabled: greys out the calendar and stops all interaction (picking / paging / keyboard) | boolean | — |
events | Scheduled items (JSON): [{ date: YYYY-MM-DD, title?, color? }] — marker dots per day (uses color if given, else primary), +N badge beyond 2; hover/focus opens an inline items popover | CalendarEvent[] | [] |
first-day-of-week | Week start override: 0 (Sunday) to 6 (Saturday); defaults to the locale (Monday for European/Chinese, Sunday for Japanese/Korean/English/Arabic) | string | — |
format | Header title format string (yyyy/MM/dd tokens; day/month panels) | string | — |
locale | Panel language override (title/weekdays/cell descriptions/nav copy/week start); defaults to config-provider > global | string | — |
max | Selectable range (ISO dates); navigation buttons grey out when the whole target page falls outside the range | string | — |
min | Selectable range (ISO dates); navigation buttons grey out when the whole target page falls outside the range | string | — |
mode | month / year (in year mode, picking a month auto-switches back to month view) | string | month |
months | Number of side-by-side month panels (1-12, default 1): panels lay out horizontally and paging steps the whole strip; the title shows the month range | string | — |
page-show-date | Panel month anchor (ISO yyyy-MM or yyyy-MM-dd): anchors the displayed month initially/on change, taking precedence over value; removing it falls back to the value month | string | — |
range | Range selection mode: two-click picking with hover preview and range highlighting; oas-change carries { start, end }; value mirrors a JSON array | boolean | — |
readonly | Read-only: page navigation and panel drill-down stay available, but picking dates / Enter does not commit | boolean | — |
show-week-number | Show the ISO week number column | boolean | — |
value | Selected value (ISO) | string | — |
Property (JS property; see each row for attribute reflection)
| Property | Description | Type | Default |
|---|---|---|---|
disabledDate | Disabled-date predicate (property function channel, (date) => boolean) | ((d: Date) => boolean) | null | — |
events | Scheduled items (CalendarEvent[], { date, title?, color? }): el.events reads the effective items; el.events = [...] writes programmatically (syncs the events attribute and re-renders, no event) | CalendarEvent[] | [] |
Events
| Event | Description |
|---|---|
oas-cell-render | Dispatched when each day cell renders, detail: { date, element } (element is the day button; host can append markers/badges/rich content) |
oas-change | Selection change, detail: { value } |
oas-mode-change | Dispatched when year mode auto-switches back to month view after picking a month, detail: { mode } |
oas-panel-change | Dispatched when the displayed panel month changes due to user paging/month picking/jumps, detail: { date } (date is the first day of the new page) |
Slots
| Name | Description |
|---|---|
header | Custom header replacing the built-in navigation (built-in kept when not distributed) |
template[slot="cell"] | Static template for day cells, cloned into each day button; the [data-cell-date] node is bound to the day number |
Keyboard: ↑/↓/←/→ to move within the grid (auto-paging across months), Home/End to jump to the week start/end, PageUp/PageDown to move between months (Shift for years), Enter/Space to select.