Calendar
The Calendar component provides an accessible date picker with a clean, modern interface. It’s perfect for forms, booking interfaces, and any application requiring date selection.
Note: The Calendar component is currently experiencing rendering issues due to a dependency conflict. The examples below show the code but not the live components. We’re working on a fix.
Usage
<script>
import { Calendar } from "$lib/components/ui/calendar";
let date = new Date();
</script>
<Calendar bind:value={date} />
Examples
Basic Calendar
A simple calendar for picking a single date.
With Default Placeholder
A calendar with a placeholder date.
With Custom Weekday Format
Customize how weekday names are displayed.
Disabled Calendar
A calendar that cannot be interacted with.
With Date Range Selection
A calendar demonstrating how to implement date range selection.
With Unavailable Dates
A calendar showing some dates as unavailable.
API Reference
Calendar Components
Component | Description |
---|---|
Calendar | The root calendar component. |
Calendar.Header | The header section of the calendar. |
Calendar.Heading | Displays the current month and year. |
Calendar.PrevButton | Button to navigate to the previous month. |
Calendar.NextButton | Button to navigate to the next month. |
Calendar.Months | Container for the month views. |
Calendar.Grid | The grid layout for calendar dates. |
Calendar.GridHead | The header for the calendar grid. |
Calendar.GridBody | The body of the calendar grid containing dates. |
Calendar.GridRow | A row in the calendar grid. |
Calendar.HeadCell | A cell in the calendar header. |
Calendar.Cell | A cell in the calendar body. |
Calendar.Day | The interactive day element. |
Calendar Root Properties
Property | Type | Default | Description |
---|---|---|---|
value | Date | undefined | The selected date value. |
placeholder | Date | undefined | Displayed date when no date is selected. |
weekdayFormat | "narrow" \| "short" \| "long" | "short" | Format for weekday names. |
disabled | boolean | false | Whether the calendar is disabled. |
readonly | boolean | false | Whether the calendar is readonly. |
isDateDisabled | (date: Date) => boolean | undefined | Function to determine if a date should be disabled. |
isDateUnavailable | (date: Date) => boolean | undefined | Function to determine if a date is unavailable. |
fromDate | Date | undefined | Minimum selectable date. |
toDate | Date | undefined | Maximum selectable date. |
numberOfMonths | number | 1 | Number of months to display. |
fixedWeeks | boolean | false | Whether to always show 6 weeks per month. |
locale | string | Browser’s locale | The locale to use for formatting. |
class | string | undefined | Custom CSS classes. |
ref | HTMLDivElement | undefined | A reference to the underlying HTML element. |
Calendar Day Properties
Property | Type | Default | Description |
---|---|---|---|
selected | boolean | false | Whether the day is selected. |
outside | boolean | false | Whether the day is outside the current month. |
disabled | boolean | false | Whether the day is disabled. |
unavailable | boolean | false | Whether the day is unavailable. |
today | boolean | false | Whether the day is today. |
class | string | undefined | Custom CSS classes. |
ref | HTMLButtonElement | undefined | A reference to the underlying HTML element. |
Implementation
The Calendar component is built on top of bits-ui primitives. The main implementation renders a composable calendar structure with proper semantic markup and ARIA attributes for accessibility:
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import * as Calendar from "./index.js";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
value = $bindable(),
placeholder = $bindable(),
class: className,
weekdayFormat = "short",
...restProps
}: CalendarPrimitive.RootProps = $props();
</script>
<CalendarPrimitive.Root
bind:value
bind:ref
bind:placeholder
{weekdayFormat}
class={cn("p-3", className)}
{...restProps}
>
{#snippet children({ months, weekdays })}
<Calendar.Header>
<Calendar.PrevButton />
<Calendar.Heading />
<Calendar.NextButton />
</Calendar.Header>
<Calendar.Months>
{#each months as month}
<Calendar.Grid>
<Calendar.GridHead>
<Calendar.GridRow class="flex">
{#each weekdays as weekday}
<Calendar.HeadCell>
{weekday.slice(0, 2)}
</Calendar.HeadCell>
{/each}
</Calendar.GridRow>
</Calendar.GridHead>
<Calendar.GridBody>
{#each month.weeks as weekDates}
<Calendar.GridRow class="mt-2 w-full">
{#each weekDates as date}
<Calendar.Cell {date} month={month.value}>
<Calendar.Day />
</Calendar.Cell>
{/each}
</Calendar.GridRow>
{/each}
</Calendar.GridBody>
</Calendar.Grid>
{/each}
</Calendar.Months>
{/snippet}
</CalendarPrimitive.Root>
The Calendar.Day component is styled with Tailwind CSS and includes various states such as today, selected, disabled, and unavailable to provide clear visual feedback.