Skip to content

Import#

import { DatePicker } from '@dnb/eufemia'

Description#

The DatePicker component should be used whenever the user is to enter a single date or a date range/period with a start and end date.

When to use DatePicker vs Eufemia Forms#

Classic form components like this one are presentational controls. They handle the styling, sizing, icons, and basic events, while you manage their value, validation, and error handling yourself.

For most data input and forms situations, use Eufemia Forms fields instead. They build on these same components, but add data handling, validation, and error messages through the surrounding Form.Handler. Browse the field components to find the one that matches your data.

Reach for a classic component when you need it standalone outside of a form context, or when you handle the value and validation yourself.

The Eufemia Forms equivalent of DatePicker is Field.Date.

Dates from adjacent months#

By default, DatePicker shows dates from the previous and next month to provide context around month boundaries. Set hideAdjacentMonthDates when the extra dates could cause confusion or when a simpler calendar would reduce cognitive load. The grid cells remain in place, so the calendar layout does not change.

Relevant links#

Date Object#

The DatePicker operates with a default JavaScript Date instance as well as a string (ISO 8601) like date="2019-05-05" (yyyy-MM-dd).

Handling time zones#

The DatePicker component has no built-in time zone support because it only deals with dates (not time).

Ensure you do not create Date objects with time information (new Date()), as that will introduce time zone issues.

If you need to use a Date object but want the same date everywhere, regardless of runtime timezone, you have to normalize it first.

Use an ISO string with an explicit offset:

const isoDate = '2025-01-01T00:00:00Z'

Or use UTC constructors:

const utcDate = new Date(Date.UTC(2025, 0, 1))

Manipulate the days in the calendar view#

The callback event onDaysRender gives you the possibility to manipulate the "day" object before it gets rendered. This callback will be called many times, both on the first render and on every user interaction, like hover and selection. This means you have to ensure a performant date calculation.

Please use date-fns to make the calculations.

ddmmåååå

<DatePicker
  onDaysRender={(days, calendarNumber = 0) => {
    return days.map((dayObject) => {
      if (isWeekend(dayObject.date)) {
        dayObject.isInactive = true
        dayObject.className = 'dnb-date-picker__day--weekend' // custom css
      }

      return dayObject
    })
  }}
/>

The dayObject object contains:

[
{
date: Date,// Vanilla JavaScript Date object
className: // define your custom css classes
isInactive: boolean,// shows it as disabled only
isDisabled: boolean,// shows it as disabled and with a strikethrough
isPreview: boolean,// date is between startDate (exclusive) and hoverDate (inclusive)
isSelectable: boolean,// if not disabled – handles z-index
isStartDate: boolean,// date selected is start date
isEndDate: boolean,// date selected is end date
isToday: boolean,
isWithinSelection: boolean,// date is between selection range
isNextMonth: boolean,// date belongs to the next month
isLastMonth: boolean,// date belongs to the previous month
},
...
]

Highlighting "today"#

By default, the DatePicker highlights the "today" date based on the user's local time zone.

If you need to treat another time zone as "today", mutate the dayObject.isToday flag inside the onDaysRender callback. The example below demonstrates how to compare every day against getOsloDate() and keep the highlight in sync with Oslo time.

ddmmåååå

const osloDate = getOsloDate()
render(
  <DatePicker
    onDaysRender={(days) => {
      return days.map((dayObject) => {
        dayObject.isToday = isSameDay(dayObject.date, osloDate)
        return dayObject
      })
    }}
  />
)

Here is how to import the required helper:

import { isSameDay } from 'date-fns'
import { DatePicker } from '@dnb/eufemia'
import { getOsloDate } from '@dnb/eufemia/components/date-format/DateFormatUtils'

Min & Max date#

The minDate and maxDate props restrict which dates can be selected in the calendar view. Dates outside the given range will be disabled, both for single dates and ranges. However, the user can still type a date outside these limits directly in the input field — minDate and maxDate do not validate typed input.

If minDate or maxDate is given, the return object also contains information about whether the date is within the given limits:

{
isValidStartDate: boolean,
isValidEndDate: boolean,
...
}

Validation for minDate, maxDate, and invalid dates#

If you need validation of typed input against minDate and maxDate, use Field.Date instead. It has built-in validation for minDate, maxDate, and invalid dates, and will show the user an error message when the entered date is outside the allowed range.

Automatically changing the user input leads to worse UX and confusion, as the user might not understand why the date changed. It's best practice to tell the user what is wrong and let them correct it.

Validation during input changes#

In order to validate dates during typing, you can make use of isValid or isValidStartDate and isValidEndDate. Because the user can change a date in the input field, and the onType event will then return a falsy isValid.

Additional event return object properties:

{
isValid: boolean, /* Available if `range` is `false` */
isValidStartDate: boolean, /* Available if `range` is `true` */
isValidEndDate: boolean, /* Available if `range` is `true` */
}

Root Element (React Portal)#

The DatePicker component uses PortalRoot internally to render its calendar. See the PortalRoot documentation for information on how to control where the portal content appears in the DOM, and for the BrowserTranslate helper when browser translation tools such as Google Translate should not modify content rendered through PortalRoot.

