> ## 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.

# Date Picker

> A calendar-based input for selecting a single date or a date range — supports locale formatting, min/max constraints, and controlled state.

## Overview

<div style={{padding:"28px 24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",gap:"24px",flexWrap:"wrap",alignItems:"flex-start"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"4px"}}>
    <label style={{fontSize:"12px",fontWeight:500,color:"#344054",fontFamily:"Inter,sans-serif"}}>Start date</label>

    <div style={{display:"flex",alignItems:"center",gap:"8px",border:"1px solid #D0D5DD",borderRadius:"8px",padding:"9px 12px",background:"#fff",width:"200px",cursor:"pointer"}}>
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
        <rect x="3" y="4" width="18" height="18" rx="2" />

        <line x1="16" y1="2" x2="16" y2="6" />

        <line x1="8" y1="2" x2="8" y2="6" />

        <line x1="3" y1="10" x2="21" y2="10" />
      </svg>

      <span style={{fontSize:"14px",color:"#667085",fontFamily:"Inter,sans-serif"}}>Pick a date</span>
    </div>

    <div style={{marginTop:"4px",background:"#fff",border:"1px solid #E5E7EB",borderRadius:"10px",boxShadow:"0 4px 16px rgba(0,0,0,0.08)",padding:"16px",width:"260px"}}>
      <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 6px"}}>‹</button>
        <span style={{fontSize:"14px",fontWeight:600,color:"#101828",fontFamily:"Inter,sans-serif"}}>April 2026</span>
        <button style={{border:"none",background:"none",cursor:"pointer",color:"#71717A",fontSize:"16px",padding:"2px 6px"}}>›</button>
      </div>

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

        {["","","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",fontFamily:"Inter,sans-serif",padding:"5px 0",borderRadius:"6px",cursor:d?"pointer":"default",background:d==="1"?"#0479CE":"transparent",color:d==="1"?"#fff":d?"#344054":"transparent",fontWeight:d==="1"?600:400}}>{d}</div>
                      ))}
      </div>
    </div>
  </div>
</div>

**Date Picker** combines an input trigger with a calendar popover. It supports single date selection, date range selection, locale formatting, and min/max date constraints.

<Note>
  For date range selection, use `DateRangePicker`. Both components share the same API shape — `DateRangePicker` accepts `{ from: Date; to?: Date }` for its `value` prop.
</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 { DatePicker, DateRangePicker } from "@araf-ds/core"

export default function Example() {
  return (
    <DatePicker
      label="Start date"
      placeholder="Pick a date"
    />
  )
}
```

***

## Variants

### Single Date (Default)

The default trigger opens a calendar popover for single date selection.

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"4px",maxWidth:"220px"}}>
    <label style={{fontSize:"12px",fontWeight:500,color:"#344054",fontFamily:"Inter,sans-serif"}}>Start date</label>

    <div style={{display:"flex",alignItems:"center",gap:"8px",border:"1px solid #D0D5DD",borderRadius:"8px",padding:"9px 12px",background:"#fff",cursor:"pointer"}}>
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
        <rect x="3" y="4" width="18" height="18" rx="2" />

        <line x1="16" y1="2" x2="16" y2="6" />

        <line x1="8" y1="2" x2="8" y2="6" />

        <line x1="3" y1="10" x2="21" y2="10" />
      </svg>

      <span style={{fontSize:"14px",color:"#667085",fontFamily:"Inter,sans-serif"}}>Pick a date</span>
    </div>
  </div>
</div>

```tsx theme={null}
<DatePicker label="Start date" placeholder="Select start date" />
```

### With Selected Value

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"4px",maxWidth:"220px"}}>
    <label style={{fontSize:"12px",fontWeight:500,color:"#344054",fontFamily:"Inter,sans-serif"}}>Date of birth</label>

    <div style={{display:"flex",alignItems:"center",gap:"8px",border:"1px solid #0479CE",borderRadius:"8px",padding:"9px 12px",background:"#fff",cursor:"pointer",boxShadow:"0 0 0 4px #CDE4F5"}}>
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#0479CE" strokeWidth="2">
        <rect x="3" y="4" width="18" height="18" rx="2" />

        <line x1="16" y1="2" x2="16" y2="6" />

        <line x1="8" y1="2" x2="8" y2="6" />

        <line x1="3" y1="10" x2="21" y2="10" />
      </svg>

      <span style={{fontSize:"14px",color:"#101828",fontFamily:"Inter,sans-serif"}}>April 1, 2026</span>
    </div>
  </div>
</div>

```tsx theme={null}
<DatePicker
  label="Date of birth"
  value={date}
  onValueChange={setDate}
  maxDate={new Date()}
/>
```

### Date Range Picker

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"4px",maxWidth:"280px"}}>
    <label style={{fontSize:"12px",fontWeight:500,color:"#344054",fontFamily:"Inter,sans-serif"}}>Booking period</label>

    <div style={{display:"flex",alignItems:"center",gap:"8px",border:"1px solid #D0D5DD",borderRadius:"8px",padding:"9px 12px",background:"#fff",cursor:"pointer"}}>
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#667085" strokeWidth="2">
        <rect x="3" y="4" width="18" height="18" rx="2" />

        <line x1="16" y1="2" x2="16" y2="6" />

        <line x1="8" y1="2" x2="8" y2="6" />

        <line x1="3" y1="10" x2="21" y2="10" />
      </svg>

      <span style={{fontSize:"14px",color:"#667085",fontFamily:"Inter,sans-serif"}}>Apr 1, 2026 – Apr 15, 2026</span>
    </div>
  </div>
</div>

```tsx theme={null}
<DateRangePicker
  label="Booking period"
  placeholder="Select date range"
