Overview
The Calendar component provides a visual calendar interface for selecting dates. It supports both single date selection and date range selection with customizable min/max dates.
Installation
import { Calendar } from '@svelte-atoms/core';
Basic Usage
<script>
import { Calendar } from '@svelte-atoms/core';
</script>
<Calendar.Root>
<Calendar.Header />
<Calendar.Body>
{#snippet children({ day })}
<Calendar.Day {day} />
{/snippet}
</Calendar.Body>
</Calendar.Root>
Calendar.Root Props
The selected date (single mode)
range
[Date | undefined, Date | undefined]
Selected date range [start, end]
The currently displayed month/year
type
'single' | 'range'
default:"single"
Selection mode
Additional custom properties
Custom factory function for creating calendar bond
onchange
(ev: CustomEvent, params: { range: CalendarRange; pivote: Date }) => void
Callback fired when date selection changes
Calendar.Day Props
Day object containing date information
HTML element type to render
Click handler for the day
preset
string
default:"calendar.day"
Preset key for styling
Day Object Structure
The Day type contains the following properties:
type Day = {
id: number;
date: Date;
dayOfMonth: number;
offmonth: boolean; // Day belongs to previous/next month
today: boolean; // Is today's date
week: number; // Week number (0-5)
month: number; // Month number
disabled: boolean; // Is disabled (outside min/max)
weekend: boolean; // Is weekend (Sunday)
name: string; // Short name (e.g., "Mon")
fullname: string; // Full name (e.g., "Monday")
fromNextMonth: boolean; // From next month
fromPreviousMonth: boolean; // From previous month
};
Extends all HtmlAtomProps. Typically contains navigation controls for month/year.
Calendar.Body Props
Extends all HtmlAtomProps. Container for the calendar grid.
Calendar.WeekDay Props
Extends all HtmlAtomProps. Displays weekday names.
Subcomponents
Calendar.Root
Root container managing calendar state and date logic.
Header section typically containing month/year navigation.
Calendar.Body
Body section containing the calendar grid of days.
Calendar.Day
Individual day cell in the calendar.
Calendar.WeekDay
Weekday name labels (Mon, Tue, Wed, etc.).
Examples
Single Date Selection
<script>
import { Calendar } from '@svelte-atoms/core';
let selectedDate = $state<Date | undefined>(undefined);
</script>
<Calendar.Root bind:value={selectedDate} type="single">
<Calendar.Header />
<Calendar.Body>
{#snippet children({ day })}
<Calendar.Day {day} />
{/snippet}
</Calendar.Body>
</Calendar.Root>
{#if selectedDate}
<p>Selected: {selectedDate.toDateString()}</p>
{/if}
Date Range Selection
<script>
import { Calendar } from '@svelte-atoms/core';
import type { CalendarRange } from '@svelte-atoms/core';
let range = $state<CalendarRange>([undefined, undefined]);
</script>
<Calendar.Root bind:range type="range">
<Calendar.Header />
<Calendar.Body>
{#snippet children({ day })}
<Calendar.Day {day} />
{/snippet}
</Calendar.Body>
</Calendar.Root>
{#if range[0] && range[1]}
<p>From: {range[0].toDateString()} To: {range[1].toDateString()}</p>
{/if}
With Min/Max Dates
<script>
import { Calendar } from '@svelte-atoms/core';
import { addDays, subDays } from 'date-fns';
const today = new Date();
const minDate = subDays(today, 7);
const maxDate = addDays(today, 14);
</script>
<Calendar.Root min={minDate} max={maxDate}>
<Calendar.Header />
<Calendar.Body>
{#snippet children({ day })}
<Calendar.Day {day} />
{/snippet}
</Calendar.Body>
</Calendar.Root>
Custom Day Rendering
<script>
import { Calendar } from '@svelte-atoms/core';
</script>
<Calendar.Root>
<Calendar.Header />
<Calendar.Body>
{#snippet children({ day })}
<button
class="calendar-day"
class:offmonth={day.offmonth}
class:today={day.today}
class:disabled={day.disabled}
class:weekend={day.weekend}
>
{day.dayOfMonth}
</button>
{/snippet}
</Calendar.Body>
</Calendar.Root>
<script>
import { Calendar } from '@svelte-atoms/core';
import { format } from 'date-fns';
let pivote = $state(new Date());
function previousMonth() {
pivote = new Date(pivote.getFullYear(), pivote.getMonth() - 1, 1);
}
function nextMonth() {
pivote = new Date(pivote.getFullYear(), pivote.getMonth() + 1, 1);
}
</script>
<Calendar.Root bind:pivote>
<Calendar.Header class="flex items-center justify-between p-4">
<button onclick={previousMonth}><</button>
<span class="font-semibold">{format(pivote, 'MMMM yyyy')}</span>
<button onclick={nextMonth}>></button>
</Calendar.Header>
<Calendar.Body>
{#snippet children({ day })}
<Calendar.Day {day} />
{/snippet}
</Calendar.Body>
</Calendar.Root>
Accessibility
- Keyboard navigation with arrow keys
- Enter/Space to select dates
- Screen reader support with ARIA attributes
- Disabled dates are not selectable
- Visual indicators for today, selected dates, and date ranges