Skip to main content
Migrate to Polaris

Version 2025-07 is the last API version to support React-based UI components. Later versions use web components, native UI elements with built-in accessibility, better performance, and consistent styling with Shopify's design system. Check out the migration guide 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.

Support
Targets (46)

Supported targets


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.

Anchor to defaultYearMonth
defaultYearMonth
{year: ; month: } |

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.

Anchor to 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.
Anchor to onChange
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.

Anchor to onYearMonthChange
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.

Anchor to readOnly
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.

Anchor to selected
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.

Anchor to yearMonth
yearMonth
{year: ; month: } |

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.


Anchor to Schedule promotion start dateSchedule 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 that schedules the promotion.

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](/docs/api/admin-extensions/2025-07/ui-components/actions/button) that schedules the promotion.

Schedule promotion start date

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 (
<BlockStack>
<Text fontWeight="bold">Schedule promotion start</Text>
<DatePicker selected={date} onChange={setDate} />
<Button
variant="primary"
onPress={async () => {
await fetch('/api/products/promotion', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId, startDate: date}),
});
close();
}}
>
Schedule promotion
</Button>
</BlockStack>
);
}

export default reactExtension(
'admin.product-details.action.render',
() => <App />,
);
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);
},
);

Anchor to Select multiple blackout datesSelect 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

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 (
<BlockStack>
<Text fontWeight="bold">Select shipping blackout dates</Text>
<Text>Choose dates when this product cannot be shipped.</Text>
<DatePicker selected={dates} onChange={setDates} />
<Button
variant="primary"
onPress={async () => {
await fetch('/api/products/blackout-dates', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId, blackoutDates: dates}),
});
close();
}}
>
Save blackout dates
</Button>
</BlockStack>
);
}

export default reactExtension(
'admin.product-details.action.render',
() => <App />,
);
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);
},
);

Anchor to Define a sale date rangeDefine 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

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 (
<BlockStack>
<Text fontWeight="bold">Set sale period</Text>
<DatePicker selected={range} onChange={setRange} />
<Button
variant="primary"
onPress={async () => {
await fetch('/api/products/sale-period', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId, ...range}),
});
close();
}}
>
Save sale period
</Button>
</BlockStack>
);
}

export default reactExtension(
'admin.product-details.action.render',
() => <App />,
);
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);
},
);

  • Use DateField in forms: When the date picker is part of a form, use DateField instead of a standalone DatePicker. DateField combines the calendar with a labeled text input.

  • 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 or Text component to provide context.

Was this page helpful?