# 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'}
{'Last 7 days'} {'Last 14 days'} {'Last 30 days'} {'Last 90 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} } } }
} ``` ### 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() {
{ e.preventDefault(); }} > 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} } } }
} ``` ### 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