package examples import (package examples import ( "time" "github.com/axadrn/shadcn-templ/v2/components/calendar") templ CalendarDemo() { {{ now := time.Now() }} @calendar.Calendar(calendar.Props{ Selected: now, CaptionLayout: calendar.CaptionLayoutDropdown, Class: "rounded-lg border", })}Installation
Usage
About
The Calendar component is a native templ and vanilla JavaScript implementation with no external dependencies.
Date Picker
You can use the Calendar component to build a date picker. See the Date Picker page for more information.
Basic
A basic calendar component. We used Class: "rounded-lg border" to style the calendar.
package examples import "github.com/axadrn/shadcn-templ/v2/components/calendar"package examples import "github.com/axadrn/shadcn-templ/v2/components/calendar" templ CalendarBasic() { @calendar.Calendar(calendar.Props{Class: "rounded-lg border"})}Range Calendar
Use the Mode: calendar.ModeRange prop to enable range selection.
package examples import (package examples import ( "time" "github.com/axadrn/shadcn-templ/v2/components/calendar") templ CalendarRange() { {{ from := time.Date(time.Now().Year(), 1, 12, 0, 0, 0, 0, time.Local) to := from.AddDate(0, 0, 30) }} @calendar.Calendar(calendar.Props{ Mode: calendar.ModeRange, Selected: from, EndValue: to, NumberOfMonths: 2, Class: "rounded-lg border", })}Month and Year Selector
Use CaptionLayout: calendar.CaptionLayoutDropdown to show month and year dropdowns.
package examples import "github.com/axadrn/shadcn-templ/v2/components/calendar"package examples import "github.com/axadrn/shadcn-templ/v2/components/calendar" templ CalendarCaption() { @calendar.Calendar(calendar.Props{ CaptionLayout: calendar.CaptionLayoutDropdown, Class: "rounded-lg border", })}Presets
package examples import (package examples import ( "time" "github.com/axadrn/shadcn-templ/v2/components/button" "github.com/axadrn/shadcn-templ/v2/components/calendar" "github.com/axadrn/shadcn-templ/v2/components/card") templ CalendarPresets() { {{ selected := time.Date(time.Now().Year(), 2, 12, 0, 0, 0, 0, time.Local) }} {{ presets := []struct { Label string Days string }{ {"Today", "0"}, {"Tomorrow", "1"}, {"In 3 days", "3"}, {"In a week", "7"}, {"In 2 weeks", "14"}, } }} @card.Card(card.Props{ Size: card.SizeSm, Class: "mx-auto w-fit max-w-[300px]", }) { @card.Content() { @calendar.Calendar(calendar.Props{ ID: "calendar-presets", Selected: selected, FixedWeeks: true, Class: "p-0 [--cell-size:--spacing(9.5)]", }) } @card.Footer(card.FooterProps{Class: "flex flex-wrap gap-2 border-t"}) { for _, preset := range presets { @button.Button(button.Props{ Variant: button.VariantOutline, Size: button.SizeSm, Class: "flex-1", Attributes: templ.Attributes{ "data-preset-days": preset.Days, }, }) { { preset.Label } } } } } <script> (() => { const calendar = () => document.getElementById("calendar-presets"); document.querySelectorAll("[data-preset-days]").forEach((btn) => { btn.addEventListener("click", () => { const date = new Date(); date.setDate(date.getDate() + parseInt(btn.dataset.presetDays, 10)); const iso = date.toLocaleDateString("sv-SE"); calendar().dispatchEvent( new CustomEvent("calendar-set", { bubbles: true, detail: { date: iso } }), ); }); }); })(); </script>}Date and Time Picker
package examples import (package examples import ( "time" "github.com/axadrn/shadcn-templ/v2/components/calendar" "github.com/axadrn/shadcn-templ/v2/components/card" "github.com/axadrn/shadcn-templ/v2/components/field" "github.com/axadrn/shadcn-templ/v2/components/icon" "github.com/axadrn/shadcn-templ/v2/components/inputgroup") templ CalendarTime() { {{ selected := time.Date(time.Now().Year(), time.Now().Month(), 12, 0, 0, 0, 0, time.Local) }} @card.Card(card.Props{Size: card.SizeSm, Class: "mx-auto w-fit"}) { @card.Content() { @calendar.Calendar(calendar.Props{ Selected: selected, Class: "p-0", }) } @card.Footer(card.FooterProps{Class: "border-t bg-card"}) { @field.Group() { @field.Field() { @field.Label(field.LabelProps{For: "calendar-time-from"}) { Start Time } @inputgroup.InputGroup() { @inputgroup.Input(inputgroup.InputProps{ ID: "calendar-time-from", Type: "time", Value: "10:30:00", Class: "appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none", Attributes: templ.Attributes{ "step": "1", }, }) @inputgroup.Addon() { @icon.Clock2(icon.Props{Class: "text-muted-foreground"}) } } } @field.Field() { @field.Label(field.LabelProps{For: "calendar-time-to"}) { End Time } @inputgroup.InputGroup() { @inputgroup.Input(inputgroup.InputProps{ ID: "calendar-time-to", Type: "time", Value: "12:30:00", Class: "appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none", Attributes: templ.Attributes{ "step": "1", }, }) @inputgroup.Addon() { @icon.Clock2(icon.Props{Class: "text-muted-foreground"}) } } } } } }}Booked dates
package examples import (package examples import ( "time" "github.com/axadrn/shadcn-templ/v2/components/calendar" "github.com/axadrn/shadcn-templ/v2/components/card") templ CalendarBookedDates() { {{ selected := time.Date(time.Now().Year(), 1, 6, 0, 0, 0, 0, time.Local) booked := make([]time.Time, 15) for i := range booked { booked[i] = time.Date(time.Now().Year(), 1, 12+i, 0, 0, 0, 0, time.Local) } }} @card.Card(card.Props{Class: "mx-auto w-fit p-0"}) { @card.Content(card.ContentProps{Class: "p-0"}) { @calendar.Calendar(calendar.Props{ Selected: selected, BookedDates: booked, }) } }}Custom Cell Size
package examples import (package examples import ( "time" "github.com/axadrn/shadcn-templ/v2/components/calendar" "github.com/axadrn/shadcn-templ/v2/components/card") templ CalendarCustomCellSize() { {{ from := time.Date(time.Now().Year(), 12, 8, 0, 0, 0, 0, time.Local) to := from.AddDate(0, 0, 10) }} @card.Card(card.Props{Class: "mx-auto w-fit p-0"}) { @card.Content(card.ContentProps{Class: "p-0"}) { @calendar.Calendar(calendar.Props{ ID: "calendar-custom-cell-size", Mode: calendar.ModeRange, Selected: from, EndValue: to, CaptionLayout: calendar.CaptionLayoutDropdown, Class: "[--cell-size:--spacing(10)] md:[--cell-size:--spacing(12)]", }) } } <script> (() => { const root = () => document.getElementById("calendar-custom-cell-size"); function decorate() { root().querySelectorAll("[data-tui-calendar-day]").forEach((btn) => { if (btn.querySelector("span") || btn.getAttribute("data-outside") === "true") return; const date = new Date(btn.getAttribute("data-tui-calendar-day")); const weekend = date.getDay() === 0 || date.getDay() === 6; const price = document.createElement("span"); price.textContent = weekend ? "$120" : "$100"; btn.appendChild(price); }); } root().addEventListener("calendar-rendered", decorate); decorate(); })(); </script>}You can customize the size of calendar cells using the --cell-size CSS variable. You can also make it responsive by using breakpoint-specific values:
Or use fixed values:
Week Numbers
Use ShowWeekNumber to show week numbers.
package examples import (package examples import ( "time" "github.com/axadrn/shadcn-templ/v2/components/calendar" "github.com/axadrn/shadcn-templ/v2/components/card") templ CalendarWeekNumbers() { {{ selected := time.Date(time.Now().Year(), 1, 12, 0, 0, 0, 0, time.Local) }} @card.Card(card.Props{Class: "mx-auto w-fit p-0"}) { @card.Content(card.ContentProps{Class: "p-0"}) { @calendar.Calendar(calendar.Props{ Selected: selected, ShowWeekNumber: true, }) } }}API Reference
Calendar
The Calendar component displays a month grid for selecting a date or a range of dates.