# Calendar

- Page: <https://kznlabs.github.io/labsUI/components/calendar>

## Calendar (`calendar`, component)

Month grid on the WAI-ARIA date-grid pattern: single date or range with a hover preview, min/max and custom disabled days, months that slide in from the direction of travel. Arrows, Home/End and PageUp/PageDown (+Shift for years). Hydration-safe: today is only marked in the browser.

- Install: `npx @kznlabs/labsui add calendar`
- Docs: <https://kznlabs.github.io/labsUI/components/calendar>
- Brings: button, button-variants, use-controllable-state, utils
- npm: clsx@^2.1.1, lucide-react@1.63.0, motion@14.7.1, tailwind-merge@^3.7.0

### API

- `key(date: Date) => string`: Local YYYY-MM-DD; sorts like the dates it names.
- `<Calendar>`: Month grid on the WAI-ARIA date-grid pattern. Single date or range (with a hover preview),
min/max and custom disabled days, months slide in from the direction of travel. Keyboard:
arrows by day and week, Home/End to the week's ends, PageUp/PageDown by month (+Shift: year).
  - `autoFocus?: boolean`: Focus the current day on mount (DatePicker sets this).
  - `defaultMonth?: Date`: Month shown at first render (uncontrolled).
  - `defaultValue?: Date | DateRange | null`: Day or range picked at first render (uncontrolled).
  - `isDisabled?: (date: Date) => boolean`: Extra rule, e.g. weekends off. Client-only (a function).
  - `locale?: string`: BCP 47 locale for month and weekday names.
  - `max?: Date`: Latest selectable day.
  - `min?: Date`: Earliest selectable day.
  - `mode?: "single" | "range"`: "single": pick one day. "range": pick a start, then an end.
  - `month?: Date`: Displayed month (any day in it). Controlled with `onMonthChange`, or start at `defaultMonth`.
  - `onMonthChange?: (month: Date) => void`: Called when the user pages or arrows into another month.
  - `onValueChange?: ((date: Date) => void) | ((range: DateRange) => void)`: Called with the picked day, or with the range as it is picked.
  - `value?: Date | DateRange | null`: Controlled day, or `{ from, to }` in range mode; null = nothing picked.
  - `weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6`: 0 is Sunday, 6 is Saturday. Default 1 (Monday, ISO).

- `type DateRange = { from?: Date; to?: Date }`

### Usage

```tsx
<Calendar mode="range" value={range} onValueChange={setRange} min={today} isDisabled={(d) => d.getDay() === 0} />
```

### Example: booking-calendar.tsx

```tsx
"use client";

import { useState } from "react";
import { Calendar, type DateRange } from "@/components/ui/calendar";

const weekend = (d: Date) => d.getDay() === 0 || d.getDay() === 6;

export function BookingCalendar() {
  const [stay, setStay] = useState<DateRange>({});
  return <Calendar mode="range" value={stay} onValueChange={setStay} isDisabled={weekend} />;
}
```
