Calendar
Use CCalendar when the active Citry locale must determine an inline calendar's month heading, weekday order, day names, and accessible date labels. The public value remains a canonical YYYY-MM-DD date regardless of display locale or calendar system.
Select one date
Compose Calendar in CField for a visible label, description, error, and shared state. A standalone Calendar uses its localized label by default.
<c-CField required>
<c-fill name="label">Arrival date</c-fill>
<c-fill name="default"><c-CCalendar name="arrival" /></c-fill>
</c-CField>
Show code
from datetime import date
from typing import Any
import citry_ui
from citry import Component, citry
from citry_ui import CCalendar
citry.register_library(citry_ui)
# ruff: noqa: E501 - template and CSS lines stay readable in public source examples
class BasicCalendar(Component):
class Kwargs:
pass
class Slots:
pass
def template_data(self, kwargs: Kwargs, slots: Slots) -> dict[str, Any]: # noqa: ARG002
return {"python_calendar": CCalendar(value=date(2026, 8, 19), label="Python-composed calendar")}
template = """
<section class="calendar-demo-grid">
<c-CField required>
<c-fill name="label">Arrival date</c-fill>
<c-fill name="description">Choose your check-in day.</c-fill>
<c-fill name="default"><c-CCalendar name="arrival" value="2026-08-19" /></c-fill>
</c-CField>
<article><h3>Python composition</h3>{{ python_calendar }}</article>
</section>
"""
css = ":where(.calendar-demo-grid){display:grid;grid-template-columns:repeat(auto-fit,minmax(20rem,1fr));gap:1.25rem}:where(.calendar-demo-grid article){display:grid;align-content:start;gap:.75rem}:where(.calendar-demo-grid h3){margin:0}"
preview = BasicCalendar()
preview # noqa: B018
The enhanced grid uses one roving tab stop. Arrow keys move by day or week, Home and End move within the locale week, Page Up/Down move by calendar month, and Shift+Page Up/Down move by calendar year. Enter or Space selects the focused date.
Submit and reset a canonical value
name contributes exactly one canonical date through the owned native Date input. Disabled Calendar is omitted; readonly Calendar remains submitted. An uncanceled reset restores the server value and visible month.
Show code
from citry import Component
class CalendarForm(Component):
class Kwargs:
pass
class Slots:
pass
template = """
<section x-data="{submitted:'Submit to inspect FormData'}">
<form @submit.prevent="submitted=JSON.stringify(Object.fromEntries(new FormData($event.target)))">
<c-CField control_id="trip-date" required>
<c-fill name="label">Trip date</c-fill>
<c-fill name="description">The native Form value remains YYYY-MM-DD.</c-fill>
<c-fill name="default"><c-CCalendar id="trip-date" name="trip_date" value="2026-08-19" /></c-fill>
<c-fill name="error">Choose a trip date.</c-fill>
</c-CField>
<div><button type="submit">Submit</button> <button type="reset">Reset</button></div>
</form>
<output x-text="submitted">Submit to inspect FormData</output>
</section>
"""
css = ":where(form,section){display:grid;justify-items:start;gap:.75rem}"
preview = CalendarForm()
preview # noqa: B018
Without JavaScript, that Date input remains visible and usable. After enhancement it becomes the visually hidden Form, validity, and reset transport; the browser-generated grid is the interaction surface.
Bound and block dates
min and max are inclusive. Dates outside them are disabled and leave the focus sequence. unavailable_dates accepts up to 4096 unique exact dates; those dates stay focusable so keyboard users can inspect the calendar, but selection is rejected.
Show code
from citry import Component
class CalendarConstraints(Component):
class Kwargs:
pass
class Slots:
pass
template = """
<c-CCalendar
label="Book an appointment"
visible_date="2026-08-19"
min="2026-08-10"
max="2026-09-15"
c-unavailable_dates="('2026-08-18', '2026-08-20', '2026-08-24')"
/>
"""
preview = CalendarConstraints()
preview # noqa: B018
This bounded exact list is for known application dates such as booked days. The server must validate submitted availability again.
Control selection and the visible month
Client value and visibleDate are independent controlled channels. A controlled request invokes onValueChange or onVisibleDateChange without claiming the selection or page changed; return the accepted canonical value to commit it. Omitting a prop releases that channel at its latest accepted state.
Show code
from citry import Component
# ruff: noqa: E501 - Alpine expressions stay readable in the public source example
class ControlledCalendar(Component):
class Kwargs:
pass
class Slots:
pass
template = """
<section x-data="{selected:'2026-08-19',visible:'2026-08-19',last:'No request yet'}">
<c-CCalendar
label="Controlled calendar"
value="2026-08-19"
visible_date="2026-08-19"
$c-props="{value:selected,visibleDate:visible,onValueChange:(value,detail)=>{last=`selection: ${value}`;selected=value},onVisibleDateChange:(value,detail)=>{last=`month: ${value}`;visible=value}}"
/>
<output x-text="last">No request yet</output>
</section>
"""
css = ":where(section){display:grid;justify-items:start;gap:.75rem}"
preview = ControlledCalendar()
preview # noqa: B018
Uncontrolled selection emits bubbling native input followed by change from the fallback input. Controlled requests do not emit those transport events.
Follow the active locale
Under a client-enabled <c-i18n> provider, Calendar rebuilds its heading, weekday order, day numbers, and full accessible date labels immediately when the locale changes. first_day_of_week can override only the week start; leave it as None to follow locale week data.
Show code
from citry import Component
# ruff: noqa: E501 - template and CSS lines stay readable in the public source example
class CalendarLocales(Component):
class Kwargs:
pass
class Slots:
pass
template = """
<section class="calendar-demo-grid">
<article><h3>Locale week start</h3><c-CCalendar label="Locale week start" visible_date="2026-08-19" /></article>
<article><h3>Explicit Monday</h3><c-CCalendar label="Monday week start" visible_date="2026-08-19" c-first_day_of_week="1" /></article>
</section>
"""
css = ":where(.calendar-demo-grid){display:grid;grid-template-columns:repeat(auto-fit,minmax(20rem,1fr));gap:1.25rem}:where(.calendar-demo-grid article){display:grid;align-content:start;gap:.5rem}:where(.calendar-demo-grid h3){margin:0}"
preview = CalendarLocales()
preview # noqa: B018
Calendar navigates locale calendar months while retaining ISO Gregorian domain dates for callbacks and FormData. The provider time zone determines today's marker when explicit; otherwise Calendar uses the browser's local date.
Choose stable or natural rows
fixed_weeks=True keeps six rows so surrounding layout does not jump between months. Set it to False for the month's natural row count. Hide neighboring month dates with show_adjacent_days=False when they should not be selectable from the current page.
Show code
from citry import Component
# ruff: noqa: E501 - template and CSS lines stay readable in the public source example
class CalendarNaturalWeeks(Component):
class Kwargs:
pass
class Slots:
pass
template = """
<section class="calendar-demo-grid">
<article><h3>Fixed six rows</h3><c-CCalendar label="Fixed weeks" visible_date="2026-02-01" /></article>
<article><h3>Natural rows</h3><c-CCalendar label="Natural weeks" visible_date="2026-02-01" c-fixed_weeks="False" c-show_adjacent_days="False" /></article>
</section>
"""
css = ":where(.calendar-demo-grid){display:grid;grid-template-columns:repeat(auto-fit,minmax(20rem,1fr));align-items:start;gap:1.25rem}:where(.calendar-demo-grid article){display:grid;gap:.5rem}:where(.calendar-demo-grid h3){margin:0}"
preview = CalendarNaturalWeeks()
preview # noqa: B018
Compare states and sizes
Outline and plain variants combine with sm, md, and lg sizes. Readonly Calendar allows focus and navigation but blocks selection. Disabled Calendar removes all day tab stops and disables navigation.
Show code
from citry import Component
# ruff: noqa: E501 - template and CSS lines stay readable in the public source example
class CalendarStates(Component):
class Kwargs:
pass
class Slots:
pass
template = """
<section class="calendar-demo-grid">
<article><h3>Small plain</h3><c-CCalendar label="Small plain calendar" value="2026-08-19" size="sm" variant="plain" /></article>
<article><h3>Readonly</h3><c-CCalendar label="Readonly calendar" value="2026-08-19" readonly /></article>
<article><h3>Disabled</h3><c-CCalendar label="Disabled calendar" value="2026-08-19" disabled /></article>
<article><h3>Invalid large</h3><c-CCalendar label="Invalid calendar" value="2026-08-19" invalid size="lg" /></article>
</section>
"""
css = ":where(.calendar-demo-grid){display:grid;grid-template-columns:repeat(auto-fit,minmax(20rem,1fr));align-items:start;gap:1.25rem}:where(.calendar-demo-grid article){display:grid;gap:.5rem}:where(.calendar-demo-grid h3){margin:0}"
preview = CalendarStates()
preview # noqa: B018
Customize documented anatomy
Public --cui-calendar-* variables style the root, navigation, dates, selected day, today, and unavailable dates. Stable data-citry-ui-part selectors expose the documented anatomy without making generated classes or arrow markup public.
Show code
from citry import Component
# ruff: noqa: E501 - template and CSS lines stay readable in the public source example
class StyledCalendar(Component):
class Kwargs:
pass
class Slots:
pass
template = """
<c-CCalendar class_="brand-calendar" label="Brand calendar" value="2026-08-19" c-unavailable_dates="('2026-08-20',)" />
"""
css = """
:where(.brand-calendar){--cui-calendar-background:#fff8eb;--cui-calendar-border-color:#9a6700;--cui-calendar-focus-color:#6f42c1;--cui-calendar-selected-background:#7c3aed;--cui-calendar-selected-foreground:white;--cui-calendar-today-color:#9a3412;--cui-calendar-radius:1rem}
@media (prefers-color-scheme:dark){:where(.brand-calendar){--cui-calendar-background:#211a10;--cui-calendar-foreground:#fff7e6}}
"""
preview = StyledCalendar()
preview # noqa: B018
Use CDateInput when browser-owned editing and picker UI are preferable. Use CDatePicker for a popup field composed from DateInput and Calendar, and CDateRange when the application value is an ordered start/end pair.
API reference
Inputs
CCalendar server inputs
Server inputs are passed in a template through <c-CCalendar ... /> or in Python through CCalendar(...).
| Input | Type | Default | Effect |
|---|---|---|---|
value | CCalendarDate | None (CCalendarDate) | None | Sets the initial/reset selected canonical date or empty value. |
visible_date | CCalendarDate | None (CCalendarDate) | Selected date or today. | Sets the initially visible calendar month; otherwise uses value or today. |
name | str | None | None | Sets the native fallback input Form field name. |
form | str | None | None | Associates the native fallback input with an external Form ID. |
id | str | None | generated | Sets the public fallback input ID and the prefix for owned IDs. |
min | CCalendarDate | None (CCalendarDate) | None | Sets the inclusive minimum selectable canonical date. |
max | CCalendarDate | None (CCalendarDate) | None | Sets the inclusive maximum selectable canonical date. |
unavailable_dates | Sequence[CCalendarDate] | () | Marks at most 4096 unique in-range dates focusable but unavailable. |
required | bool | None | None | Enables native empty-value validity outside Field; Field owns it inside Field. |
disabled | bool | None | None | Blocks interaction and Form participation outside Field; Form disabledness also wins. |
readonly | bool | None | None | Keeps a focusable submitted value while blocking selection changes. |
invalid | bool | None | None | Adds application invalid state to revealed native validity. |
first_day_of_week | Literal[1, 2, 3, 4, 5, 6, 7] | None | None | Overrides the locale week start using ISO Monday 1 through Sunday 7. |
show_adjacent_days | bool | True | Shows selectable dates from neighboring months in leading and trailing cells. |
fixed_weeks | bool | True | Uses six stable week rows instead of the natural month row count. |
label | str | "Calendar" | Names a standalone calendar; Field supplies the name when composed. |
previous_label | str | "Previous month" | Names the previous-month button. |
next_label | str | "Next month" | Names the next-month button. |
unavailable_message | str | "Choose an available date." | Supplies native custom validity when a formerly selected date becomes unavailable. |
variant | "outline" | "plain" (CCalendarVariant) | "outline" | Selects bordered or unframed treatment. |
size | "sm" | "md" | "lg" (CCalendarSize) | "md" | Selects coordinated cell navigation and text sizing. |
class_ | CClassValue | None (CClassValue) | None | Adds classes to the root group and merges with attrs. |
style | CStyleValue | None (CStyleValue) | None | Adds styles to the root group and merges with attrs. |
attrs | Mapping[str, object] | None | None | Adds copied allowed root attributes without replacing owned roles state IDs or runtime markers. |
CCalendar client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CCalendar />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
value | canonical string | null | Releases control at the latest accepted value. | Controls the selected date while supplied. |
visibleDate | canonical string | Releases visible-month control at its latest accepted month. | Controls the month containing this date while supplied. |
min | canonical string | null | Uses the server minimum. | Replaces or removes the inclusive minimum. |
max | canonical string | null | Uses the server maximum. | Replaces or removes the inclusive maximum. |
unavailableDates | canonical string array | Uses the server sequence. | Replaces the bounded unavailable-date set. |
required | boolean | Uses server or Field state. | Controls standalone required validity. |
disabled | boolean | Uses server or owner state. | Controls navigation selection and Form participation. |
readonly | boolean | Uses server or owner state. | Controls focusable nonmutable state. |
invalid | boolean | Uses server or Field state. | Controls application invalid state. |
firstDayOfWeek | 1 | 2 | 3 | 4 | 5 | 6 | 7 | null | Uses the server input. | Replaces or restores the locale week start. |
showAdjacentDays | boolean | Uses the server input. | Controls neighboring-month cell visibility. |
fixedWeeks | boolean | Uses the server input. | Controls six-row versus natural-row layout. |
variant | CCalendarVariant (CCalendarVariant) | Uses the server input. | Controls presentation. |
size | CCalendarSize (CCalendarSize) | Uses the server input. | Controls coordinated sizing. |
onValueChange | function | No semantic selection callback. | Receives pointer keyboard or reset selection requests. |
onVisibleDateChange | function | No semantic month callback. | Receives button keyboard or selection-driven month requests. |
Slots
-
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CCalendar events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onValueChange | (value: string | null, detail: CCalendarValueChangeDetail) => void (CCalendarValueChangeDetail) | A pointer or keyboard selection requests a new date or the owning Form resets. | {value, previousValue, controlled, source, sourceEvent} (CCalendarValueChangeDetail) | Uncontrolled selection commits before notification and emits native input/change; controlled selection is request-only. |
onVisibleDateChange | (visibleDate: string, detail: CCalendarVisibleDateChangeDetail) => void (CCalendarVisibleDateChangeDetail) | Navigation or focus crossing a month requests another visible calendar month. | {visibleDate, previousVisibleDate, controlled, source, sourceEvent} (CCalendarVisibleDateChangeDetail) | Uncontrolled navigation commits before notification; controlled navigation waits for its owner. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CCalendar CSS variables
Apply these variables to CCalendar or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-calendar-background | color | Root and native fallback background. | Canvas |
--cui-calendar-foreground | color | Root foreground. | CanvasText |
--cui-calendar-border-color | color | Root fallback and cell border. | Mixed CanvasText. |
--cui-calendar-focus-color | color | Navigation and day focus outline. | Highlight |
--cui-calendar-selected-background | color | Selected day background and border. | Highlight |
--cui-calendar-selected-foreground | color | Selected day text. | HighlightText |
--cui-calendar-today-color | color | Today marker border. | LinkText |
--cui-calendar-adjacent-color | color | Weekdays and neighboring-month dates. | Muted CanvasText. |
--cui-calendar-unavailable-color | color | Unavailable date text. | GrayText |
--cui-calendar-radius | length | Root corner radius. | 0.75rem |
--cui-calendar-padding | length | Root inset. | 0.75rem |
--cui-calendar-gap | length | Header grid and cell spacing. | 0.25rem |
--cui-calendar-cell-size | length | Day cell minimum target size. | 2.5rem |
--cui-calendar-navigation-size | length | Previous and next button size. | 2.5rem |
--cui-calendar-font-size | length | Root text size. | 1rem |
--cui-calendar-invalid-border-color | color | Invalid root border. | Theme error. |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CCalendar attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
data-required | Root group | present | absent | Mirrors effective requiredness. |
data-disabled | Root group | present | absent | Mirrors effective disabledness. |
data-readonly | Root group | present | absent | Mirrors effective readonly state. |
data-invalid | Root group | present | absent | Mirrors application or revealed native invalidity. |
data-empty | Root group | present | absent | Marks no selected canonical value. |
data-variant | Root group | CCalendarVariant (CCalendarVariant) | Mirrors visual treatment. |
data-size | Root group | CCalendarSize (CCalendarSize) | Mirrors coordinated sizing. |
CCalendar attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
data-date | Date gridcell | canonical date | Identifies the exact ISO domain date. |
data-selected | Date gridcell | present | absent | Marks the committed selected date. |
data-today | Date gridcell | present | absent | Marks today in the effective provider time zone. |
data-outside | Date gridcell | present | absent | Marks a neighboring-month date or blank. |
data-unavailable | Date gridcell | present | absent | Marks a focusable date that selection rejects. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CCalendar selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="calendar"] | Root group | State reflections root attrs and styling destination. |
[data-citry-ui-part="header"] | Header div | Navigation and localized heading layout. |
[data-citry-ui-part="previous"] | Button | Requests the previous calendar month. |
[data-citry-ui-part="heading"] | Live h2 | Announces the localized visible month and year. |
[data-citry-ui-part="next"] | Button | Requests the next calendar month. |
[data-citry-ui-part="grid"] | Table grid | Owns localized weekdays and roving date cells. |
[data-citry-ui-part="weekday-row"] | Header row | Owns the seven localized weekday headers. |
[data-citry-ui-part="weekday"] | Column header | Displays abbreviated and full localized weekday names. |
[data-citry-ui-part="week"] | Grid row | Groups one locale-ordered week. |
[data-citry-ui-part="day"] | Gridcell | Exact roving focus selection and day-state hook. |
[data-citry-ui-part="fallback-input"] | Native Date input | Form reset validity and no-JavaScript transport. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CCalendarDate | date | str |
CCalendarVariant | Literal["outline", "plain"] |
CCalendarSize | Literal["sm", "md", "lg"] |
CCalendarChangeSource | Literal["pointer", "keyboard", "button", "value", "reset"] |
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, object] | Sequence[CStyleValue] |
CCalendarValueChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
value | string | null | - | Requested selected canonical date or empty state. |
previousValue | string | null | - | Effective selected date before the request. |
controlled | boolean | - | Whether client value owns committed selection. |
source | CCalendarChangeSource (CCalendarChangeSource) | - | Pointer keyboard value or reset cause. |
sourceEvent | object | null | - | Native interaction event when one exists. |
CCalendarVisibleDateChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
visibleDate | string | - | Requested canonical date inside the new visible month. |
previousVisibleDate | string | - | Visible canonical date before the request. |
controlled | boolean | - | Whether client visibleDate owns the visible month. |
source | CCalendarChangeSource (CCalendarChangeSource) | - | Button keyboard selection value or reset cause. |
sourceEvent | object | null | - | Native interaction event when one exists. |
Translation keys
Catalog keys used by this family. An explicit component input or slot listed in Override takes precedence over the catalog for that instance.
CCalendar translation keys
| Key | Purpose | Variables | Override | Browser updates |
|---|---|---|---|---|
citry-ui-calendar-label | Names a standalone root group and its native fallback. | none | label or root attrs aria-label/aria-labelledby | $c-tr updates both stable aria-label destinations. |
citry-ui-calendar-previous-month | Names the previous-month button. | none | previous_label | $c-tr updates the stable aria-label destination. |
citry-ui-calendar-next-month | Names the next-month button. | none | next_label | $c-tr updates the stable aria-label destination. |
citry-ui-calendar-unavailable | Supplies custom native validity when a selected date becomes unavailable. | none | unavailable_message | i18n.bind() updates the browser-owned validity message. |