Calendar
Month grid — one date, a range, or a handful of dates.
Walkthrough
1. Basic
One date, bound. The value is a Date at local midnight; the caption opens a month and year grid for jumping further than a few presses.
Sunday, September 27, 2026
<script lang="ts"> import { Calendar, Text, latn } from 'omaris'; let day = $state<Date | null>(new Date()); const long = new Intl.DateTimeFormat('en-US', latn({ dateStyle: 'full' }));</script><div class="flex flex-col items-start gap-2"> <Calendar bind:value={day} class="rounded-shape-lg border border-border" /> <Text variant="body-sm" tone="muted">{day ? long.format(day) : 'No date'}</Text></div> 2. Range
mode="range": the first press starts it, the second ends it, and in between the band follows the pointer or the focus. months={2} puts two side by side from sm up and stacks them below.
Sep 30 – Oct 5
<script lang="ts"> import { Calendar, Text, addDays, startOfDay, latn, type DateRange } from 'omaris'; const today = startOfDay(new Date()); let stay = $state<DateRange | null>({ start: addDays(today, 3), end: addDays(today, 8) }); const short = new Intl.DateTimeFormat('en-US', latn({ month: 'short', day: 'numeric' }));</script><div class="flex flex-col items-start gap-2"> <Calendar mode="range" months={2} min={today} bind:value={stay} class="rounded-shape-lg border border-border" /> <Text variant="body-sm" tone="muted"> {stay ? short.formatRange(stay.start, stay.end) : 'Pick a check-in day'} </Text></div> 3. Multiple and bounds
mode="multiple" toggles days in and out of a sorted array. min, max and isDateDisabled take days off the table — here, the next six weeks with Fridays and Saturdays closed — and showWeekNumbers adds the ISO week.
0 shifts picked
<script lang="ts"> import { Calendar, Text, addDays, startOfDay } from 'omaris'; const today = startOfDay(new Date()); let shifts = $state<Date[]>([]); const closed = (date: Date) => date.getDay() === 5 || date.getDay() === 6;</script><div class="flex flex-col items-start gap-2"> <Calendar mode="multiple" bind:value={shifts} min={today} max={addDays(today, 42)} isDateDisabled={closed} showWeekNumbers class="rounded-shape-lg border border-border" /> <Text variant="body-sm" tone="muted"> {shifts.length === 1 ? '1 shift' : `${shifts.length} shifts`} picked </Text></div> 4. Locale
Names come from Intl and the first weekday from the locale — Saturday in Iraq, Monday in Germany. Inside dir="rtl" the arrows, the keys and the band all mirror, and the digits stay 0–9.
<script lang="ts"> import { Calendar } from 'omaris';</script><div class="flex flex-wrap items-start gap-4"> <div dir="rtl" lang="ar-IQ"> <Calendar locale="ar-IQ" class="rounded-shape-lg border border-border" /> </div> <Calendar locale="de-DE" weekdayFormat="short" class="rounded-shape-lg border border-border" /></div> 5. Overridden
class is the root, so a card's padding replaces the calendar's own, and classes reaches every part — here square faces, a tinted caption and a wider cell through the --cal-cell property the grid is sized from.
<script lang="ts"> import { Calendar } from 'omaris';</script><div class="w-full max-w-sm rounded-shape-xl bg-surface-container-low p-2"> <Calendar class="flex w-full p-1 [--cal-cell:3rem]" aria-label="Delivery day" classes={{ face: 'rounded-shape-sm', caption: 'text-primary', weekday: 'text-label-sm uppercase' }} /></div>