> ## Documentation Index
> Fetch the complete documentation index at: https://araf.badr.co.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Calendar

> A standalone month-view calendar for date and date-range selection — the base component used by Date Picker.

## Overview

<div style={{padding:"28px 24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",justifyContent:"center"}}>
  <div style={{background:"#fff",border:"1px solid #E5E7EB",borderRadius:"12px",boxShadow:"0 2px 8px rgba(0,0,0,0.06)",padding:"16px",width:"260px",fontFamily:"Inter,sans-serif"}}>
    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"12px"}}>
      <button style={{border:"none",background:"none",cursor:"pointer",color:"#71717A",fontSize:"16px",padding:"2px 8px",borderRadius:"6px"}}>‹</button>
      <span style={{fontSize:"14px",fontWeight:600,color:"#101828"}}>April 2026</span>
      <button style={{border:"none",background:"none",cursor:"pointer",color:"#71717A",fontSize:"16px",padding:"2px 8px",borderRadius:"6px"}}>›</button>
    </div>

    <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"2px",textAlign:"center",marginBottom:"4px"}}>
      {["Su","Mo","Tu","We","Th","Fr","Sa"].map(d => (
                  <div key={d} style={{fontSize:"11px",color:"#9CA3AF",padding:"4px 0",fontWeight:500}}>{d}</div>
                ))}
    </div>

    <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"2px",textAlign:"center"}}>
      {["","","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30"].map((d,i) => (
                  <div key={i} style={{fontSize:"13px",padding:"5px 0",borderRadius:"6px",cursor:d?"pointer":"default",background:d==="2"?"#0479CE":d==="1"||d==="3"||d==="4"?"#EFF8FF":"transparent",color:d==="2"?"#fff":d==="1"||d==="3"||d==="4"?"#0479CE":d?"#344054":"transparent",fontWeight:d==="2"?600:400}}>{d}</div>
                ))}
    </div>
  </div>
</div>

**Calendar** is a standalone month-view grid for selecting a date or date range. It is the underlying component used by `DatePicker` and `DateRangePicker` — use Calendar directly when you need an always-visible calendar (not in a popover).

<Note>
  Need a calendar inside a popover trigger? Use `DatePicker` instead. Calendar is for always-visible inline calendar UIs.
</Note>

***

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @araf-ds/core
  ```

  ```bash yarn theme={null}
  yarn add @araf-ds/core
  ```

  ```bash pnpm theme={null}
  pnpm add @araf-ds/core
  ```
</CodeGroup>

***

## Usage

```tsx theme={null}
import { Calendar } from "@araf-ds/core"
import { useState } from "react"

export default function Example() {
  const [date, setDate] = useState<Date | undefined>(new Date())

  return (
    <Calendar
      mode="single"
      selected={date}
      onSelect={setDate}
    />
  )
}
```

***

## Variants

### Single Date Selection

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",justifyContent:"center"}}>
  <div style={{background:"#fff",border:"1px solid #E5E7EB",borderRadius:"12px",padding:"16px",width:"260px",fontFamily:"Inter,sans-serif"}}>
    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"12px"}}>
      <button style={{border:"none",background:"none",cursor:"pointer",color:"#71717A",fontSize:"16px",padding:"2px 8px"}}>‹</button>
      <span style={{fontSize:"14px",fontWeight:600,color:"#101828"}}>April 2026</span>
      <button style={{border:"none",background:"none",cursor:"pointer",color:"#71717A",fontSize:"16px",padding:"2px 8px"}}>›</button>
    </div>

    <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"2px",textAlign:"center",marginBottom:"4px"}}>
      {["Su","Mo","Tu","We","Th","Fr","Sa"].map(d => (
                  <div key={d} style={{fontSize:"11px",color:"#9CA3AF",padding:"4px 0",fontWeight:500}}>{d}</div>
                ))}
    </div>

    <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"2px",textAlign:"center"}}>
      {["","","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30"].map((d,i) => (
                  <div key={i} style={{fontSize:"13px",padding:"5px 0",borderRadius:"6px",cursor:d?"pointer":"default",background:d==="15"?"#0479CE":"transparent",color:d==="15"?"#fff":d?"#344054":"transparent",fontWeight:d==="15"?600:400}}>{d}</div>
                ))}
    </div>
  </div>
</div>

```tsx theme={null}
const [date, setDate] = useState<Date | undefined>()

<Calendar
  mode="single"
  selected={date}
  onSelect={setDate}
  initialFocus
