---
title: DatePicker
description: >-
The DatePicker component renders a visual calendar that lets merchants select
a single date, multiple dates, or a date range. It supports disabling specific
dates, days of the week, or date ranges.
api_version: 2025-07
source_url:
html: >-
https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/datepicker
md: >-
https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/datepicker.md
api_name: admin-extensions
---
Migrate to Polaris
Version 2025-07 is the last API version to support React-based UI components. Later versions use [web components](https://shopify.dev/docs/api/admin-extensions/latest/web-components), native UI elements with built-in accessibility, better performance, and consistent styling with [Shopify's design system](https://shopify.dev/docs/apps/design). Check out the [migration guide](https://shopify.dev/docs/apps/build/admin/upgrading-to-2025-10) to upgrade your extension.
# DatePicker
The DatePicker component renders a visual calendar that lets merchants select a single date, multiple dates, or a date range. It supports disabling specific dates, days of the week, or date ranges.
For a compact form field with a calendar dropdown, use [DateField](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/datefield).
### Support Targets (46)
### Supported targets
* [admin.abandoned-checkout-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/abandoned-checkouts#abandoned-checkout-details-action-)
* [admin.abandoned-checkout-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/abandoned-checkouts#abandoned-checkout-details-block-)
* [admin.catalog-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/catalogs#catalog-details-action-)
* [admin.catalog-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/catalogs#catalog-details-block-)
* [admin.collection-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/collections#collection-details-action-target)
* [admin.collection-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/collections#collection-details-block-target)
* [admin.collection-index.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/collections#collection-index-targets)
* [admin.company-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/companies#company-details-action-)
* [admin.company-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/companies#company-details-block-)
* [admin.company-location-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/companies#company-location-details-block-)
* [admin.customer-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/customers#customer-details-action-)
* [admin.customer-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/customers#customer-details-block-)
* [admin.customer-index.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/customers#customer-index-targets)
* [admin.customer-index.selection-action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/customers#customer-index-selection-action-)
* [admin.customer-segment-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/customers#customer-segment-targets)
* [admin.discount-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/discounts#discount-details-action-)
* [admin.discount-details.function-settings.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/function-settings#discount-details-function-settings-)
* [admin.discount-index.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/discounts#discount-index-targets)
* [admin.draft-order-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/draft-orders#draft-order-details-action-)
* [admin.draft-order-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/draft-orders#draft-order-details-block-)
* [admin.draft-order-index.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/draft-orders#draft-order-index-targets)
* [admin.draft-order-index.selection-action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/draft-orders#draft-order-index-selection-action-)
* [admin.gift-card-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/gift-cards#gift-card-details-action-)
* [admin.gift-card-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/gift-cards#gift-card-details-block-)
* [admin.order-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/orders#order-details-action-)
* [admin.order-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/orders#order-details-block-)
* [admin.order-details.print-action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/orders#order-details-print-action-)
* [admin.order-fulfilled-card.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/orders#order-fulfilled-card-targets)
* [admin.order-index.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/orders#order-index-targets)
* [admin.order-index.selection-action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/orders#order-index-selection-action-)
* [admin.order-index.selection-print-action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/orders#order-index-selection-print-action-)
* [admin.product-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-details-action-)
* [admin.product-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-details-block-)
* [admin.product-details.configuration.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-details-configuration-)
* [admin.product-details.print-action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-details-print-action-)
* [admin.product-details.reorder.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-details-reorder-)
* [admin.product-index.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-index-targets)
* [admin.product-index.selection-action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-index-selection-action-)
* [admin.product-index.selection-print-action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-index-selection-print-action-)
* [admin.product-purchase-option.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/products#product-purchase-option-action-)
* [admin.product-variant-details.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/product-variants#product-variant-details-action-)
* [admin.product-variant-details.block.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/product-variants#product-variant-details-block-)
* [admin.product-variant-details.configuration.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/product-variants#product-variant-details-configuration-)
* [admin.product-variant-purchase-option.action.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/product-variants#product-variant-purchase-option-action-)
* [admin.settings.order-routing-rule.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/function-settings#order-routing-rule-function-settings-)
* [admin.settings.validation.render](https://shopify.dev/docs/api/admin-extensions/2025-07/targets/function-settings#validation-function-settings-)
#### Use cases
* **Visual date selection:** Provide calendar-based date selection with visual context.
* **Quick date navigation:** Enable fast navigation between months and years.
* **Date validation:** Enforce date constraints like minimum/maximum dates or disabled dates.
* **User-friendly input:** Offer intuitive date selection without requiring manual formatting.
***
## Properties
Props for the DatePicker component, a calendar-based date selection control. The generic parameter `T` determines the selection mode: pass a `DateString` for single-date, a `DateString[]` for multi-date, or a `Range` for range selection.
* **defaultYearMonth**
**{year: Year; month: Month} | YearMonthString**
The year and month to display when the calendar first renders. Use this for an uncontrolled calendar that manages its own navigation state. This prop is ignored when `yearMonth` is set (controlled mode).
Accepts either an object (`{ year, month }`) or a `YYYY-MM` string.
* **disabled**
**Disabled | Disabled\[] | boolean**
The dates that the user can't select.
* `DateString`: Disables a specific date, such as `'2024-12-25'`.
* `Range`: Disables a span of dates between `start` and `end`. Omit `start` or `end` for an open-ended range.
* `Day`: Disables every occurrence of a weekday, such as `'Sunday'`.
* `Disabled[]`: An array combining any of the above.
* `true`: Disables the entire date picker.
* **onChange**
**(selected: T) => void**
A callback that fires when the user selects or deselects a date. Receives the new selection value matching the shape of `selected` (a string, an array of strings, or a `Range` object). You must store this value in state and pass it back through the `selected` prop.
* **onYearMonthChange**
**(yearMonth: { year: number; month: number; }) => void**
A callback that fires when the user navigates to a different month or year (for example, by pressing the forward/back arrows). Receives an object with `year` and `month` properties. When using controlled navigation (`yearMonth` is set), you must update your state and pass the new value back through the `yearMonth` prop.
* **readOnly**
**boolean**
Whether the date picker is read-only. When `true`, the user can view the calendar and any selected dates, but can't change the selection.
* **selected**
**T**
The currently selected date or dates. Pass a date string for single-date selection, an array of date strings for multi-date selection, or a `Range` object for range selection. Update this value in your `onChange` handler to reflect the user's choice.
* **yearMonth**
**{year: Year; month: Month} | YearMonthString**
The year and month currently displayed in the calendar. Use this prop together with `onYearMonthChange` to control which month the user sees. When set, the calendar won't navigate on its own. You must update this value in response to `onYearMonthChange` to let the user browse months.
Accepts either an object (`{ year, month }`) or a `YYYY-MM` string.
### Year
A four-digit year number, for example \`2024\`.
```ts
number
```
### Month
A month number in the 1–12 range (1 = January, 12 = December).
```ts
number
```
### YearMonthString
A year-and-month string in simplified ISO 8601 format (\`YYYY-MM\`), for example \`'2024-12'\`.
```ts
string
```
### Disabled
A value that can be disabled in the date picker. Can be a specific \`DateString\`, a \`Range\` of dates, or a \`Day\` of the week.
```ts
DateString | Range | Day
```
### DateString
A date string in simplified ISO 8601 format (\`YYYY-MM-DD\`), for example \`'2024-12-25'\`.
```ts
string
```
### Range
A date range with optional start and end boundaries. Used for range selection in the date picker or for disabling a span of dates. Omitting \`start\` or \`end\` creates an open-ended range.
* end
The last day (inclusive) of the selected range.
```ts
DateString
```
* start
The first day (inclusive) of the selected range.
```ts
DateString
```
### Day
A day of the week. Used in \`disabled\` to disable every occurrence of a specific weekday (for example, \`'Sunday'\` disables all Sundays).
```ts
'Sunday' | 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday'
```
***
## Examples
### Schedule promotion start date
Schedule a promotion start date using an inline calendar. This example renders a `DatePicker` that captures the selected date, with a [Button](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/actions/button) that schedules the promotion.
## Schedule promotion start date
 that schedules the promotion.](https://shopify.dev/assets/assets/images/templated-apis-screenshots/admin-extensions/2025-07/datepicker-default-DaZaBe7f.png)
## Schedule promotion start date
##### React
```tsx
import {useState} from 'react';
import {reactExtension, useApi, DatePicker, Button, BlockStack, Text} from '@shopify/ui-extensions-react/admin';
function App() {
const {data, close} = useApi('admin.product-details.action.render');
const productId = data.selected[0]?.id;
const [date, setDate] = useState('');
return (
Schedule promotion start
);
}
export default reactExtension(
'admin.product-details.action.render',
() => ,
);
```
##### TS
```ts
import {extension, DatePicker, Button, BlockStack, Text} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.action.render',
(root, api) => {
const {data, close} = api;
const productId = data.selected[0]?.id;
let selectedDate = '';
const stack = root.createComponent(BlockStack);
const heading = root.createComponent(
Text,
{fontWeight: 'bold'},
'Schedule promotion start',
);
const picker = root.createComponent(DatePicker, {
selected: selectedDate,
onChange: (value) => {
selectedDate = value;
},
});
const saveButton = root.createComponent(
Button,
{
variant: 'primary',
onPress: async () => {
await fetch('/api/products/promotion', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId, startDate: selectedDate}),
});
close();
},
},
'Schedule promotion',
);
stack.appendChild(heading);
stack.appendChild(picker);
stack.appendChild(saveButton);
root.appendChild(stack);
},
);
```
### Select multiple blackout dates
Enable multi-date selection by passing an array to `selected` to let merchants pick multiple individual dates. This example collects shipping blackout dates (specific days when a product can't be shipped) and saves them as an array to your fulfillment backend.
## Select multiple blackout dates
##### React
```tsx
import {useState} from 'react';
import {reactExtension, useApi, DatePicker, Button, BlockStack, Text} from '@shopify/ui-extensions-react/admin';
function App() {
const {data, close} = useApi('admin.product-details.action.render');
const productId = data.selected[0]?.id;
const [dates, setDates] = useState([]);
return (
Select shipping blackout datesChoose dates when this product cannot be shipped.
);
}
export default reactExtension(
'admin.product-details.action.render',
() => ,
);
```
##### TS
```ts
import {extension, DatePicker, Button, BlockStack, Text} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.action.render',
(root, api) => {
const {data, close} = api;
const productId = data.selected[0]?.id;
let blackoutDates = [];
const stack = root.createComponent(BlockStack);
const heading = root.createComponent(
Text,
{fontWeight: 'bold'},
'Select shipping blackout dates',
);
const description = root.createComponent(
Text,
{},
'Choose dates when this product cannot be shipped.',
);
const picker = root.createComponent(DatePicker, {
selected: blackoutDates,
onChange: (value) => {
blackoutDates = value;
},
});
const saveButton = root.createComponent(
Button,
{
variant: 'primary',
onPress: async () => {
await fetch('/api/products/blackout-dates', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId, blackoutDates}),
});
close();
},
},
'Save blackout dates',
);
stack.appendChild(heading);
stack.appendChild(description);
stack.appendChild(picker);
stack.appendChild(saveButton);
root.appendChild(stack);
},
);
```
### Define a sale date range
Select a date range by passing an object with `start` and `end` properties to `selected`. This example lets merchants define a sale period by picking start and end dates on the calendar, then saves the range to configure time-limited pricing.
## Define a sale date range
##### React
```tsx
import {useState} from 'react';
import {reactExtension, useApi, DatePicker, Button, BlockStack, Text} from '@shopify/ui-extensions-react/admin';
function App() {
const {data, close} = useApi('admin.product-details.action.render');
const productId = data.selected[0]?.id;
const [range, setRange] = useState({start: '', end: ''});
return (
Set sale period
);
}
export default reactExtension(
'admin.product-details.action.render',
() => ,
);
```
##### TS
```ts
import {extension, DatePicker, Button, BlockStack, Text} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.action.render',
(root, api) => {
const {data, close} = api;
const productId = data.selected[0]?.id;
let dateRange = {start: '', end: ''};
const stack = root.createComponent(BlockStack);
const heading = root.createComponent(
Text,
{fontWeight: 'bold'},
'Set sale period',
);
const picker = root.createComponent(DatePicker, {
selected: dateRange,
onChange: (value) => {
dateRange = value;
},
});
const saveButton = root.createComponent(
Button,
{
variant: 'primary',
onPress: async () => {
await fetch('/api/products/sale-period', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId, ...dateRange}),
});
close();
},
},
'Save sale period',
);
stack.appendChild(heading);
stack.appendChild(picker);
stack.appendChild(saveButton);
root.appendChild(stack);
},
);
```
***
## Best practices
* **Use DateField in forms:** When the date picker is part of a form, use [DateField](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/forms/datefield) instead of a standalone DatePicker. DateField combines the calendar with a labeled text input.
***
## Limitations
* DatePicker doesn't support time selection. Dates are returned as strings in YYYY-MM-DD format without time information.
* The calendar displays one month at a time. There's no built-in way to show two months side-by-side for range selection.
* DatePicker doesn't include a built-in label or form field wrapper. When using it standalone, pair it with a [Heading](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/heading) or [Text](https://shopify.dev/docs/api/admin-extensions/2025-07/ui-components/typography-and-content/text) component to provide context.
***