Fluixi UI
GitHub ↗

Examples

Loading preview…

calendar

Accessible, internationalised calendar and date-range calendar.


A headless month-grid calendar following the WAI-ARIA grid pattern. Locale drives the month/weekday names, the calendar system (Gregorian, Buddhist, Hebrew, Islamic…) and the first day of the week. Full keyboard navigation, min/max bounds, per-date availability, and a two-click range mode. Date math is powered by @fluixi/date-core (built on @internationalized/date), so values are immutable and time-zone safe.

Installation

pnpm add @fluixi/calendar

Usage

import {
  Calendar,
  CalendarHeader,
  CalendarHeading,
  CalendarPrevButton,
  CalendarNextButton,
  CalendarGrid,
} from '@fluixi/calendar';
import { today, getLocalTimeZone } from '@fluixi/date-core';

<Calendar locale="en-US" defaultValue={today(getLocalTimeZone())} onChange={console.log}>
  <CalendarHeader>
    <CalendarPrevButton></CalendarPrevButton>
    <CalendarHeading />
    <CalendarNextButton></CalendarNextButton>
  </CalendarHeader>
  <CalendarGrid />
</Calendar>

Range calendar

RangeCalendar swaps single-date selection for a two-click range. The first click sets an anchor; the grid previews anchor → cursor as the pointer or keyboard sweeps, and the next click commits an ordered { start, end }.

import { RangeCalendar, CalendarGrid } from '@fluixi/calendar';

<RangeCalendar locale="fr-FR" onChange={(range) => console.log(range?.start, range?.end)}>
  <CalendarGrid />
</RangeCalendar>

Props (Calendar / RangeCalendar)

Prop Type Default Description
locale string BCP-47 locale; drives names, week start and calendar system.
value DateValue | DateRange | null Controlled selection (a date, or { start, end } for ranges).
defaultValue DateValue | DateRange | null Initial uncontrolled selection.
onChange (value) => void Fired when the selection changes.
minValue DateValue Earliest selectable date; disables earlier cells and paging.
maxValue DateValue Latest selectable date.
isDateUnavailable (date) => boolean Marks individual dates unavailable (e.g. booked days).
isDisabled boolean false Disables the whole calendar.
isReadOnly boolean false Selection is fixed but still focusable.
defaultFocusedValue DateValue today Month/day the grid opens on when nothing is selected.
firstDayOfWeek 'sun' … 'sat' locale Overrides the locale's natural week start.
visibleDuration DateDuration { months: 1 } How much is visible at once.
timeZone string local IANA zone used for today / conversions.
createCalendar (id) => Calendar Gregorian Inject a non-Gregorian calendar system.

Parts

Component Element Description
Calendar / RangeCalendar div[role=group] Root; owns state and provides context.
CalendarHeader div Layout row for the nav controls and heading.
CalendarHeading h2 Live, locale-formatted month + year.
CalendarPrevButton / CalendarNextButton button Page by the visible duration; auto-disable at bounds.
CalendarGrid table[role=grid] Weekday header + week rows; owns keyboard navigation.

Day cells expose data-* hooks for styling: data-selected, data-today, data-disabled, data-unavailable, data-outside-month, and, for ranges, data-selection-start / data-selection-end.

Keyboard

Key Action
/ Previous / next day
/ Previous / next week
Home / End First / last day of the week
Page Up / Page Down Previous / next month
Shift + Page Up/Down Previous / next year
Enter / Space Select the focused day