Calendar
A date picker component with month navigation and single or range selection.
March 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
single
range
#Installation
bunx --bun barefoot add calendar#Usage
March 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
March 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
April 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
March 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
1"use client"23import { createSignal } from "@barefootjs/dom"4import { Calendar } from "@/components/ui/calendar"56function CalendarDemo() {7 const [selected, setSelected] = createSignal<Date | undefined>()89 return (10 <div className="space-y-4">11 {/* Single date selection */}12 <Calendar13 mode="single"14 selected={selected()}15 onSelect={setSelected}16 />1718 {/* Range selection */}19 <Calendar mode="range" numberOfMonths={2} />2021 {/* With constraints (next 30 days only) */}22 <Calendar23 mode="single"24 fromDate={new Date()}25 toDate={new Date(Date.now() + 30 * 86400000)}26 />27 </div>28 )29}#Examples
#Basic
March 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
No date selected
1"use client"23import { createSignal, createMemo } from "@barefootjs/dom"4import { Calendar } from "@/components/ui/calendar"56export function CalendarBasicDemo() {7 const [date, setDate] = createSignal<Date | undefined>(undefined)89 const formattedDate = createMemo(() => {10 const d = date()11 if (!d) return 'No date selected'12 return d.toLocaleDateString('en-US', {13 weekday: 'long',14 year: 'numeric',15 month: 'long',16 day: 'numeric',17 })18 })1920 return (21 <div className="flex flex-col items-center gap-4">22 <Calendar selected={date()} onSelect={setDate} />23 <p className="text-sm text-muted-foreground">{formattedDate()}</p>24 </div>25 )26}#Form
Book an appointment
March 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
1"use client"23import { createSignal, createMemo } from "@barefootjs/dom"4import { Calendar } from "@/components/ui/calendar"56export function CalendarFormDemo() {7 const today = new Date()8 const [date, setDate] = createSignal<Date | undefined>(undefined)9 const [name, setName] = createSignal('')1011 const canSubmit = createMemo(() => date() !== undefined && name().length > 0)1213 const formattedDate = createMemo(() => {14 const d = date()15 if (!d) return ''16 return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })17 })1819 return (20 <div className="space-y-4 max-w-sm">21 <div className="space-y-2">22 <h4 className="text-sm font-medium">Book an appointment</h4>23 <div className="space-y-2">24 <label className="text-sm text-muted-foreground">Name</label>25 <input26 className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs"27 placeholder="Your name"28 value={name()}29 onInput={(e: Event) => setName((e.target as HTMLInputElement).value)}30 />31 </div>32 <div className="space-y-2">33 <label className="text-sm text-muted-foreground">Date</label>34 <Calendar35 selected={date()}36 onSelect={setDate}37 fromDate={today}38 />39 {date() && (40 <p className="text-sm text-muted-foreground">41 Selected: {formattedDate()}42 </p>43 )}44 </div>45 </div>46 <button47 className="inline-flex ... bg-primary text-primary-foreground disabled:opacity-50"48 disabled={!canSubmit()}49 >50 Book Appointment51 </button>52 </div>53 )54}#Constraints
Schedule a meeting
Weekdays only, within the next 30 days
March 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Select a weekday
1"use client"23import { createSignal, createMemo } from "@barefootjs/dom"4import { Calendar } from "@/components/ui/calendar"56export function CalendarWithConstraintsDemo() {7 const today = new Date()8 const maxDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30)9 const [date, setDate] = createSignal<Date | undefined>(undefined)1011 // Disable weekends (Saturday=6, Sunday=0)12 const isWeekend = (d: Date) => d.getDay() === 0 || d.getDay() === 61314 const formattedDate = createMemo(() => {15 const d = date()16 if (!d) return 'Select a weekday'17 return d.toLocaleDateString('en-US', { weekday: 'long', month: 'short', day: 'numeric' })18 })1920 return (21 <div className="flex flex-col items-center gap-4">22 <div className="text-center space-y-1">23 <h4 className="text-sm font-medium">Schedule a meeting</h4>24 <p className="text-xs text-muted-foreground">Weekdays only, within the next 30 days</p>25 </div>26 <Calendar27 selected={date()}28 onSelect={setDate}29 fromDate={today}30 toDate={maxDate}31 disabled={isWeekend}32 />33 <p className="text-sm text-muted-foreground">{formattedDate()}</p>34 </div>35 )36}#API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| mode | 'single' | 'range' | 'single' | Selection mode: single date or date range. |
| selected | Date | - | The currently selected date (controlled, single mode). |
| onSelect | (date: Date | undefined) => void | - | Callback when a date is selected (single mode). |
| selectedRange | { from?: Date; to?: Date } | - | The currently selected range (controlled, range mode). |
| onRangeSelect | (range: { from?: Date; to?: Date }) => void | - | Callback when a range is selected (range mode). |
| fromDate | Date | - | Minimum selectable date. |
| toDate | Date | - | Maximum selectable date. |
| numberOfMonths | number | 1 | Number of months to display side by side. |
| className | string | - | Additional CSS classes. |