---
title: Calendar
description: "A date, time, or datetime selection component with a calendar popover and time spinner."
type: component
section: Components
order: 4
---

A date, time, or datetime selection component with a calendar popover and time spinner.

---

## Import

```tsx
import { Calendar } from "asheeui";
```

---

## Usage

```tsx
"use client";

import { Calendar } from "asheeui";
import { useState } from "react";

export default function Basic() {
  const [selected, setSelected] = useState<Date | null>(null);

  return (
    <div className="w-full max-w-md">
      <Calendar
        selected={selected}
        onChange={setSelected}
        label="Dropmenu Date"
      />
    </div>
  );
}
```

---

## Examples

### Date selection

<ComponentPreview path="calendar/date-selection" />

### Time selection

<ComponentPreview path="calendar/time-selection" />

### Datetime selection

<ComponentPreview path="calendar/datetime-selection" />

### Clearable

<ComponentPreview path="calendar/clearable" />

### Disable future dates

<ComponentPreview path="calendar/disable-future" />

### Custom picker styling

<ComponentPreview path="calendar/picker-styling" />

---

## Inheritance

Calendar extends the [`<Input />`](/docs/components/input) component and inherits **all** of its props and functionality. This means you can use any Input prop with Calendar, including:

- `size`, `radius`, `variant`, `color`
- `label`, `labelAlign`, `description`, `message`
- `status`, `required`, `isLoading`, `disabled`
- `className`, and all native input attributes

