Calendar
Locale-aware calendar primitive that gives you precomputed month/day metadata, weekend info, text direction, and focusable grid navigation so you can render any UI you want.
Usage
Pass a View snippet that receives CalendarData and bind to the api for helpers like format, sameDay, and month navigation.
<script lang="ts">
import { Calendar, type CalendarApi } from '@obelus/trioxide';
import '@obelus/trioxide/index.css';
let locale = $state('en-US');
let api = $state({}) as CalendarApi;
</script>
<Calendar
{locale}
bind:api
onGridNavigationInlineEnd={api.goToNextMonth}
onGridNavigationInlineStart={api.goToPrevMonth}
>
{#snippet View({ activeDate, days, weekDaysNames, dir, useGridNavigation })}
<div {dir}>
<header>
<button on:click={api.goToPrevMonth} aria-label="Previous month">←</button>
<span>{api.format(activeDate!, { month: 'long', year: 'numeric' })}</span>
<button on:click={api.goToNextMonth} aria-label="Next month">→</button>
</header>
<div class="weekdays">
{#each weekDaysNames as d}
<span class:weekend={d.isWeekend}>{d.short}</span>
{/each}
</div>
<div class="days">
{#each days as day}
<button {...useGridNavigation} disabled={day.isPrevMonth || day.isNextMonth}>
{api.format(day.date, { day: 'numeric' })}
</button>
{/each}
</div>
</div>
{/snippet}
</Calendar> useGridNavigation wires up arrow-key movement across your buttons and calls the onGridNavigation… callbacks when focus would leave the grid (handy for jumping to the next/previous month).
Calendar data
activeDate: anchor date for the current view (defaults to today).days: array of day objects for the rendered range; each hasdate,isToday,isWeekend,isPrevMonth, andisNextMonth.weekDaysNames: localized weekday labels (long,narrow,short) plusisWeekend.weekStartOffset: how many days from the locale’s first day of week to the start of the month (useful for CSS grid placement).dir:'ltr'|'rtl'inferred from the locale; apply to your container so grid navigation matches.useGridNavigation: Svelte action to attach to focusable day cells for keyboard movement.
Props
View(required): snippet receivingCalendarDatato render the UI.locale: BCP 47 locale used for formatting, weekends, week start, and direction; defaults tonavigator.languages[0].show:'extended'(default 6-row view padded with prev/next month),'month'(only the active month), or a number of additional months to include (e.g.show={1}renders the active month plus the next).activeDate/bind:activeDate: controls which month is shown and updates when navigation happens.api/bind:api: receives the populatedCalendarApi.onGridNavigationInlineStart/onGridNavigationInlineEnd/onGridNavigationBlockStart/onGridNavigationBlockEnd: callbacks invoked when arrow navigation tries to leave the current grid in that direction.
CalendarApi
goToNextMonth(),goToPrevMonth(),goToToday(): updateactiveDate.format(date, options?)/formatToParts(date, options?): localized formatting helpers bound to the chosen locale.sameDay(a, b): compares dates ignoring time.isBetween(date, start, end): inclusive range check (useful for range highlighting).