# Date Picker
URL: https://ark-ui.com/docs/components/date-picker
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/date-picker.mdx
A component that allows users to select a date from a calendar.
---
## Anatomy
```tsx
```
## Examples
**Example: basic**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component Basic() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Default Value
Use the `defaultValue` prop with `parseDate` to set the initial date value.
**Example: default-value**
```ripple
import { DatePicker, parseDate } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component DefaultValue() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Controlled
Use the `value` and `onValueChange` props to control the date picker's value programmatically.
**Example: controlled**
```ripple
import { DatePicker, parseDate } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import { track } from 'ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component Controlled() {
let value = track([parseDate('2022-01-01')]);
{
@value = e.value;
}}
>
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Root Provider
An alternative way to control the date picker is to use the `RootProvider` component and the `useDatePicker` hook. This
way you can access the state and methods from outside the component.
**Example: root-provider**
```ripple
import { DatePicker, useDatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component RootProvider() {
const datePicker = useDatePicker();
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid(
{ columns: 4 },
); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Default View
Use the `defaultView` prop to set which view (day, month, or year) the calendar opens to initially.
**Example: default-view**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component DefaultView() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Month and Year Select
Use `MonthSelect` and `YearSelect` components to create a header with dropdown selects for quick month/year navigation,
alongside the prev/next triggers.
**Example: month-year-select**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component MonthYearSelect() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
}
```
### Range
To create a date picker that allows a range selection, you need to:
- Set the `selectionMode` prop to `range`.
- Render multiple inputs with the `index` prop set to `0` and `1`.
**Example: range-selection**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component RangeSelection() {
{'Label'}{'Clear'}
{'Last 7 days'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Multiple
Use the `selectionMode="multiple"` prop to allow selecting multiple dates. This example also shows how to display
selected dates as removable tags.
**Example: multi-selection**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { type DateValue } from '@internationalized/date';
import { Calendar, ChevronLeft, ChevronRight, X } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
const formatWithDay = (date: DateValue) => new Intl.DateTimeFormat('en', {
dateStyle: 'medium',
}).format(date.toDate('UTC'));
export component MultiSelection() {
{'Label'}
component children({ context }) {
for (const date of @context.value; key date.toString()) {
{formatWithDay(date)}
}
}
{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Max Selected Dates
Use the `maxSelectedDates` prop with `selectionMode="multiple"` to limit the number of dates that can be selected. In
this example, users can select up to 3 dates.
**Example: max-selected-dates**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { ChevronLeft, ChevronRight } from 'lucide-ripple';
import styles from 'styles/date-picker.module.css';
export component MaxSelectedDates() {
{'Label'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
}
```
### Multiple Months
To create a date picker that displays multiple months side by side:
- Set the `numOfMonths` prop to the number of months you want to display.
- Use the `datePicker.getOffset({ months: 1 })` to get data for the next month.
**Example: multiple-months**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component MultipleMonths() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
const offset = @context.getOffset({ months: 1 });
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of offset.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
}
```
### Presets
Use the `DatePicker.PresetTrigger` component to add quick-select preset options like "Last 7 days" or "This month".
**Example: presets**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component Presets() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Min and Max
Use the `min` and `max` props with `parseDate` to restrict the selectable date range. Dates outside this range will be
disabled.
**Example: min-max**
```ripple
import { DatePicker, parseDate } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component MinMax() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Unavailable
Use the `isDateUnavailable` prop to mark specific dates as unavailable. This example disables weekends.
**Example: unavailable**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { isWeekend } from '@internationalized/date';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component Unavailable() {
isWeekend(date, locale)}
>
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Locale
Use the `locale` prop to set the language and formatting, and `startOfWeek` to set the first day of the week (0 =
Sunday, 1 = Monday, etc.).
**Example: locale**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component Locale() {
{'Beschriftung'}{'Löschen'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Month Picker
Create a month-only picker by setting `defaultView="month"` and `minView="month"`. Use custom `format` and `parse`
functions to handle month/year input format.
**Example: month-picker**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { CalendarDate, type DateValue } from '@internationalized/date';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
const format = (date: DateValue) => {
const month = String(date.month).padStart(2, '0');
const year = String(date.year);
return `${month}/${year}`;
};
const parse = (value: string) => {
const fullRegex = /^(\d{1,2})\/(\d{4})$/;
const fullMatch = value.match(fullRegex);
if (fullMatch) {
const [, month, year] = fullMatch.map(Number);
return new CalendarDate(year, month, 1);
}
return undefined;
};
export component MonthPicker() {
{'Label'}{'Clear'}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Year Picker
Create a year-only picker by setting `defaultView="year"` and `minView="year"`. Use custom `format` and `parse`
functions to handle year-only input format.
**Example: year-picker**
```ripple
import { DatePicker, parseDate } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { CalendarDate, type DateValue } from '@internationalized/date';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
const format = (date: DateValue) => String(date.year);
const parse = (value: string) => {
const fullRegex = /^(\d{4})$/;
const fullMatch = value.match(fullRegex);
if (fullMatch) {
const [, year] = fullMatch.map(Number);
return new CalendarDate(year, 1, 1);
}
return undefined;
};
export component YearPicker() {
{'Label'}{'Clear'}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Inline
Use the `inline` prop to display the date picker directly on the page, without a popup.
> When using the `inline` prop, omit the `Portal`, `Positioner`, and `Content` components to render the calendar inline
> within your layout.
**Example: inline**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { ChevronLeft, ChevronRight } from 'lucide-ripple';
import styles from 'styles/date-picker.module.css';
export component Inline() {
{'Label'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Custom Parsing
Use the `parse` prop to implement custom date parsing logic. This allows users to enter dates in flexible formats like
"25/12" or "25/12/24" which are automatically converted to valid dates.
**Example: format-parse**
```ripple
import { DatePicker, parseDate } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { type DateValue } from '@internationalized/date';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
const format = (date: DateValue) => {
const day = String(date.day).padStart(2, '0');
const month = String(date.month).padStart(2, '0');
const year = String(date.year);
return `${day}/${month}/${year}`;
};
const parse = (value: string) => {
const fullRegex = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/;
const fullMatch = value.match(fullRegex);
if (fullMatch) {
const [, day, month, year] = fullMatch.map(Number);
return parseDate(`${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`);
}
return undefined;
};
export component FormatParse() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Month Picker Range
Create a month range picker by combining `selectionMode="range"` with `defaultView="month"` and `minView="month"`. This
is useful for selecting billing periods or date ranges by month.
**Example: month-picker-range**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { CalendarDate, type DateValue } from '@internationalized/date';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
const format = (date: DateValue) => {
const month = String(date.month).padStart(2, '0');
const year = String(date.year);
return `${month}/${year}`;
};
const parse = (value: string) => {
const fullRegex = /^(\d{1,2})\/(\d{4})$/;
const fullMatch = value.match(fullRegex);
if (fullMatch) {
const [, month, year] = fullMatch.map(Number);
return new CalendarDate(year, month, 1);
}
return undefined;
};
export component MonthPickerRange() {
{'Label'}{'Clear'}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Year Range
Create a year range picker by combining `selectionMode="range"` with `defaultView="year"` and `minView="year"`. This is
useful for selecting multi-year periods.
**Example: year-picker-range**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { CalendarDate, type DateValue } from '@internationalized/date';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
const format = (date: DateValue) => String(date.year);
const parse = (value: string) => {
const fullRegex = /^(\d{4})$/;
const fullMatch = value.match(fullRegex);
if (fullMatch) {
const [, year] = fullMatch.map(Number);
return new CalendarDate(year, 1, 1);
}
return undefined;
};
export component YearPickerRange() {
{'Label'}{'Clear'}
component children({ context }) {
{@context.getDecade().start}
{' - '}
{@context.getDecade().end}
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Select Today
Use the `selectToday` method from the date picker context to add a "Today" button that quickly selects the current date.
**Example: select-today**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component SelectToday() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Fixed Weeks
Use the `fixedWeeks` prop to always display 6 weeks in the calendar, preventing layout shifts when navigating between
months.
**Example: fixed-weeks**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component FixedWeeks() {
{'Label'}{'Clear'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
}
component children({ context }) {
for (const months of @context.getMonthsGrid(
{ columns: 4, format: 'short' },
); key months[0].value) {
for (const month of months; key month.value) {
{month.label}
}
}
}
component children({ context }) {
for (const years of @context.getYearsGrid({ columns: 4 }); key years[0].value) {
for (const year of years; key year.value) {
{year.label}
}
}
}
}
```
### Form
Use the `name` prop to integrate the date picker with native HTML forms. The selected date value will be submitted as
form data. This example also uses `isDateUnavailable` to disable weekends.
**Example: form**
```ripple
import { DatePicker } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { isWeekend } from '@internationalized/date';
import { Calendar, ChevronLeft, ChevronRight } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component Form() {
}
```
### With Time
Integrate a time input with the date picker using `CalendarDateTime` from `@internationalized/date`. The time input
updates the hour and minute of the selected date value.
**Example: with-time**
```ripple
import { DatePicker, type CalendarDateTime } from 'ark-ripple/date-picker';
import { Portal } from 'ark-ripple/portal';
import { track } from 'ripple';
import { ChevronLeft, ChevronRight, Calendar } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/date-picker.module.css';
export component WithTime() {
let value = track([]);
{
@value = e.value as CalendarDateTime[];
}}
>
{'Label'}
component children({ context }) {
for (const weekDay of @context.weekDays; key weekDay.short) {
{weekDay.short}
}
for (const week of @context.weeks; key week[0].toString()) {
for (const day of week; key day.toString()) {
{day.day}
}
}
{
@value = [e.value as CalendarDateTime];
}}
/>
}
}
```
## API Reference
### Props
**Component API Reference**
**Root Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete.
This is ignored when the selection mode is `multiple`. |
| `createCalendar` | `(identifier: CalendarIdentifier) => Calendar` | No | A function that creates a Calendar object for a given calendar identifier.
Enables non-Gregorian calendar support (Persian, Buddhist, Islamic, etc.)
without bundling all calendars by default. |
| `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered.
Use when you don't need to control the focused date of the date picker. |
| `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered.
Use when you don't need to control the open state of the date picker. |
| `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered.
Use when you don't need to control the selected date(s) of the date picker. |
| `defaultView` | `DateView` | No | The default view of the calendar |
| `disabled` | `boolean` | No | Whether the calendar is disabled. |
| `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks.
This renders the calendar with 6 weeks instead of 5 or 6. |
| `focusedValue` | `DateValue` | No | The controlled focused date. |
| `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{ root: string; label: (index: number) => string; table: (id: string) => string; tableHeader: (id: string) => string; tableBody: (id: string) => string; tableRow: (id: string) => string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `inline` | `boolean` | No | Whether to render the date picker inline |
| `invalid` | `boolean` | No | Whether the date picker is invalid |
| `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. |
| `max` | `DateValue` | No | The maximum date that can be selected. |
| `maxSelectedDates` | `number` | No | The maximum number of dates that can be selected.
This is only applicable when `selectionMode` is `multiple`. |
| `maxView` | `DateView` | No | The maximum view of the calendar |
| `min` | `DateValue` | No | The minimum date that can be selected. |
| `minView` | `DateView` | No | The minimum view of the calendar |
| `name` | `string` | No | The `name` attribute of the input element. |
| `numOfMonths` | `number` | No | The number of months to display. |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `onFocusChange` | `(details: FocusChangeDetails) => void` | No | Function called when the focused date changes. |
| `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the calendar opens or closes. |
| `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when the value changes. |
| `onViewChange` | `(details: ViewChangeDetails) => void` | No | Function called when the view changes. |
| `onVisibleRangeChange` | `(details: VisibleRangeChangeDetails) => void` | No | Function called when the visible range changes. |
| `open` | `boolean` | No | The controlled open state of the date picker |
| `openOnClick` | `boolean` | No | Whether to open the calendar when the input is clicked. |
| `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. |
| `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. |
| `placeholder` | `string` | No | The placeholder text to display in the input. |
| `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `readOnly` | `boolean` | No | Whether the calendar is read-only. |
| `required` | `boolean` | No | Whether the date picker is required |
| `selectionMode` | `SelectionMode` | No | The selection mode of the calendar.
- `single` - only one date can be selected
- `multiple` - multiple dates can be selected
- `range` - a range of dates can be selected |
| `showWeekNumbers` | `boolean` | No | Whether to show the week number column in the day view. |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `startOfWeek` | `number` | No | The first day of the week.
`0` - Sunday
`1` - Monday
`2` - Tuesday
`3` - Wednesday
`4` - Thursday
`5` - Friday
`6` - Saturday |
| `timeZone` | `string` | No | The time zone to use |
| `translations` | `IntlTranslations` | No | The localized messages to use. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |
| `value` | `DateValue[]` | No | The controlled selected date(s). |
| `view` | `DateView` | No | The view of the calendar |
**Root Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | root |
| `[data-state]` | "open" | "closed" |
| `[data-disabled]` | Present when disabled |
| `[data-readonly]` | Present when read-only |
| `[data-empty]` | Present when the content is empty |
**ClearTrigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Content Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Content Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | content |
| `[data-state]` | "open" | "closed" |
| `[data-nested]` | popover |
| `[data-has-nested]` | popover |
| `[data-placement]` | The placement of the content |
| `[data-inline]` | Present when the content is inline |
**Content CSS Variables:**
| Variable | Description |
|----------|-------------|
| `--layer-index` | The index of the dismissable in the layer stack |
| `--nested-layer-count` | The number of nested date-pickers |
**Control Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Control Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | control |
| `[data-disabled]` | Present when disabled |
| `[data-placeholder-shown]` | Present when placeholder is shown |
**Input Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. |
| `index` | `number` | No | The index of the input to focus. |
**Input Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | input |
| `[data-index]` | The index of the item |
| `[data-state]` | "open" | "closed" |
| `[data-placeholder-shown]` | Present when placeholder is shown |
| `[data-invalid]` | Present when invalid |
**Label Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Label Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | label |
| `[data-state]` | "open" | "closed" |
| `[data-index]` | The index of the item |
| `[data-disabled]` | Present when disabled |
| `[data-readonly]` | Present when read-only |
**MonthSelect Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**NextTrigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**NextTrigger Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | next-trigger |
| `[data-disabled]` | Present when disabled |
**Positioner Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Positioner CSS Variables:**
| Variable | Description |
|----------|-------------|
| `--reference-width` | The width of the reference element |
| `--reference-height` | The height of the root |
| `--available-width` | The available width in viewport |
| `--available-height` | The available height in viewport |
| `--x` | The x position for transform |
| `--y` | The y position for transform |
| `--z-index` | The z-index value |
| `--transform-origin` | The transform origin for animations |
**PresetTrigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `PresetTriggerValue` | Yes | |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**PrevTrigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**PrevTrigger Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | prev-trigger |
| `[data-disabled]` | Present when disabled |
**RangeText Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**RootProvider Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseDatePickerReturn` | Yes | |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |
**TableBody Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**TableBody Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | table-body |
| `[data-view]` | The view of the tablebody |
| `[data-disabled]` | Present when disabled |
**TableCell Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `number | DateValue` | Yes | |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `columns` | `number` | No | |
| `disabled` | `boolean` | No | |
| `visibleRange` | `VisibleRange` | No | |
**TableCellTrigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**TableHead Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**TableHead Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | table-head |
| `[data-view]` | The view of the tablehead |
| `[data-disabled]` | Present when disabled |
**TableHeader Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**TableHeader Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | table-header |
| `[data-view]` | The view of the tableheader |
| `[data-disabled]` | Present when disabled |
**Table Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `columns` | `number` | No | |
**Table Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | table |
| `[data-columns]` | |
| `[data-view]` | The view of the table |
**TableRow Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**TableRow Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | table-row |
| `[data-disabled]` | Present when disabled |
| `[data-view]` | The view of the tablerow |
**Trigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Trigger Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | trigger |
| `[data-placement]` | The placement of the trigger |
| `[data-state]` | "open" | "closed" |
| `[data-placeholder-shown]` | Present when placeholder is shown |
**ValueText Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `placeholder` | `string` | No | Text to display when no date is selected. |
| `separator` | `string` | No | The separator to use between multiple date values when using default rendering. |
**ValueTextRender Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `number` | Yes | |
| `remove` | `() => void` | Yes | |
| `value` | `DateValue` | Yes | |
| `valueAsString` | `string` | Yes | |
**ViewControl Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**ViewControl Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | view-control |
| `[data-view]` | The view of the viewcontrol |
**View Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `view` | `DateView` | Yes | |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**View Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | view |
| `[data-view]` | The view of the view |
**ViewTrigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**ViewTrigger Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | view-trigger |
| `[data-view]` | The view of the viewtrigger |
**WeekNumberCell Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `week` | `DateValue[]` | Yes | |
| `weekIndex` | `number` | Yes | |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**WeekNumberCell Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | week-number-cell |
| `[data-view]` | The view of the weeknumbercell |
| `[data-week-index]` | |
| `[data-type]` | The type of the item |
| `[data-disabled]` | Present when disabled |
**WeekNumberHeaderCell Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**WeekNumberHeaderCell Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | date-picker |
| `[data-part]` | week-number-header-cell |
| `[data-view]` | The view of the weeknumberheadercell |
| `[data-type]` | The type of the item |
| `[data-disabled]` | Present when disabled |
**YearSelect Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
### Context
**API:**
| Property | Type | Description |
|----------|------|-------------|
| `focused` | `boolean` | Whether the input is focused |
| `open` | `boolean` | Whether the date picker is open |
| `disabled` | `boolean` | Whether the date picker is disabled |
| `invalid` | `boolean` | Whether the date picker is invalid |
| `readOnly` | `boolean` | Whether the date picker is read-only |
| `inline` | `boolean` | Whether the date picker is rendered inline |
| `numOfMonths` | `number` | The number of months to display |
| `showWeekNumbers` | `boolean` | Whether the week number column is shown in the day view |
| `selectionMode` | `SelectionMode` | The selection mode (single, multiple, or range) |
| `maxSelectedDates` | `number` | The maximum number of dates that can be selected (only for multiple selection mode). |
| `isMaxSelected` | `boolean` | Whether the maximum number of selected dates has been reached. |
| `view` | `DateView` | The current view of the date picker |
| `getWeekNumber` | `(week: DateValue[]) => number` | Returns the ISO 8601 week number (1-53) for the given week (array of dates). |
| `getDaysInWeek` | `(week: number, from?: DateValue) => DateValue[]` | Returns an array of days in the week index counted from the provided start date, or the first visible date if not given. |
| `getOffset` | `(duration: DateDuration) => DateValueOffset` | Returns the offset of the month based on the provided number of months. |
| `getRangePresetValue` | `(value: DateRangePreset) => DateValue[]` | Returns the range of dates based on the provided date range preset. |
| `getMonthWeeks` | `(from?: DateValue) => DateValue[][]` | Returns the weeks of the month from the provided date. Represented as an array of arrays of dates. |
| `isUnavailable` | `(date: DateValue) => boolean` | Returns whether the provided date is available (or can be selected) |
| `weeks` | `DateValue[][]` | The weeks of the month. Represented as an array of arrays of dates. |
| `weekDays` | `WeekDay[]` | The days of the week. Represented as an array of strings. |
| `visibleRange` | `VisibleRange` | The visible range of dates. |
| `visibleRangeText` | `VisibleRangeText` | The human readable text for the visible range of dates. |
| `value` | `DateValue[]` | The selected date. |
| `valueAsDate` | `Date[]` | The selected date as a Date object. |
| `valueAsString` | `string[]` | The selected date as a string. |
| `focusedValue` | `DateValue` | The focused date. |
| `focusedValueAsDate` | `Date` | The focused date as a Date object. |
| `focusedValueAsString` | `string` | The focused date as a string. |
| `selectToday` | `VoidFunction` | Sets the selected date to today. |
| `setValue` | `(values: DateValue[]) => void` | Sets the selected date to the given date. |
| `setTime` | `(time: Time, index?: number) => void` | Sets the time for a specific date value.
Converts CalendarDate to CalendarDateTime if needed. |
| `setFocusedValue` | `(value: DateValue) => void` | Sets the focused date to the given date. |
| `clearValue` | `(options?: { focus?: boolean; }) => void` | Clears the selected date(s). |
| `setOpen` | `(open: boolean) => void` | Function to open or close the calendar. |
| `focusMonth` | `(month: number) => void` | Function to set the selected month. |
| `focusYear` | `(year: number) => void` | Function to set the selected year. |
| `getYears` | `() => Cell[]` | Returns the months of the year |
| `getYearsGrid` | `(props?: YearGridProps) => YearGridValue` | Returns the years of the decade based on the columns.
Represented as an array of arrays of years. |
| `getDecade` | `() => Range` | Returns the start and end years of the decade. |
| `getMonths` | `(props?: MonthFormatOptions) => Cell[]` | Returns the months of the year |
| `getMonthsGrid` | `(props?: MonthGridProps) => MonthGridValue` | Returns the months of the year based on the columns.
Represented as an array of arrays of months. |
| `format` | `(value: DateValue, opts?: Intl.DateTimeFormatOptions) => string` | Formats the given date value based on the provided options. |
| `setView` | `(view: DateView) => void` | Sets the view of the date picker. |
| `goToNext` | `VoidFunction` | Goes to the next month/year/decade. |
| `goToPrev` | `VoidFunction` | Goes to the previous month/year/decade. |
| `getDayTableCellState` | `(props: DayTableCellProps) => DayTableCellState` | Returns the state details for a given cell. |
| `getMonthTableCellState` | `(props: TableCellProps) => TableCellState` | Returns the state details for a given month cell. |
| `getYearTableCellState` | `(props: TableCellProps) => TableCellState` | Returns the state details for a given year cell. |
## Accessibility
### Keyboard Support