> **Reference**: For a complete list of inherited props with detailed descriptions, see the [Input documentation](/docs/components/input#props).

### What Calendar adds

Calendar extends Input with the following additional features:

| Feature | Description |
|---|---|
| **Calendar Popover** | A floating calendar for date selection |
| **Time Spinners** | Hour, minute, and second spinners for time selection |
| **Multiple Modes** | Support for date, time, and datetime selection modes |
| **Date Formatting** | Automatic formatting of dates for display |
| **Manual Input** | Type dates directly with smart parsing |
| **Clear Button** | Optional clear button to reset selection |
| **Future Date Restriction** | Option to disable future dates |

### What Calendar modifies

| Modification | Description |
|---|---|
| **`value`** | Replaced with `selected` which accepts a Date object |
| **`onChange`** | Receives a Date object or null instead of an event |
| **`endContent`** | Used internally for calendar/clock icon and clear button |
| **`placeholder`** | Auto-generated based on the selected mode |

### What Calendar does not inherit

The following Input props are **not available** on Calendar:

| Prop | Reason |
|---|---|
| `type` | Not applicable - Calendar uses a custom input |
| `value` | Replaced with `selected` |
| `defaultValue` | Not applicable - use `selected` with controlled state |
| `onChange` | Replaced with custom `onChange` that receives Date |

> **All other Input props** are fully supported. See the [Input documentation](/docs/components/input#props) for the complete list.

---

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `selected` | `Date \| null` | None | Currently selected date/time |
| `onChange` | `(date: Date \| null) => void` | None | Callback when date/time changes |
| `mode` | `"date" \| "time" \| "datetime"` | `"date"`* | Selection mode |
| `isClearable` | `boolean` | `false` | Shows clear button |
| `disableFuture` | `boolean` | `false` | Prevents future date selection |
| `placeholder` | `string` | Auto-generated | Custom placeholder text |
| `picker` | `PickerMenu` | None | Picker configuration overrides (see below) |

### Picker Configuration

The calendar popover appearance is controlled through the `picker` prop:

| Prop | Type | Default | Description |
|---|---|---|---|
| `picker.portal` | `boolean` | `true`* | Whether to render the popover in a portal |
| `picker.portalTarget` | `HTMLElement \| null` | `null`* | Custom portal target element |
| `picker.className` | `string` | None | Extra classes for the calendar popover |

---

## Global Configuration

Calendar reads defaults from four places, in this order of precedence:

1. **Instance prop**: set directly on `<Calendar />`
2. **Component config**: `components.datePicker` in your `ashee.config`
3. **Theme default**: `defaultVariant` / `defaultColor` / `defaultRadius` in your `ashee.config`
4. **Built-in fallback**: component's internal default values

### Component config

```ts
// ashee.config.ts
import type { ExternalConfig } from "asheeui";

export const config: ExternalConfig = {
  components: {
    datePicker: {
      size: "md",
      radius: "md",
      variant: "bordered",
      color: "primary",
      mode: "date",
      labelAlign: "left",
      picker: {
        portal: true,
      },
    },
  },
};
```

### Built-in fallbacks

```ts
{
  size: "md",
  radius: "md",
  variant: "bordered",
  color: "primary",
  status: "default",
  labelAlign: "left",
  mode: "date",
}
```

---

## Date Formatting

The Calendar automatically formats dates for display based on the selected mode:

| Mode | Format | Example |
|---|---|---|
| `date` | `DD/MM/YYYY` | `15/01/2024` |
| `time` | `HH:MM:SS` | `14:30:45` |
| `datetime` | `DD/MM/YYYY HH:MM:SS` | `15/01/2024 14:30:45` |

### Manual Input

Users can type dates directly into the input field. The component will parse the input intelligently:

- Typing `15012024` in date mode → `15/01/2024`
- Typing `1430` in time mode → `14:30:00`
- Typing `150120241430` in datetime mode → `15/01/2024 14:30:00`

The cursor position is preserved during formatting, making manual input feel natural and responsive.

---

## Portal Behavior

The Calendar calendar popover is rendered in a React portal by default. This means the popover is attached to `document.body` rather than staying in the component's DOM hierarchy.

### Why use a portal?

- **Escapes CSS containment**: The popover appears above other content even when inside containers with `overflow: hidden` or `contain: layout`
- **Avoids stacking context issues**: The popover maintains proper z-index regardless of parent stacking contexts
- **Works with any parent**: The popover functions correctly regardless of where the Calendar is placed in the component tree
- **Prevents clipping**: The popover is never clipped by parent containers

### When to disable the portal

You may want to disable the portal (by setting `picker.portal={false}`) when:
- You need the popover to stay within a specific container for testing purposes
- You are rendering inside a shadow DOM or iframe where `document.body` is not appropriate
- You have specific layout requirements that depend on the popover remaining in the DOM hierarchy

You can also provide a custom `picker.portalTarget` to render the popover into a specific container instead of `document.body`.

---

## Accessibility

- Renders a native combobox role with `aria-expanded` and `aria-haspopup="dialog"`
- Uses `aria-invalid` for error states
- Uses `aria-disabled` for disabled state
- Supports keyboard navigation with focus management
- Calendar navigation uses semantic button elements with proper ARIA labels
- Time spinners include increment/decrement buttons with `aria-label`
- Focus management via Floating UI with focus trapping
- Clear button includes `aria-label="Clear selection"`
- Month navigation buttons have `aria-label="Previous month"` and `aria-label="Next month"`
- Disabled dates are properly marked with `disabled` attribute

---

## Notes

- **Modes**: The component supports three modes - `date` (calendar only), `time` (time spinner only), and `datetime` (both calendar and time).
- **Status Colors**: When `status` is set to `error`, `success`, or `warning`, the input border automatically reflects the status color.
- **Clearable**: When `isClearable` is `true`, a clear button appears when a date is selected.
- **Disable Future**: When `disableFuture` is `true`, future dates are disabled in the calendar view.
- **Manual Input**: Users can type dates directly with smart parsing and cursor preservation.
- **Time Precision**: Time selection includes hours, minutes, and seconds.
- **Portal**: The calendar popover is portaled to `document.body` by default. This can be disabled via the `picker.portal` prop or component config.
- **Inheritance**: Calendar inherits all Input props except `value`, `defaultValue`, and `onChange`.