/>
```

### Error State

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"4px",maxWidth:"220px"}}>
    <label style={{fontSize:"12px",fontWeight:500,color:"#344054",fontFamily:"Inter,sans-serif"}}>Expiry date</label>

    <div style={{display:"flex",alignItems:"center",gap:"8px",border:"1px solid #DC2626",borderRadius:"8px",padding:"9px 12px",background:"#fff",cursor:"pointer",boxShadow:"0 0 0 4px #FEE2E2"}}>
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#DC2626" strokeWidth="2">
        <rect x="3" y="4" width="18" height="18" rx="2" />

        <line x1="16" y1="2" x2="16" y2="6" />

        <line x1="8" y1="2" x2="8" y2="6" />

        <line x1="3" y1="10" x2="21" y2="10" />
      </svg>

      <span style={{fontSize:"14px",color:"#667085",fontFamily:"Inter,sans-serif"}}>Pick a date</span>
    </div>

    <span style={{fontSize:"12px",color:"#DC2626",fontFamily:"Inter,sans-serif"}}>Please select a valid date</span>
  </div>
</div>

```tsx theme={null}
<DatePicker
  label="Expiry date"
  state="error"
  helperText="Please select a valid date"
/>
```

### Disabled

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"4px",maxWidth:"220px"}}>
    <label style={{fontSize:"12px",fontWeight:500,color:"#D0D5DD",fontFamily:"Inter,sans-serif"}}>Delivery date</label>

    <div style={{display:"flex",alignItems:"center",gap:"8px",border:"1px solid #E5E7EB",borderRadius:"8px",padding:"9px 12px",background:"#F9FAFB",cursor:"not-allowed",opacity:0.6}}>
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#9CA3AF" strokeWidth="2">
        <rect x="3" y="4" width="18" height="18" rx="2" />

        <line x1="16" y1="2" x2="16" y2="6" />

        <line x1="8" y1="2" x2="8" y2="6" />

        <line x1="3" y1="10" x2="21" y2="10" />
      </svg>

      <span style={{fontSize:"14px",color:"#9CA3AF",fontFamily:"Inter,sans-serif"}}>Pick a date</span>
    </div>
  </div>
</div>

```tsx theme={null}
<DatePicker label="Delivery date" disabled />
```

***

## API Reference

### DatePicker

<ParamField path="value" type="Date | undefined">
  Controlled selected date.
</ParamField>

<ParamField path="onValueChange" type="(date: Date | undefined) => void">
  Callback fired when the selected date changes.
</ParamField>

<ParamField path="defaultValue" type="Date">
  Uncontrolled default selected date.
</ParamField>

<ParamField path="label" type="string">
  Label displayed above the trigger input.
</ParamField>

<ParamField path="placeholder" type="string" default="Pick a date">
  Trigger placeholder text shown when no date is selected.
</ParamField>

<ParamField path="format" type="string" default="PPP">
  Date format string (date-fns format). E.g. `"dd/MM/yyyy"`, `"MMM d, yyyy"`.
</ParamField>

<ParamField path="minDate" type="Date">
  Earliest selectable date. Dates before this are disabled in the calendar.
</ParamField>

<ParamField path="maxDate" type="Date">
  Latest selectable date. Dates after this are disabled in the calendar.
</ParamField>

<ParamField path="disabled" type="boolean" default="false">
  Disables the picker entirely — trigger cannot be opened.
</ParamField>

<ParamField path="helperText" type="string">
  Helper or error message displayed below the trigger.
</ParamField>

<ParamField path="state" type="string" default="default">
  Validation state. Values: `default` · `error`
</ParamField>

<ParamField path="className" type="string">
  Additional Tailwind classes for the trigger container.
</ParamField>

### DateRangePicker

Same props as `DatePicker`, except:

<ParamField path="value" type="{ from: Date; to?: Date } | undefined">
  Controlled selected date range.
</ParamField>

<ParamField path="onValueChange" type="(range: { from: Date; to?: Date } | undefined) => void">
  Callback fired when the selected range changes.
</ParamField>

***

## Accessibility

* The trigger renders as a `<button>` with `aria-haspopup="dialog"` and `aria-expanded`
* The calendar popover uses `role="dialog"` with `aria-modal="true"`
* Individual day cells use `role="gridcell"` with `aria-selected` and `aria-disabled`
* Keyboard navigation: Arrow keys move focus between days, Enter/Space selects, Escape closes the popover
* The calendar `<table>` has `role="grid"` with column headers labeled by weekday abbreviation

***

## Do's & Don'ts

<CardGroup cols={2}>
  <Card title="Do" icon="check" iconType="solid" color="#16A34A">
    * Use `minDate` and `maxDate` to constrain valid selections
    * Show the selected date in a human-readable format (`"April 1, 2026"`, not `"2026-04-01"`)
    * Provide a `helperText` with error state to explain what went wrong
    * Use `DateRangePicker` for date range inputs — never two separate DatePickers
  </Card>

  <Card title="Don't" icon="xmark" iconType="solid" color="#DC2626">
    * Don't use DatePicker for time-only selection — use a time input
    * Don't disable today's date unless there's a valid business reason
    * Don't rely solely on the calendar for date entry — allow manual text input where possible
    * Don't use DatePicker inline in dense form rows — it opens a popover that needs space
  </Card>
</CardGroup>
