Calendar
A month grid for picking a date, with the month and weekday names coming from the locale Django has active for the request.
Page the months, pick a day. Today is outlined; days from the neighbouring months are dimmed and still selectable.
Installation
uvx django_shadcn@latest add calendar
Usage
<c-calendar name="due_date" value="{{ form.due_date.value|date:'Y-m-d' }}" />
With name set, the component is a form field on its own: it renders a hidden
input carrying the ISO date, so an ordinary Django form receives
request.POST['due_date'] as 2026-08-13 and forms.DateField parses it
without any help.
For a field that opens on click instead of sitting on the page, use Date Picker, which is this component inside a popover.
Where the month grid comes from
Upstream hands the grid to react-day-picker. There is no library to hand it to
here, and a copied template carries no Python of its own, so the grid is built
from the calendar the browser already has.
What the browser does not decide is the language. That comes from Django:
{% get_current_language as LANGUAGE_CODE %}
so the month and weekday names follow the site's active language, not the
visitor's browser settings. Switch the language and the same page renders
agosto de 2026 or août 2026.
The first day of the week follows the same language. fr starts on Monday,
en-us and pt-br on Sunday, ar-eg on Saturday — without a setting to keep
in sync.
Set first_day when a project disagrees with its own locale:
<c-calendar first_day="1" />
0 is Sunday and 6 is Saturday, matching Django's FIRST_DAY_OF_WEEK.
Limiting the range
<c-calendar name="appointment" min="2026-08-10" max="2026-08-20" />
Days outside the range render dimmed and their buttons are disabled, so they cannot be clicked or reached by keyboard.
Reacting to a selection
Picking a day dispatches a bubbling calendar-change event carrying the ISO
date, which is how
Date Picker is built:
<div x-data="{ chosen: '' }" x-on:calendar-change="chosen = $event.detail.value">
<c-calendar />
<p x-text="chosen"></p>
</div>
The selection is also on the Alpine scope as selected.
Props
| Prop | Default | Meaning |
|---|---|---|
name |
— | renders a hidden input under this name; leave it out for a display-only calendar |
value |
— | the ISO date selected when the page loads |
first_day |
the locale's | 0 for Sunday through 6 for Saturday |
min |
— | the earliest selectable ISO date |
max |
— | the latest selectable ISO date |
A note on what is not here
Range and multiple selection are not implemented. They have no behavioural
parity with react-day-picker in a grid this size, and half of a range picker
is worse than none — it would look like the upstream component and answer to a
different set of rules. Single-date selection is faithful, and it is what a
Django form field needs.