{"slug":"date-picker","title":"Date Picker","description":"Using the date-picker machine in your project.","contentType":"component","framework":"react","content":"A date picker lets you enter a date through text input or pick one from a\ncalendar.\n\n> **Good to know**: The date picker is built on top of the\n> [`@internationalized/date`](https://react-spectrum.adobe.com/internationalized/date/CalendarDate.html)\n> library.\n\n## Resources\n\n\n[Latest version: v1.39.1](https://www.npmjs.com/package/@zag-js/date-picker)\n[Logic Visualizer](https://zag-visualizer.vercel.app/date-picker)\n[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/date-picker)\n\n\n\n**Features**\n\n- Displays a calendar view for date selection\n- Supports `single`, `multiple`, and `range` selection modes\n- Supports disabling specific dates\n- Supports date range presets\n- Supports week numbers\n- Supports custom format and parse logic\n- Works with localization, timezone, and custom calendar systems\n- Provides keyboard accessibility for navigating the calendar.\n\n## Installation\n\nInstall the date-picker package:\n\n```bash\nnpm install @zag-js/date-picker @zag-js/react\n# or\nyarn add @zag-js/date-picker @zag-js/react\n```\n\n## Anatomy\n\nCheck the date-picker anatomy and part names.\n\n> Each part includes a `data-part` attribute to help identify them in the DOM.\n\n\n\n## Usage\n\nImport the package:\n\n```tsx\nimport * as datepicker from \"@zag-js/date-picker\"\n```\n\nThese are the key exports:\n\n- `machine` - Behavior logic.\n- `connect` - Maps behavior to JSX props and event handlers.\n- `parse` - Parses an ISO 8601 date string.\n\n> You'll also need to provide a unique `id` to the `useMachine` hook. This is\n> used to ensure that every part has a unique identifier.\n\nThen use the framework integration helpers:\n\n```tsx\nimport * as datepicker from \"@zag-js/date-picker\"\nimport { useMachine, normalizeProps, Portal } from \"@zag-js/react\"\nimport { useId } from \"react\"\n\nfunction DatePicker() {\n  const service = useMachine(datepicker.machine, { id: useId() })\n\n  const api = datepicker.connect(service, normalizeProps)\n\n  return (\n    <>\n      <div {...api.getControlProps()}>\n        <input {...api.getInputProps()} />\n        <button {...api.getTriggerProps()}>🗓</button>\n      </div>\n\n      <Portal>\n        <div {...api.getPositionerProps()}>\n          <div {...api.getContentProps()}>\n            {/*  Day View  */}\n            <div hidden={api.view !== \"day\"}>\n              <div {...api.getViewControlProps({ view: \"year\" })}>\n                <button {...api.getPrevTriggerProps()}>Prev</button>\n                <button {...api.getViewTriggerProps()}>\n                  {api.visibleRangeText.start}\n                </button>\n                <button {...api.getNextTriggerProps()}>Next</button>\n              </div>\n\n              <table {...api.getTableProps({ view: \"day\" })}>\n                <thead {...api.getTableHeaderProps({ view: \"day\" })}>\n                  <tr {...api.getTableRowProps({ view: \"day\" })}>\n                    {api.weekDays.map((day, i) => (\n                      <th scope=\"col\" key={i} aria-label={day.long}>\n                        {day.narrow}\n                      </th>\n                    ))}\n                  </tr>\n                </thead>\n                <tbody {...api.getTableBodyProps({ view: \"day\" })}>\n                  {api.weeks.map((week, i) => (\n                    <tr key={i} {...api.getTableRowProps({ view: \"day\" })}>\n                      {week.map((value, i) => (\n                        <td key={i} {...api.getDayTableCellProps({ value })}>\n                          <div {...api.getDayTableCellTriggerProps({ value })}>\n                            {value.day}\n                          </div>\n                        </td>\n                      ))}\n                    </tr>\n                  ))}\n                </tbody>\n              </table>\n            </div>\n\n            {/*  Month View  */}\n            <div hidden={api.view !== \"month\"}>\n              <div {...api.getViewControlProps({ view: \"month\" })}>\n                <button {...api.getPrevTriggerProps({ view: \"month\" })}>\n                  Prev\n                </button>\n                <button {...api.getViewTriggerProps({ view: \"month\" })}>\n                  {api.visibleRange.start.year}\n                </button>\n                <button {...api.getNextTriggerProps({ view: \"month\" })}>\n                  Next\n                </button>\n              </div>\n\n              <table {...api.getTableProps({ view: \"month\", columns: 4 })}>\n                <tbody {...api.getTableBodyProps({ view: \"month\" })}>\n                  {api\n                    .getMonthsGrid({ columns: 4, format: \"short\" })\n                    .map((months, row) => (\n                      <tr key={row} {...api.getTableRowProps()}>\n                        {months.map((month, index) => (\n                          <td\n                            key={index}\n                            {...api.getMonthTableCellProps({\n                              ...month,\n                              columns: 4,\n                            })}\n                          >\n                            <div\n                              {...api.getMonthTableCellTriggerProps({\n                                ...month,\n                                columns: 4,\n                              })}\n                            >\n                              {month.label}\n                            </div>\n                          </td>\n                        ))}\n                      </tr>\n                    ))}\n                </tbody>\n              </table>\n            </div>\n\n            {/*  Year View  */}\n            <div hidden={api.view !== \"year\"}>\n              <div {...api.getViewControlProps({ view: \"year\" })}>\n                <button {...api.getPrevTriggerProps({ view: \"year\" })}>\n                  Prev\n                </button>\n                <span>\n                  {api.getDecade().start} - {api.getDecade().end}\n                </span>\n                <button {...api.getNextTriggerProps({ view: \"year\" })}>\n                  Next\n                </button>\n              </div>\n\n              <table {...api.getTableProps({ view: \"year\", columns: 4 })}>\n                <tbody {...api.getTableBodyProps()}>\n                  {api.getYearsGrid({ columns: 4 }).map((years, row) => (\n                    <tr key={row} {...api.getTableRowProps({ view: \"year\" })}>\n                      {years.map((year, index) => (\n                        <td\n                          key={index}\n                          {...api.getYearTableCellProps({\n                            ...year,\n                            columns: 4,\n                          })}\n                        >\n                          <div\n                            {...api.getYearTableCellTriggerProps({\n                              ...year,\n                              columns: 4,\n                            })}\n                          >\n                            {year.label}\n                          </div>\n                        </td>\n                      ))}\n                    </tr>\n                  ))}\n                </tbody>\n              </table>\n            </div>\n          </div>\n        </div>\n      </Portal>\n    </>\n  )\n}\n```\n\n### Setting the initial date\n\nTo set the initial value rendered by the date picker, set `defaultValue`.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  defaultValue: [datepicker.parse(\"2022-01-01\")],\n})\n```\n\n### Controlling the selected date\n\nUse the `value` and `onValueChange` properties to programmatically control the\nselected date.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  value: [datepicker.parse(\"2022-01-01\")],\n  onValueChange(details) {\n    // details => { value: DateValue[], valueAsString: string[], view: \"day\" | \"month\" | \"year\" }\n    console.log(\"selected date:\", details.valueAsString)\n  },\n})\n```\n\nYou can also set it with `api.setValue`.\n\n```tsx\nconst nextValue = datepicker.parse(\"2022-01-01\")\napi.setValue([nextValue])\n```\n\n### Controlling the open state\n\nUse `open` and `onOpenChange` to control the popup state.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  open: true,\n  onOpenChange(details) {\n    // details => { open: boolean, value: DateValue[] }\n    console.log(\"open state changed to:\", details.open)\n  },\n})\n```\n\nYou can also manage it with `api.setOpen`.\n\n```tsx\n// open the date picker\napi.setOpen(true)\n\n// close the date picker\napi.setOpen(false)\n```\n\n### Setting the min and max dates\n\nTo constrain the date range that can be selected by the user, set the `min` and\n`max` properties.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  min: datepicker.parse(\"2022-01-01\"),\n  max: datepicker.parse(\"2022-12-31\"),\n})\n```\n\nWhen min or max is reached, previous/next triggers are disabled.\n\n### Changing the start of the week\n\nSet `startOfWeek` from `0` to `6` (`0` is Sunday, `6` is Saturday).\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  startOfWeek: 1, // Monday\n})\n```\n\n### Disabling the date picker\n\nSet `disabled` to `true` to disable the picker.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  disabled: true,\n})\n```\n\n### Rendering month and year pickers\n\nRender month and year selects with `api.getMonthSelectProps` and\n`api.getYearSelectProps`.\n\n```tsx\n<div>\n  <select {...api.getMonthSelectProps()}>\n    {api.getMonths().map((month, i) => (\n      <option key={i} value={month.value}>\n        {month.label}\n      </option>\n    ))}\n  </select>\n\n  <select {...api.getYearSelectProps()}>\n    {getYearsRange({ from: 1_000, to: 4_000 }).map((year, i) => (\n      <option key={i} value={year}>\n        {year}\n      </option>\n    ))}\n  </select>\n</div>\n```\n\n### Marking unavailable dates\n\nSet `isDateUnavailable` and return `true` for blocked dates.\n\n```tsx\nimport { isWeekend } from \"@internationalized/date\"\n\nconst service = useMachine(datepicker.machine, {\n  isDateUnavailable: (date, locale) => {\n    // mark weekends as unavailable\n    return isWeekend(date, locale)\n  },\n})\n```\n\n### Setting the calendar starting view\n\nThe default view is `day`. Set `defaultView` to `day`, `month`, or `year` to\nchange it.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  defaultView: \"month\",\n})\n```\n\n### Setting the read-only mode\n\nSet `readOnly` to `true` to prevent value changes.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  readOnly: true,\n})\n```\n\n### Required and invalid state\n\nUse `required` and `invalid` for form validation and UI state.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  required: true,\n  invalid: false,\n})\n```\n\n### Setting the focused date\n\nBy default, focused date is the first selected date or today. Set\n`defaultFocusedValue` to override it.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  defaultFocusedValue: datepicker.parse(\"2022-01-01\"),\n})\n```\n\n### Rendering the calendar inline\n\nTo render the calendar inline, set `inline` to `true`.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  inline: true,\n})\n```\n\n### Usage within a form\n\nSet `name` to include the picker in form data.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  name: \"date\",\n})\n```\n\n### Rendering fixed number of weeks\n\nSet `fixedWeeks` to `true` to always render 6 weeks and avoid layout jumps\nbetween months.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  fixedWeeks: true,\n})\n```\n\n### Showing week numbers\n\nSet `showWeekNumbers` to `true` to enable a week-number column in day view.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  showWeekNumbers: true,\n})\n```\n\nThen render the week-number header and cells in your day table.\n\n```tsx\n<table {...api.getTableProps({ view: \"day\" })}>\n  <thead {...api.getTableHeaderProps({ view: \"day\" })}>\n    <tr {...api.getTableRowProps({ view: \"day\" })}>\n      {api.showWeekNumbers && (\n        <th {...api.getWeekNumberHeaderCellProps({ view: \"day\" })}>Wk</th>\n      )}\n      {api.weekDays.map((day, i) => (\n        <th scope=\"col\" key={i} aria-label={day.long}>\n          {day.narrow}\n        </th>\n      ))}\n    </tr>\n  </thead>\n  <tbody {...api.getTableBodyProps({ view: \"day\" })}>\n    {api.weeks.map((week, weekIndex) => (\n      <tr key={weekIndex} {...api.getTableRowProps({ view: \"day\" })}>\n        {api.showWeekNumbers && (\n          <td {...api.getWeekNumberCellProps({ weekIndex, week })}>\n            {api.getWeekNumber(week)}\n          </td>\n        )}\n        {week.map((value, i) => (\n          <td key={i} {...api.getDayTableCellProps({ value })}>\n            <div {...api.getDayTableCellTriggerProps({ value })}>\n              {value.day}\n            </div>\n          </td>\n        ))}\n      </tr>\n    ))}\n  </tbody>\n</table>\n```\n\n### Choosing a selection mode\n\nUse `selectionMode` to switch between `single`, `multiple`, and `range`.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  selectionMode: \"multiple\",\n})\n```\n\nIf you use `multiple`, you can cap selections with `maxSelectedDates`.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  selectionMode: \"multiple\",\n  maxSelectedDates: 3,\n})\n```\n\n### Using range presets\n\nIn range mode, `api.getPresetTriggerProps` accepts a preset key like\n`\"last7Days\"` or a custom `DateValue[]`.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  selectionMode: \"range\",\n})\n```\n\n```tsx\n<button {...api.getPresetTriggerProps({ value: \"last7Days\" })}>\n  Last 7 days\n</button>\n<button {...api.getPresetTriggerProps({ value: \"last30Days\" })}>\n  Last 30 days\n</button>\n```\n\n```tsx\n<button\n  {...api.getPresetTriggerProps({\n    value: [datepicker.parse(\"2024-01-01\"), datepicker.parse(\"2024-01-15\")],\n  })}\n>\n  First half of Jan\n</button>\n```\n\n### Customizing format and parse behavior\n\nUse `format` and `parse` to control how input text is displayed and parsed.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  format: (date, details) =>\n    date\n      .toDate(details.timeZone)\n      .toLocaleDateString(details.locale, { dateStyle: \"short\" }),\n  parse: (value) => datepicker.parse(value),\n})\n```\n\nYou can also build specialized pickers:\n\n- Month-year picker: use `minView: \"month\"` and `placeholder: \"mm/yyyy\"`\n- Year picker: use `minView: \"year\"`, `defaultView: \"year\"`, and\n  `placeholder: \"yyyy\"`\n\n```tsx\nimport { CalendarDate } from \"@internationalized/date\"\n\nconst service = useMachine(datepicker.machine, {\n  minView: \"month\",\n  view: \"month\",\n  placeholder: \"mm/yyyy\",\n  format: (date) => `${String(date.month).padStart(2, \"0\")}/${date.year}`,\n  parse: (value) => {\n    const match = value.match(/^(\\d{1,2})\\/(\\d{4})$/)\n    if (!match) return undefined\n    const [_, month, year] = match.map(Number)\n    return new CalendarDate(year, month, 1)\n  },\n})\n```\n\n```tsx\nimport { CalendarDate } from \"@internationalized/date\"\n\nconst service = useMachine(datepicker.machine, {\n  selectionMode: \"range\",\n  minView: \"year\",\n  defaultView: \"year\",\n  placeholder: \"yyyy\",\n  format: (date) => String(date.year),\n  parse: (value) => {\n    const match = value.match(/^(\\d{4})$/)\n    if (!match) return undefined\n    const [_, year] = match.map(Number)\n    return new CalendarDate(year, 1, 1)\n  },\n})\n```\n\n### Setting locale and timezone\n\nSet `locale` and `timeZone` to control date rendering.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  locale: \"en-GB\",\n  timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n})\n```\n\n### Using custom calendar systems\n\nPass a dedicated `createCalendar` function so you only ship the calendar your\nlocale needs.\n\n```tsx\nimport { PersianCalendar } from \"@internationalized/date\"\n\nfunction createPersianCalendar(identifier: string) {\n  if (identifier === \"persian\") return new PersianCalendar()\n  throw new Error(`Unsupported calendar: ${identifier}`)\n}\n\nconst service = useMachine(datepicker.machine, {\n  locale: \"fa-IR\",\n  createCalendar: createPersianCalendar,\n})\n```\n\n```tsx\nimport { BuddhistCalendar } from \"@internationalized/date\"\n\nfunction createBuddhistCalendar(identifier: string) {\n  if (identifier === \"buddhist\") return new BuddhistCalendar()\n  throw new Error(`Unsupported calendar: ${identifier}`)\n}\n\nconst service = useMachine(datepicker.machine, {\n  locale: \"th-TH\",\n  createCalendar: createBuddhistCalendar,\n})\n```\n\n### Restricting available views\n\nUse `minView` and `maxView` to limit view navigation.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  minView: \"month\",\n  maxView: \"year\",\n})\n```\n\n### Controlling open behavior\n\nBy default, the picker closes after selection and does not open on input click.\nYou can change both behaviors.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  openOnClick: true,\n  closeOnSelect: false,\n})\n```\n\nUse `defaultOpen` if you want the calendar to start open in uncontrolled mode.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  defaultOpen: true,\n})\n```\n\n### Allowing outside-day selection\n\nDays outside the visible month are disabled by default. Set\n`outsideDaySelectable` to `true` if you want them selectable.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  outsideDaySelectable: true,\n})\n```\n\n### Listening to date changes\n\nUse `onValueChange` to listen for date changes.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  onValueChange(details) {\n    // details => { value: DateValue[], valueAsString: string[], view: \"day\" | \"month\" | \"year\" }\n    console.log(\"selected date:\", details.valueAsString)\n  },\n})\n```\n\n### Listening to view changes\n\nUse `onViewChange` to listen for view changes.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  onViewChange(details) {\n    // details => { view: \"day\" | \"month\" | \"year\" }\n    console.log(\"view changed to:\", details.view)\n  },\n})\n```\n\n### Controlling the focused date\n\nUse `focusedValue` and `onFocusChange` to control keyboard focus in the\ncalendar.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  focusedValue: datepicker.parse(\"2022-01-01\"),\n  onFocusChange(details) {\n    console.log(\"focused date:\", details.focusedValue)\n  },\n})\n```\n\n### Listening to focus and visible range changes\n\nUse `onFocusChange` for focused-date changes and `onVisibleRangeChange` for\nvisible-range changes.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  onFocusChange(details) {\n    console.log(\"focused date:\", details.focusedValue)\n  },\n  onVisibleRangeChange(details) {\n    console.log(\"visible range:\", details.visibleRange)\n  },\n})\n```\n\n### Rendering multiple months\n\nTo display multiple months:\n\n- set the `numOfMonths` prop to the desired number of months\n- generate the weeks for the offset months using `api.getOffset({ months: 1 })`\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  // ...\n  numOfMonths: 2,\n})\n\nconst offset = api.getOffset({ months: 1 })\n```\n\nThen render the offset months.\n\n```tsx\n<tbody {...api.getTableBodyProps({ view: \"day\" })}>\n  {offset.weeks.map((week, i) => (\n    <tr key={i} {...api.getTableRowProps({ view: \"day\" })}>\n      {week.map((value, i) => (\n        <td\n          key={i}\n          {...api.getDayTableCellProps({\n            value,\n            visibleRange: offset.visibleRange,\n          })}\n        >\n          <div\n            {...api.getDayTableCellTriggerProps({\n              value,\n              visibleRange: offset.visibleRange,\n            })}\n          >\n            {value.day}\n          </div>\n        </td>\n      ))}\n    </tr>\n  ))}\n</tbody>\n```\n\n### Positioning\n\nUse `positioning` to customize popup placement.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  positioning: { placement: \"bottom-start\" },\n})\n```\n\n### Localization\n\nUse `translations` to customize accessibility labels and messages.\n\n```tsx\nconst service = useMachine(datepicker.machine, {\n  translations: {\n    clearTrigger: \"Clear date\",\n  },\n})\n```\n\n## Styling guide\n\nEach date-picker part includes a `data-part` attribute you can target in CSS.\n\n```css\n[data-scope=\"date-picker\"][data-part=\"root\"] {\n  /* styles for the root part */\n}\n\n[data-scope=\"date-picker\"][data-part=\"input\"] {\n  /* styles for the input part */\n}\n\n[data-scope=\"date-picker\"][data-part=\"trigger\"] {\n  /* styles for the trigger part */\n}\n\n[data-scope=\"date-picker\"][data-part=\"content\"] {\n  /* styles for the input part */\n}\n```\n\n### Open State\n\n```css\n[data-scope=\"date-picker\"][data-part=\"trigger\"] {\n  &[data-state=\"open\"] {\n    /* styles for the open state */\n  }\n\n  &[data-state=\"closed\"] {\n    /* styles for the closed state */\n  }\n}\n```\n\n### Cell States\n\n```css\n[data-scope=\"date-picker\"][data-part=\"table-cell-trigger\"] {\n  /* styles for the cell */\n\n  &[data-selected] {\n    /* styles for the selected date */\n  }\n\n  &[data-focus] {\n    /* styles for the focused date */\n  }\n\n  &[data-disabled] {\n    /* styles for the disabled date */\n  }\n\n  &[data-unavailable] {\n    /* styles for the unavailable date */\n  }\n\n  &[data-today] {\n    /* styles for the today date */\n  }\n\n  &[data-weekend] {\n    /* styles for the weekend date */\n  }\n}\n```\n\n### Range Selection States\n\nWhen using `selectionMode: \"range\"`, additional data attributes are available on\nday, month, and year table cell triggers for styling the selected and hovered\nranges.\n\n```css\n[data-scope=\"date-picker\"][data-part=\"table-cell-trigger\"] {\n  &[data-range-start] {\n    /* styles for the start of the selected range */\n  }\n\n  &[data-range-end] {\n    /* styles for the end of the selected range */\n  }\n\n  &[data-in-range] {\n    /* styles for dates within the selected range */\n  }\n\n  &[data-in-hover-range] {\n    /* styles for dates within the hovered range preview */\n  }\n\n  &[data-hover-range-start] {\n    /* styles for the start of the hovered range */\n  }\n\n  &[data-hover-range-end] {\n    /* styles for the end of the hovered range */\n  }\n}\n```\n\n## Methods and Properties\n\n### Machine Context\n\nThe date picker machine exposes the following context properties:\n\n**`locale`**\nType: `string`\nDescription: The locale (BCP 47 language tag) to use when formatting the date.\n\n**`createCalendar`**\nType: `(identifier: CalendarIdentifier) => Calendar`\nDescription: A function that creates a Calendar object for a given calendar identifier.\nEnables non-Gregorian calendar support (Persian, Buddhist, Islamic, etc.)\nwithout bundling all calendars by default.\n\n**`translations`**\nType: `IntlTranslations`\nDescription: The localized messages to use.\n\n**`ids`**\nType: `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; cellTrigger: (id: string) => string; prevTrigger: (view: DateView) => string; nextTrigger: (view: DateView) => string; viewTrigger: (view: DateView) => string; clearTrigger: string; control: string; input: (index: number) => string; trigger: string; monthSelect: string; yearSelect: string; positioner: string; }>`\nDescription: The ids of the elements in the date picker. Useful for composition.\n\n**`name`**\nType: `string`\nDescription: The `name` attribute of the input element.\n\n**`timeZone`**\nType: `string`\nDescription: The time zone to use\n\n**`disabled`**\nType: `boolean`\nDescription: Whether the calendar is disabled.\n\n**`readOnly`**\nType: `boolean`\nDescription: Whether the calendar is read-only.\n\n**`required`**\nType: `boolean`\nDescription: Whether the date picker is required\n\n**`invalid`**\nType: `boolean`\nDescription: Whether the date picker is invalid\n\n**`outsideDaySelectable`**\nType: `boolean`\nDescription: Whether day outside the visible range can be selected.\n\n**`min`**\nType: `DateValue`\nDescription: The minimum date that can be selected.\n\n**`max`**\nType: `DateValue`\nDescription: The maximum date that can be selected.\n\n**`closeOnSelect`**\nType: `boolean`\nDescription: Whether the calendar should close after the date selection is complete.\nThis is ignored when the selection mode is `multiple`.\n\n**`openOnClick`**\nType: `boolean`\nDescription: Whether to open the calendar when the input is clicked.\n\n**`value`**\nType: `DateValue[]`\nDescription: The controlled selected date(s).\n\n**`defaultValue`**\nType: `DateValue[]`\nDescription: The initial selected date(s) when rendered.\nUse when you don't need to control the selected date(s) of the date picker.\n\n**`focusedValue`**\nType: `DateValue`\nDescription: The controlled focused date.\n\n**`defaultFocusedValue`**\nType: `DateValue`\nDescription: The initial focused date when rendered.\nUse when you don't need to control the focused date of the date picker.\n\n**`numOfMonths`**\nType: `number`\nDescription: The number of months to display.\n\n**`startOfWeek`**\nType: `number`\nDescription: The first day of the week.\n `0` - Sunday\n `1` - Monday\n `2` - Tuesday\n `3` - Wednesday\n `4` - Thursday\n `5` - Friday\n `6` - Saturday\n\n**`fixedWeeks`**\nType: `boolean`\nDescription: Whether the calendar should have a fixed number of weeks.\nThis renders the calendar with 6 weeks instead of 5 or 6.\n\n**`showWeekNumbers`**\nType: `boolean`\nDescription: Whether to show the week number column in the day view.\n\n**`onValueChange`**\nType: `(details: ValueChangeDetails) => void`\nDescription: Function called when the value changes.\n\n**`onFocusChange`**\nType: `(details: FocusChangeDetails) => void`\nDescription: Function called when the focused date changes.\n\n**`onViewChange`**\nType: `(details: ViewChangeDetails) => void`\nDescription: Function called when the view changes.\n\n**`onVisibleRangeChange`**\nType: `(details: VisibleRangeChangeDetails) => void`\nDescription: Function called when the visible range changes.\n\n**`onOpenChange`**\nType: `(details: OpenChangeDetails) => void`\nDescription: Function called when the calendar opens or closes.\n\n**`isDateUnavailable`**\nType: `(date: DateValue, locale: string) => boolean`\nDescription: Returns whether a date of the calendar is available.\n\n**`selectionMode`**\nType: `SelectionMode`\nDescription: The selection mode of the calendar.\n- `single` - only one date can be selected\n- `multiple` - multiple dates can be selected\n- `range` - a range of dates can be selected\n\n**`maxSelectedDates`**\nType: `number`\nDescription: The maximum number of dates that can be selected.\nThis is only applicable when `selectionMode` is `multiple`.\n\n**`format`**\nType: `(date: LocaleDetails) => string`\nDescription: The format of the date to display in the input.\n\n**`parse`**\nType: `(value: string, details: LocaleDetails) => DateValue`\nDescription: Function to parse the date from the input back to a DateValue.\n\n**`placeholder`**\nType: `string`\nDescription: The placeholder text to display in the input.\n\n**`view`**\nType: `DateView`\nDescription: The view of the calendar\n\n**`defaultView`**\nType: `DateView`\nDescription: The default view of the calendar\n\n**`minView`**\nType: `DateView`\nDescription: The minimum view of the calendar\n\n**`maxView`**\nType: `DateView`\nDescription: The maximum view of the calendar\n\n**`positioning`**\nType: `PositioningOptions`\nDescription: The user provided options used to position the date picker content\n\n**`open`**\nType: `boolean`\nDescription: The controlled open state of the date picker\n\n**`defaultOpen`**\nType: `boolean`\nDescription: The initial open state of the date picker when rendered.\nUse when you don't need to control the open state of the date picker.\n\n**`inline`**\nType: `boolean`\nDescription: Whether to render the date picker inline\n\n**`dir`**\nType: `\"ltr\" | \"rtl\"`\nDescription: The document's text/writing direction.\n\n**`id`**\nType: `string`\nDescription: The unique identifier of the machine.\n\n**`getRootNode`**\nType: `() => ShadowRoot | Node | Document`\nDescription: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.\n\n### Machine API\n\nThe date picker `api` exposes the following methods:\n\n**`focused`**\nType: `boolean`\nDescription: Whether the input is focused\n\n**`open`**\nType: `boolean`\nDescription: Whether the date picker is open\n\n**`disabled`**\nType: `boolean`\nDescription: Whether the date picker is disabled\n\n**`invalid`**\nType: `boolean`\nDescription: Whether the date picker is invalid\n\n**`readOnly`**\nType: `boolean`\nDescription: Whether the date picker is read-only\n\n**`inline`**\nType: `boolean`\nDescription: Whether the date picker is rendered inline\n\n**`numOfMonths`**\nType: `number`\nDescription: The number of months to display\n\n**`showWeekNumbers`**\nType: `boolean`\nDescription: Whether the week number column is shown in the day view\n\n**`selectionMode`**\nType: `SelectionMode`\nDescription: The selection mode (single, multiple, or range)\n\n**`maxSelectedDates`**\nType: `number`\nDescription: The maximum number of dates that can be selected (only for multiple selection mode).\n\n**`isMaxSelected`**\nType: `boolean`\nDescription: Whether the maximum number of selected dates has been reached.\n\n**`view`**\nType: `DateView`\nDescription: The current view of the date picker\n\n**`getWeekNumber`**\nType: `(week: DateValue[]) => number`\nDescription: Returns the ISO 8601 week number (1-53) for the given week (array of dates).\n\n**`getDaysInWeek`**\nType: `(week: number, from?: DateValue) => DateValue[]`\nDescription: Returns an array of days in the week index counted from the provided start date, or the first visible date if not given.\n\n**`getOffset`**\nType: `(duration: DateDuration) => DateValueOffset`\nDescription: Returns the offset of the month based on the provided number of months.\n\n**`getRangePresetValue`**\nType: `(value: DateRangePreset) => DateValue[]`\nDescription: Returns the range of dates based on the provided date range preset.\n\n**`getMonthWeeks`**\nType: `(from?: DateValue) => DateValue[][]`\nDescription: Returns the weeks of the month from the provided date. Represented as an array of arrays of dates.\n\n**`isUnavailable`**\nType: `(date: DateValue) => boolean`\nDescription: Returns whether the provided date is available (or can be selected)\n\n**`weeks`**\nType: `DateValue[][]`\nDescription: The weeks of the month. Represented as an array of arrays of dates.\n\n**`weekDays`**\nType: `WeekDay[]`\nDescription: The days of the week. Represented as an array of strings.\n\n**`visibleRange`**\nType: `VisibleRange`\nDescription: The visible range of dates.\n\n**`visibleRangeText`**\nType: `VisibleRangeText`\nDescription: The human readable text for the visible range of dates.\n\n**`value`**\nType: `DateValue[]`\nDescription: The selected date.\n\n**`valueAsDate`**\nType: `Date[]`\nDescription: The selected date as a Date object.\n\n**`valueAsString`**\nType: `string[]`\nDescription: The selected date as a string.\n\n**`focusedValue`**\nType: `DateValue`\nDescription: The focused date.\n\n**`focusedValueAsDate`**\nType: `Date`\nDescription: The focused date as a Date object.\n\n**`focusedValueAsString`**\nType: `string`\nDescription: The focused date as a string.\n\n**`selectToday`**\nType: `VoidFunction`\nDescription: Sets the selected date to today.\n\n**`setValue`**\nType: `(values: DateValue[]) => void`\nDescription: Sets the selected date to the given date.\n\n**`setTime`**\nType: `(time: Time, index?: number) => void`\nDescription: Sets the time for a specific date value.\nConverts CalendarDate to CalendarDateTime if needed.\n\n**`setFocusedValue`**\nType: `(value: DateValue) => void`\nDescription: Sets the focused date to the given date.\n\n**`clearValue`**\nType: `(options?: { focus?: boolean; }) => void`\nDescription: Clears the selected date(s).\n\n**`setOpen`**\nType: `(open: boolean) => void`\nDescription: Function to open or close the calendar.\n\n**`focusMonth`**\nType: `(month: number) => void`\nDescription: Function to set the selected month.\n\n**`focusYear`**\nType: `(year: number) => void`\nDescription: Function to set the selected year.\n\n**`getYears`**\nType: `() => Cell[]`\nDescription: Returns the months of the year\n\n**`getYearsGrid`**\nType: `(props?: YearGridProps) => YearGridValue`\nDescription: Returns the years of the decade based on the columns.\nRepresented as an array of arrays of years.\n\n**`getDecade`**\nType: `() => Range<number>`\nDescription: Returns the start and end years of the decade.\n\n**`getMonths`**\nType: `(props?: MonthFormatOptions) => Cell[]`\nDescription: Returns the months of the year\n\n**`getMonthsGrid`**\nType: `(props?: MonthGridProps) => MonthGridValue`\nDescription: Returns the months of the year based on the columns.\nRepresented as an array of arrays of months.\n\n**`format`**\nType: `(value: DateValue, opts?: Intl.DateTimeFormatOptions) => string`\nDescription: Formats the given date value based on the provided options.\n\n**`setView`**\nType: `(view: DateView) => void`\nDescription: Sets the view of the date picker.\n\n**`goToNext`**\nType: `VoidFunction`\nDescription: Goes to the next month/year/decade.\n\n**`goToPrev`**\nType: `VoidFunction`\nDescription: Goes to the previous month/year/decade.\n\n**`getDayTableCellState`**\nType: `(props: DayTableCellProps) => DayTableCellState`\nDescription: Returns the state details for a given cell.\n\n**`getMonthTableCellState`**\nType: `(props: TableCellProps) => TableCellState`\nDescription: Returns the state details for a given month cell.\n\n**`getYearTableCellState`**\nType: `(props: TableCellProps) => TableCellState`\nDescription: Returns the state details for a given year cell.\n\n### Data Attributes\n\n**`Root`**\n\n**`data-scope`**: date-picker\n**`data-part`**: root\n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n**`data-readonly`**: Present when read-only\n**`data-empty`**: Present when the content is empty\n\n**`Label`**\n\n**`data-scope`**: date-picker\n**`data-part`**: label\n**`data-state`**: \"open\" | \"closed\"\n**`data-index`**: The index of the item\n**`data-disabled`**: Present when disabled\n**`data-readonly`**: Present when read-only\n\n**`Control`**\n\n**`data-scope`**: date-picker\n**`data-part`**: control\n**`data-disabled`**: Present when disabled\n**`data-placeholder-shown`**: Present when placeholder is shown\n\n**`Content`**\n\n**`data-scope`**: date-picker\n**`data-part`**: content\n**`data-state`**: \"open\" | \"closed\"\n**`data-nested`**: popover\n**`data-has-nested`**: popover\n**`data-placement`**: The placement of the content\n**`data-inline`**: Present when the content is inline\n\n**`Table`**\n\n**`data-scope`**: date-picker\n**`data-part`**: table\n**`data-columns`**: \n**`data-view`**: The view of the table\n\n**`TableHead`**\n\n**`data-scope`**: date-picker\n**`data-part`**: table-head\n**`data-view`**: The view of the tablehead\n**`data-disabled`**: Present when disabled\n\n**`TableHeader`**\n\n**`data-scope`**: date-picker\n**`data-part`**: table-header\n**`data-view`**: The view of the tableheader\n**`data-disabled`**: Present when disabled\n\n**`TableBody`**\n\n**`data-scope`**: date-picker\n**`data-part`**: table-body\n**`data-view`**: The view of the tablebody\n**`data-disabled`**: Present when disabled\n\n**`TableRow`**\n\n**`data-scope`**: date-picker\n**`data-part`**: table-row\n**`data-disabled`**: Present when disabled\n**`data-view`**: The view of the tablerow\n\n**`WeekNumberHeaderCell`**\n\n**`data-scope`**: date-picker\n**`data-part`**: week-number-header-cell\n**`data-view`**: The view of the weeknumberheadercell\n**`data-type`**: The type of the item\n**`data-disabled`**: Present when disabled\n\n**`WeekNumberCell`**\n\n**`data-scope`**: date-picker\n**`data-part`**: week-number-cell\n**`data-view`**: The view of the weeknumbercell\n**`data-week-index`**: \n**`data-type`**: The type of the item\n**`data-disabled`**: Present when disabled\n\n**`DayTableCell`**\n\n**`data-scope`**: date-picker\n**`data-part`**: day-table-cell\n**`data-value`**: The value of the item\n\n**`DayTableCellTrigger`**\n\n**`data-scope`**: date-picker\n**`data-part`**: day-table-cell-trigger\n**`data-disabled`**: Present when disabled\n**`data-selected`**: Present when selected\n**`data-value`**: The value of the item\n**`data-view`**: The view of the daytablecelltrigger\n**`data-today`**: Present when the date represents today\n**`data-focus`**: Present when focused\n**`data-unavailable`**: Present when the date is unavailable based on the min and max date\n**`data-range-start`**: Present when is the start of a range\n**`data-range-end`**: Present when is the end of a range\n**`data-in-range`**: Present when is within the range\n**`data-outside-range`**: Present when is outside the range\n**`data-weekend`**: Present when is a weekend day\n**`data-in-hover-range`**: Present when in hovered range\n**`data-hover-range-start`**: Present when is the start of the hovered range\n**`data-hover-range-end`**: Present when is the end of the hovered range\n\n**`MonthTableCell`**\n\n**`data-scope`**: date-picker\n**`data-part`**: month-table-cell\n**`data-selected`**: Present when selected\n**`data-value`**: The value of the item\n\n**`MonthTableCellTrigger`**\n\n**`data-scope`**: date-picker\n**`data-part`**: month-table-cell-trigger\n**`data-disabled`**: Present when disabled\n**`data-selected`**: Present when selected\n**`data-value`**: The value of the item\n**`data-view`**: The view of the monthtablecelltrigger\n**`data-focus`**: Present when focused\n**`data-outside-range`**: Present when is outside the range\n**`data-range-start`**: Present when is the start of a range\n**`data-range-end`**: Present when is the end of a range\n**`data-in-range`**: Present when is within the range\n**`data-in-hover-range`**: Present when in hovered range\n**`data-hover-range-start`**: Present when is the start of the hovered range\n**`data-hover-range-end`**: Present when is the end of the hovered range\n\n**`YearTableCell`**\n\n**`data-scope`**: date-picker\n**`data-part`**: year-table-cell\n**`data-selected`**: Present when selected\n**`data-value`**: The value of the item\n\n**`YearTableCellTrigger`**\n\n**`data-scope`**: date-picker\n**`data-part`**: year-table-cell-trigger\n**`data-disabled`**: Present when disabled\n**`data-selected`**: Present when selected\n**`data-value`**: The value of the item\n**`data-view`**: The view of the yeartablecelltrigger\n**`data-focus`**: Present when focused\n**`data-outside-range`**: Present when is outside the range\n**`data-range-start`**: Present when is the start of a range\n**`data-range-end`**: Present when is the end of a range\n**`data-in-range`**: Present when is within the range\n**`data-in-hover-range`**: Present when in hovered range\n**`data-hover-range-start`**: Present when is the start of the hovered range\n**`data-hover-range-end`**: Present when is the end of the hovered range\n\n**`NextTrigger`**\n\n**`data-scope`**: date-picker\n**`data-part`**: next-trigger\n**`data-disabled`**: Present when disabled\n\n**`PrevTrigger`**\n\n**`data-scope`**: date-picker\n**`data-part`**: prev-trigger\n**`data-disabled`**: Present when disabled\n\n**`Trigger`**\n\n**`data-scope`**: date-picker\n**`data-part`**: trigger\n**`data-placement`**: The placement of the trigger\n**`data-state`**: \"open\" | \"closed\"\n**`data-placeholder-shown`**: Present when placeholder is shown\n\n**`View`**\n\n**`data-scope`**: date-picker\n**`data-part`**: view\n**`data-view`**: The view of the view\n\n**`ViewTrigger`**\n\n**`data-scope`**: date-picker\n**`data-part`**: view-trigger\n**`data-view`**: The view of the viewtrigger\n\n**`ViewControl`**\n\n**`data-scope`**: date-picker\n**`data-part`**: view-control\n**`data-view`**: The view of the viewcontrol\n\n**`Input`**\n\n**`data-scope`**: date-picker\n**`data-part`**: input\n**`data-index`**: The index of the item\n**`data-state`**: \"open\" | \"closed\"\n**`data-placeholder-shown`**: Present when placeholder is shown\n**`data-invalid`**: Present when invalid\n\n### CSS Variables\n\n<CssVarTable name=\"date-picker\" />","package":"@zag-js/date-picker","editUrl":"https://github.com/chakra-ui/zag/edit/main/website/data/components/date-picker.mdx"}