Calendar
Import
Section titled “Import”import { Calendar } from '@delightstack/components';The CalendarEvent and MarkedDate types are also exported:
import type { CalendarEvent, MarkedDate } from '@delightstack/components';Basic Usage
Section titled “Basic Usage”July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<script> import { Calendar } from '@delightstack/components';
let selectedDate = $state<Date | undefined>(undefined);</script>
<Calendar bind:value={selectedDate} />The container is transparent by default so it drops onto any surface. Add filled for a subtle surface, or outline for a hairline border — both give it generously rounded card corners. They can be combined.
Default (transparent)
July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Filled
July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Outline
July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<!-- Transparent (default) --><Calendar bind:value={date} />
<!-- Subtle surface fill --><Calendar bind:value={date} filled />
<!-- Hairline outline --><Calendar bind:value={date} outline />Examples
Section titled “Examples”Density
Section titled “Density”Use dense for compact spacing or comfortable for a roomier layout. The corner radius scales with the density.
Dense
July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Comfortable
July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<!-- Compact --><Calendar bind:value={date} outline dense />
<!-- Roomy --><Calendar bind:value={date} outline comfortable />Single Date Selection
Section titled “Single Date Selection”July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<script> let date = $state<Date | undefined>(undefined);</script>
<Calendar bind:value={date} />Date Range Selection
Section titled “Date Range Selection”First click sets the start date, second click sets the end date. Hovering between clicks previews the range.
July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<script> let dateRange = $state<[Date, Date] | undefined>(undefined);</script>
<Calendar mode="range" bind:value={dateRange} />Multiple Date Selection
Section titled “Multiple Date Selection”Click to toggle individual dates on or off.
July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<script> let selectedDates = $state<Date[]>([]);</script>
<Calendar mode="multiple" bind:value={selectedDates} />With Date Constraints
Section titled “With Date Constraints”July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<Calendar bind:value={date} min={new Date()} max={new Date(2026, 11, 31)}/>With Marked Dates
Section titled “With Marked Dates”March 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<Calendar bind:value={date} marked={[ { date: new Date(2026, 2, 15), color: 'var(--color-action)', label: 'Meeting' }, { date: new Date(2026, 2, 20), color: 'var(--color-error)', label: 'Deadline' }, ]}/>With Events
Section titled “With Events”March 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<script> const events = [ { id: '1', title: 'Team Standup', start: new Date(2026, 2, 12) }, { id: '2', title: 'Sprint Review', start: new Date(2026, 2, 15), end: new Date(2026, 2, 16), color: '#10b981' }, ];</script>
<Calendar bind:value={date} events={events} />Locale and Week Start
Section titled “Locale and Week Start”German (Monday start)
Juli 2026
Mo
Di
Mi
Do
Fr
Sa
So
US English (Sunday start)
July 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
View code
<!-- German locale, Monday start --><Calendar bind:value={date} locale="de-DE" week_starts_on={1} />
<!-- US locale, Sunday start --><Calendar bind:value={date} locale="en-US" week_starts_on={0} />With Time Slots
Section titled “With Time Slots”July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
View code
<Calendar bind:value={date} outline show_time_slots time_slot_interval={15} time_slot_min="09:00" time_slot_max="17:00" ontimeslotselect={({ time, date }) => console.log(time, date)}/>Skeleton Loading
Section titled “Skeleton Loading”View code
<Calendar skeleton={loading} bind:value={date} />| Prop | Type | Default | Description |
|---|---|---|---|
value | Date | Date[] | [Date, Date] | - | Selected date(s), bindable |
mode | 'single' | 'range' | 'multiple' | 'single' | Selection mode |
month | Date | new Date() | Currently displayed month, bindable |
min | Date | - | Minimum selectable date |
max | Date | - | Maximum selectable date |
disabled | Date[] | ((date: Date) => boolean) | [] | Disabled dates (array or predicate function) |
marked | MarkedDate[] | [] | Dates with colored dot markers |
events | CalendarEvent[] | [] | Events to display on dates |
week_starts_on | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 1 | First day of week (0=Sunday) |
locale | string | - | BCP 47 locale string for formatting |
show_time_slots | boolean | false | Show time slot picker alongside calendar |
time_slot_interval | number | 30 | Time slot interval in minutes |
time_slot_min | string | '00:00' | Earliest time slot |
time_slot_max | string | '23:59' | Latest time slot |
dense | boolean | false | Compact cell spacing |
comfortable | boolean | false | Relaxed cell spacing |
filled | boolean | false | Fill the container with a subtle surface (card look) |
outline | boolean | false | Add a 1px outline + rounded corners (transparent fill) |
skeleton | boolean | false | Show loading skeleton |
id | string | auto | Element ID |
class | string | '' | Additional CSS classes |
Events
Section titled “Events”| Event | Detail | Description |
|---|---|---|
onselect | { value: Date | Date[] | [Date, Date] } | Selection changed |
onmonthchange | { month: Date } | Navigated to a different month |
ontimeslotselect | { time: string, date: Date } | Time slot selected |
interface CalendarEvent { id: string; title: string; start: Date; end?: Date; color?: string; allDay?: boolean;}
interface MarkedDate { date: Date; color?: string; label?: string;}Accessibility
Section titled “Accessibility”- Calendar container has
role="group"witharia-label="Calendar" - Day grid has
role="grid"witharia-label="Calendar dates" - Weekday headers use
role="columnheader" - Each day cell is a
<button>withrole="gridcell",aria-selected, andaria-disabled - Today and event information included in each cell’s
aria-label - Month/year header uses
aria-live="polite"for screen reader announcements - Navigation buttons have
aria-label(“Previous month”, “Next month”) - Time slots panel has
role="listbox"withrole="option"on each slot - Full keyboard navigation:
- Arrow keys move focus between days
- Page Up / Page Down moves by month (with Shift, by year)
- Home / End moves to start/end of week
- Enter / Space selects the focused date
- Focus wraps across month boundaries automatically
- Respects
prefers-reduced-motion