Related components#

DatePicker is part of the Input category. Other components for similar needs:

  • Autocomplete — to help people find and choose from matching suggestions as they type.
  • Checkbox — when people can turn one or more options on or off.
  • Dropdown — when people need to choose one option from a list.
  • Filter — to help people narrow down a list or data set.
  • FormLabel — to name an input, control, or form-related field.
  • Input — when people need to enter a short line of text.

See all in Input

Demos#

English (US) is not included in Eufemia by default. You can include it like:

import enUS from '@dnb/eufemia/shared/locales/en-US'
<EufemiaProvider locale={enUS} ...>
App
</EufemiaProvider>

Range DatePicker#

DatePicker
01042019
17052019

<DatePicker
  label="DatePicker"
  startDate="2019-04-01"
  endDate="2019-05-17"
  range
  showInput
  onChange={({ startDate, endDate }) => {
    console.log('onChange', startDate, endDate)
  }}
  onSubmit={({ startDate, endDate }) => {
    console.log('onSubmit', startDate, endDate)
  }}
  onCancel={({ startDate, endDate }) => {
    console.log('onCancel', startDate, endDate)
  }}
  onBlur={({ startDate, endDate }) => {
    console.log('onBlurComplete', startDate, endDate)
  }}
  shortcuts={[
    {
      title: 'Set date period',
      startDate: '1969-07-15',
      endDate: '1969-08-15',
    },
    {
      title: 'Today',
      startDate: new Date(),
    },
    {
      title: 'This week',
      startDate: startOfWeek(new Date()),
      endDate: lastDayOfWeek(new Date()),
    },
    {
      closeOnSelect: true,
      title: 'This month',
      startDate: startOfMonth(new Date()),
      endDate: lastDayOfMonth(new Date()),
    },
    {
      title: 'Relative +3 days',
      // @ts-expect-error -- strictFunctionTypes
      startDate: ({ startDate }) => startDate || new Date(),
      // @ts-expect-error -- strictFunctionTypes
      endDate: ({ endDate }) => addDays(endDate || new Date(), 3),
    },
  ]}
/>

Default DatePicker#

DatePicker
05052019

<DatePicker
  label="DatePicker"
  date="2019-05-05"
  returnFormat="dd-MM-yyyy"
  onChange={({ date }) => {
    console.log('onChange', date)
  }}
  onOpen={({ date }) => {
    console.log('onOpen', date)
  }}
  onBlur={({ startDate, endDate }) => {
    console.log('onBlur', startDate, endDate)
  }}
/>

Default DatePicker with Input#

DatePicker
10092026

<DatePicker
  label="DatePicker"
  date={new Date()}
  showInput
  showCancelButton
  showResetButton
  onChange={({ date }) => {
    console.log('onChange', date)
  }}
  onCancel={({ date }) => {
    console.log('onCancel', date)
  }}
  onBlur={({ date }) => {
    console.log('onBlur', date)
  }}
/>

Hidden Nav:#

DatePicker
05052022

<DatePicker
  label="DatePicker"
  date="2022/05/05"
  minDate="2022/05/01"
  maxDate="2022/05/17"
  dateFormat="yyyy/MM/dd"
  returnFormat="dd/MM/yyyy"
  hideNavigation
  hideDays
  hideAdjacentMonthDates
  onChange={({ date }) => {
    console.log('onChange', date)
  }}
  onClose={({ date }) => {
    console.log('onClose', date)
  }}
  onBlur={({ date }) => {
    console.log('onBlur', date)
  }}
/>

Show days in a specific month#

DatePicker
02052019

<DatePicker
  label="DatePicker"
  date="05/02/2019"
  dateFormat="MM/dd/yyyy"
  onlyMonth
/>

With info message#

Please select a valid date
DatePicker
10092026

<DatePicker
  label="DatePicker"
  date={new Date()}
  showInput
  status="Please select a valid date"
  statusState="information"
/>

With suffix#

DatePicker
10092026

<DatePicker
  label="DatePicker"
  date={new Date()}
  showInput
  suffix={<HelpButton title="Modal Title">Modal content</HelpButton>}
/>

Linked DatePickers#

DatePicker
ddmmåååå
ddmmåååå

<DatePicker label="DatePicker" range link showInput />

Year navigation#

ddmmåååå

<DatePicker showInput yearNavigation />

DatePicker with error status (no input)#

Please select a valid date
DatePicker
05052019

<DatePicker
  label="DatePicker"
  date="2019-05-05"
  hideNavigation
  status="Please select a valid date"
/>

DatePicker with error#

Status message with HTML inside
DatePicker
05052019

<DatePicker
  label="DatePicker"
  date="2019-05-05"
  showInput
  showSubmitButton
  status={
    <span>
      Status message with <b>HTML</b> inside
    </span>
  }
/>

DatePicker with error status#

DatePicker
10092026

<DatePicker
  label="DatePicker"
  date={new Date()}
  hideNavigation
  status="error"
/>

Inline DatePicker#

mai 2019
juni 2019

<DatePicker inline range startDate="2019-05-05" endDate="2019-06-05" />
Suggest an edit