/>
```

### Date Range Selection

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",justifyContent:"center"}}>
  <div style={{background:"#fff",border:"1px solid #E5E7EB",borderRadius:"12px",padding:"16px",width:"260px",fontFamily:"Inter,sans-serif"}}>
    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"12px"}}>
      <button style={{border:"none",background:"none",cursor:"pointer",color:"#71717A",fontSize:"16px",padding:"2px 8px"}}>‹</button>
      <span style={{fontSize:"14px",fontWeight:600,color:"#101828"}}>April 2026</span>
      <button style={{border:"none",background:"none",cursor:"pointer",color:"#71717A",fontSize:"16px",padding:"2px 8px"}}>›</button>
    </div>

    <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"2px",textAlign:"center",marginBottom:"4px"}}>
      {["Su","Mo","Tu","We","Th","Fr","Sa"].map(d => (
                  <div key={d} style={{fontSize:"11px",color:"#9CA3AF",padding:"4px 0",fontWeight:500}}>{d}</div>
                ))}
    </div>

    <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"2px",textAlign:"center"}}>
      {["","","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30"].map((d,i) => {
                  const n = parseInt(d);
                  const inRange = n>=5 && n<=12;
                  const isStart = n===5;
                  const isEnd = n===12;
                  return (
                    <div key={i} style={{fontSize:"13px",padding:"5px 0",cursor:d?"pointer":"default",background:isStart||isEnd?"#0479CE":inRange?"#EFF8FF":"transparent",color:isStart||isEnd?"#fff":inRange?"#0479CE":d?"#344054":"transparent",fontWeight:isStart||isEnd?600:400,borderRadius:isStart?"6px 0 0 6px":isEnd?"0 6px 6px 0":inRange?"0":"6px"}}>{d}</div>
                  );
                })}
    </div>
  </div>
</div>

```tsx theme={null}
const [range, setRange] = useState<DateRange | undefined>()

<Calendar
  mode="range"
  selected={range}
  onSelect={setRange}
  numberOfMonths={2}
/>
```

### With Disabled Dates

```tsx theme={null}
<Calendar
  mode="single"
  selected={date}
  onSelect={setDate}
  disabled={[
    { before: new Date() },          // Disable past dates
    { dayOfWeek: [0, 6] },           // Disable weekends
    new Date(2026, 3, 25),           // Disable a specific date
  ]}
/>
```

***

## API Reference

<ParamField path="mode" type="string" required>
  Selection mode. Values: `single` · `multiple` · `range`
</ParamField>

<ParamField path="selected" type="Date | Date[] | DateRange | undefined">
  Controlled selected value. Type depends on `mode`.
</ParamField>

<ParamField path="onSelect" type="(date) => void">
  Callback fired when selection changes. Argument type matches `mode`.
</ParamField>

<ParamField path="defaultMonth" type="Date">
  The month shown on initial render.
</ParamField>

<ParamField path="numberOfMonths" type="number" default="1">
  Number of months to display side by side (useful for range selection).
</ParamField>

<ParamField path="disabled" type="Matcher | Matcher[]">
  Rules for disabled dates. Accepts: `Date`, `DateRange`, `DayOfWeek`, `Before`, `After`, or a function `(date: Date) => boolean`.
</ParamField>

<ParamField path="fromDate" type="Date">
  The earliest navigable and selectable month.
</ParamField>

<ParamField path="toDate" type="Date">
  The latest navigable and selectable month.
</ParamField>

<ParamField path="initialFocus" type="boolean" default="false">
  Auto-focus the calendar on mount — required when used inside a `Dialog` or `Popover`.
</ParamField>

<ParamField path="weekStartsOn" type="number" default="0">
  Day the week starts on. `0` = Sunday, `1` = Monday.
</ParamField>

***

## Accessibility

* Calendar grid uses `role="grid"` with column headers labeled by weekday abbreviation
* Each day cell has `role="gridcell"` with `aria-selected` and `aria-disabled`
* Navigation buttons are labeled "Go to previous month" / "Go to next month"
* Keyboard: Arrow keys move focus between days, Enter/Space selects, Page Up/Down navigates months

***

## Do's & Don'ts

<CardGroup cols={2}>
  <Card title="Do" icon="check" iconType="solid" color="#16A34A">
    * Use `initialFocus` when placing Calendar inside a Dialog or Popover
    * Use `numberOfMonths={2}` for range selection to show both start and end months
    * Use `disabled` prop to prevent selection of past dates, weekends, or holidays
    * Show a clear visual distinction between range start, range middle, and range end
  </Card>

  <Card title="Don't" icon="xmark" iconType="solid" color="#DC2626">
    * Don't use Calendar inline inside a form field — use `DatePicker` instead
    * Don't display more than 3 months side by side — it becomes too wide on mobile
    * Don't forget `initialFocus` in modal contexts — keyboard users will be stuck outside
    * Don't use `mode="multiple"` for date ranges — use `mode="range"` instead
  </Card>
</CardGroup>
